Graphviz 12.0.1~dev.20240716.0800
Loading...
Searching...
No Matches
node.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#include <cgraph/alloc.h>
12#include <stdlib.h>
13#include <inttypes.h>
14#include <label/index.h>
15#include <stdbool.h>
16#include <stddef.h>
17#include <stdint.h>
18#include <stdio.h>
19#include <assert.h>
20#include <label/node.h>
21
22/* Make a new node and initialize to have all branch cells empty.
23*/
25 Node_t *n = gv_alloc(sizeof(Node_t));
26 InitNode(n);
27 return n;
28}
29
30/* Initialize a Node structure.
31*/
33{
34 n->count = 0;
35 n->level = -1;
36 for (size_t i = 0; i < NODECARD; i++)
37 InitBranch(&(n->branch[i]));
38}
39
40/* Initialize one branch cell in a node.
41*/
43{
44 InitRect(&(b->rect));
45 b->child = NULL;
46}
47
48#ifdef RTDEBUG
49/* Print out the data in a node.
50*/
51void PrintNode(Node_t * n)
52{
53 assert(n);
54
55 fprintf(stderr, "node");
56 if (n->level == 0)
57 fprintf(stderr, " LEAF");
58 else if (n->level > 0)
59 fprintf(stderr, " NONLEAF");
60 else
61 fprintf(stderr, " TYPE=?");
62 fprintf(stderr, " level=%d count=%d child address=%p\n",
63 n->level, n->count, n);
64
65 for (size_t i = 0; i < NODECARD; i++) {
66 if (n->branch[i].child != NULL)
67 PrintBranch(i, &n->branch[i]);
68 }
69}
70
71void PrintBranch(int i, Branch_t * b)
72{
73 fprintf(stderr, " child[%d] X%X\n", i, (unsigned int) b->child);
74 PrintRect(&(b->rect));
75}
76#endif
77
78/* Find the smallest rectangle that includes all rectangles in
79** branches of a node.
80*/
82{
83 Rect_t r;
84 assert(n);
85
86 InitRect(&r);
87 bool flag = true;
88 for (size_t i = 0; i < NODECARD; i++)
89 if (n->branch[i].child) {
90 if (flag) {
91 r = n->branch[i].rect;
92 flag = false;
93 } else
94 r = CombineRect(&r, &(n->branch[i].rect));
95 }
96 return r;
97}
98
99/* Pick a branch. Pick the one that will need the smallest increase
100** in area to accommodate the new rectangle. This will result in the
101** least total area for the covering rectangles in the current node.
102** In case of a tie, pick the one which was smaller before, to get
103** the best resolution when searching.
104*/
106{
107 uint64_t bestIncr = 0;
108 uint64_t bestArea = 0;
109 int best=0;
110 bool bestSet = false;
111 assert(r && n);
112
113 for (int i = 0; i < NODECARD; i++) {
114 if (n->branch[i].child) {
115 Rect_t *rr = &n->branch[i].rect;
116 uint64_t area = RectArea(rr);
117 Rect_t rect = CombineRect(r, rr);
118 uint64_t increase = RectArea(&rect) - area;
119 if (!bestSet || increase < bestIncr) {
120 best = i;
121 bestArea = area;
122 bestIncr = increase;
123 bestSet = true;
124 } else if (increase == bestIncr && area < bestArea) {
125 best = i;
126 bestArea = area;
127 bestIncr = increase;
128 }
129# ifdef RTDEBUG
130 fprintf(stderr,
131 "i=%d area before=%" PRIu64 " area after=%" PRIu64 " increase=%" PRIu64
132 "\n", i, area, area + increase, increase);
133# endif
134 }
135 }
136# ifdef RTDEBUG
137 fprintf(stderr, "\tpicked %d\n", best);
138# endif
139 return best;
140}
141
142/* Add a branch to a node. Split the node if necessary.
143** Returns 0 if node not split. Old node updated.
144** Returns 1 if node split, sets *new to address of new node.
145** Old node updated, becomes one of two.
146*/
147int AddBranch(RTree_t * rtp, Branch_t * b, Node_t * n, Node_t ** new)
148{
149 assert(b);
150 assert(n);
151
152 if (n->count < NODECARD) { /* split won't be necessary */
153 size_t i;
154 for (i = 0; i < NODECARD; i++) { /* find empty branch */
155 if (n->branch[i].child == NULL) {
156 n->branch[i] = *b;
157 n->count++;
158 break;
159 }
160 }
161 assert(i < NODECARD);
162 return 0;
163 } else {
164 assert(new);
165 SplitNode(rtp, n, b, new);
166 return 1;
167 }
168}
169
170/* Disconnect a dependent node.
171*/
172void DisconBranch(Node_t * n, int i)
173{
174 assert(n && i >= 0 && i < NODECARD);
175 assert(n->branch[i].child);
176
177 InitBranch(&(n->branch[i]));
178 n->count--;
179}
Memory allocation wrappers that exit on failure.
static void * gv_alloc(size_t size)
Definition alloc.h:47
node NULL
Definition grammar.y:149
#define NODECARD
Definition index.h:43
void InitNode(Node_t *n)
Definition node.c:32
Node_t * RTreeNewNode(void)
Definition node.c:24
int AddBranch(RTree_t *rtp, Branch_t *b, Node_t *n, Node_t **new)
Definition node.c:147
Rect_t NodeCover(Node_t *n)
Definition node.c:81
int PickBranch(Rect_t *r, Node_t *n)
Definition node.c:105
void InitBranch(Branch_t *b)
Definition node.c:42
void DisconBranch(Node_t *n, int i)
Definition node.c:172
void PrintBranch(int, Branch_t *)
void InitRect(Rect_t *r)
Definition rectangle.c:29
Rect_t CombineRect(const Rect_t *r, const Rect_t *rr)
Definition rectangle.c:88
uint64_t RectArea(const Rect_t *r)
Definition rectangle.c:66
void SplitNode(RTree_t *rtp, Node_t *n, Branch_t *b, Node_t **nn)
Definition split.q.c:35
Definition node.h:19
Rect_t rect
Definition node.h:20
struct Node * child
Definition node.h:21
Definition node.h:24
int level
Definition node.h:26
struct Branch branch[NODECARD]
Definition node.h:27
int count
Definition node.h:25
Definition index.h:65