2727 */
2828final class ComponentTree implements Component2D {
2929
30- private static final Comparator <Component2D > XComparator =
30+ private static final Comparator <Component2D > X_COMPARATOR =
3131 Comparator .comparingDouble (Component2D ::getMinX ).thenComparingDouble (Component2D ::getMaxX );
3232
33- private static final Comparator <Component2D > YComparator =
33+ private static final Comparator <Component2D > Y_COMPARATOR =
3434 Comparator .comparingDouble (Component2D ::getMinY ).thenComparingDouble (Component2D ::getMaxY );
3535
36+ private static final boolean ROOT_SPLITX = false ;
37+
3638 /** minimum Y of this geometry's bounding box area */
3739 private double minY ;
3840
@@ -48,23 +50,18 @@ final class ComponentTree implements Component2D {
4850 // child components, or null. Note internal nodes might mot have
4951 // a consistent bounding box. Internal nodes should not be accessed
5052 // outside if this class.
51- private Component2D left ;
52- private Component2D right ;
53-
54- /** which dimension was this node split on */
55- // TODO: its implicit based on level, but boolean keeps code simple
56- private final boolean splitX ;
53+ private ComponentTree left ;
54+ private ComponentTree right ;
5755
5856 /** root node of edge tree */
5957 private final Component2D component ;
6058
61- private ComponentTree (Component2D component , boolean splitX ) {
59+ private ComponentTree (Component2D component ) {
6260 this .minY = component .getMinY ();
6361 this .maxY = component .getMaxY ();
6462 this .minX = component .getMinX ();
6563 this .maxX = component .getMaxX ();
6664 this .component = component ;
67- this .splitX = splitX ;
6865 }
6966
7067 @ Override
@@ -89,19 +86,23 @@ public double getMaxY() {
8986
9087 @ Override
9188 public boolean contains (double x , double y ) {
89+ return contains (x , y , ROOT_SPLITX );
90+ }
91+
92+ private boolean contains (double x , double y , boolean splitX ) {
9293 if (y <= this .maxY && x <= this .maxX ) {
9394 if (component .contains (x , y )) {
9495 return true ;
9596 }
9697 if (left != null ) {
97- if (left .contains (x , y )) {
98+ if (left .contains (x , y , ! splitX )) {
9899 return true ;
99100 }
100101 }
101102 if (right != null
102103 && ((splitX == false && y >= this .component .getMinY ())
103104 || (splitX && x >= this .component .getMinX ()))) {
104- return right .contains (x , y );
105+ return right .contains (x , y , ! splitX );
105106 }
106107 }
107108 return false ;
@@ -117,19 +118,32 @@ public boolean intersectsLine(
117118 double aY ,
118119 double bX ,
119120 double bY ) {
121+ return intersectsLine (minX , maxX , minY , maxY , aX , aY , bX , bY , ROOT_SPLITX );
122+ }
123+
124+ private boolean intersectsLine (
125+ double minX ,
126+ double maxX ,
127+ double minY ,
128+ double maxY ,
129+ double aX ,
130+ double aY ,
131+ double bX ,
132+ double bY ,
133+ boolean splitX ) {
120134 if (minY <= this .maxY && minX <= this .maxX ) {
121135 if (component .intersectsLine (minX , maxX , minY , maxY , aX , aY , bX , bY )) {
122136 return true ;
123137 }
124138 if (left != null ) {
125- if (left .intersectsLine (minX , maxX , minY , maxY , aX , aY , bX , bY )) {
139+ if (left .intersectsLine (minX , maxX , minY , maxY , aX , aY , bX , bY , ! splitX )) {
126140 return true ;
127141 }
128142 }
129143 if (right != null
130144 && ((splitX == false && maxY >= this .component .getMinY ())
131145 || (splitX && maxX >= this .component .getMinX ()))) {
132- return right .intersectsLine (minX , maxX , minY , maxY , aX , aY , bX , bY );
146+ return right .intersectsLine (minX , maxX , minY , maxY , aX , aY , bX , bY , ! splitX );
133147 }
134148 }
135149 return false ;
@@ -147,19 +161,34 @@ public boolean intersectsTriangle(
147161 double bY ,
148162 double cX ,
149163 double cY ) {
164+ return intersectsTriangle (minX , maxX , minY , maxY , aX , aY , bX , bY , cX , cY , ROOT_SPLITX );
165+ }
166+
167+ private boolean intersectsTriangle (
168+ double minX ,
169+ double maxX ,
170+ double minY ,
171+ double maxY ,
172+ double aX ,
173+ double aY ,
174+ double bX ,
175+ double bY ,
176+ double cX ,
177+ double cY ,
178+ boolean splitX ) {
150179 if (minY <= this .maxY && minX <= this .maxX ) {
151180 if (component .intersectsTriangle (minX , maxX , minY , maxY , aX , aY , bX , bY , cX , cY )) {
152181 return true ;
153182 }
154183 if (left != null ) {
155- if (left .intersectsTriangle (minX , maxX , minY , maxY , aX , aY , bX , bY , cX , cY )) {
184+ if (left .intersectsTriangle (minX , maxX , minY , maxY , aX , aY , bX , bY , cX , cY , ! splitX )) {
156185 return true ;
157186 }
158187 }
159188 if (right != null
160189 && ((splitX == false && maxY >= this .component .getMinY ())
161190 || (splitX && maxX >= this .component .getMinX ()))) {
162- return right .intersectsTriangle (minX , maxX , minY , maxY , aX , aY , bX , bY , cX , cY );
191+ return right .intersectsTriangle (minX , maxX , minY , maxY , aX , aY , bX , bY , cX , cY , ! splitX );
163192 }
164193 }
165194 return false ;
@@ -175,19 +204,32 @@ public boolean containsLine(
175204 double aY ,
176205 double bX ,
177206 double bY ) {
207+ return containsLine (minX , maxX , minY , maxY , aX , aY , bX , bY , ROOT_SPLITX );
208+ }
209+
210+ private boolean containsLine (
211+ double minX ,
212+ double maxX ,
213+ double minY ,
214+ double maxY ,
215+ double aX ,
216+ double aY ,
217+ double bX ,
218+ double bY ,
219+ boolean splitX ) {
178220 if (minY <= this .maxY && minX <= this .maxX ) {
179221 if (component .containsLine (minX , maxX , minY , maxY , aX , aY , bX , bY )) {
180222 return true ;
181223 }
182224 if (left != null ) {
183- if (left .containsLine (minX , maxX , minY , maxY , aX , aY , bX , bY )) {
225+ if (left .containsLine (minX , maxX , minY , maxY , aX , aY , bX , bY , ! splitX )) {
184226 return true ;
185227 }
186228 }
187229 if (right != null
188230 && ((splitX == false && maxY >= this .component .getMinY ())
189231 || (splitX && maxX >= this .component .getMinX ()))) {
190- return right .containsLine (minX , maxX , minY , maxY , aX , aY , bX , bY );
232+ return right .containsLine (minX , maxX , minY , maxY , aX , aY , bX , bY , ! splitX );
191233 }
192234 }
193235 return false ;
@@ -205,19 +247,34 @@ public boolean containsTriangle(
205247 double bY ,
206248 double cX ,
207249 double cY ) {
250+ return containsTriangle (minX , maxX , minY , maxY , aX , aY , bX , bY , cX , cY , ROOT_SPLITX );
251+ }
252+
253+ private boolean containsTriangle (
254+ double minX ,
255+ double maxX ,
256+ double minY ,
257+ double maxY ,
258+ double aX ,
259+ double aY ,
260+ double bX ,
261+ double bY ,
262+ double cX ,
263+ double cY ,
264+ boolean splitX ) {
208265 if (minY <= this .maxY && minX <= this .maxX ) {
209266 if (component .containsTriangle (minX , maxX , minY , maxY , aX , aY , bX , bY , cX , cY )) {
210267 return true ;
211268 }
212269 if (left != null ) {
213- if (left .containsTriangle (minX , maxX , minY , maxY , aX , aY , bX , bY , cX , cY )) {
270+ if (left .containsTriangle (minX , maxX , minY , maxY , aX , aY , bX , bY , cX , cY , ! splitX )) {
214271 return true ;
215272 }
216273 }
217274 if (right != null
218275 && ((splitX == false && maxY >= this .component .getMinY ())
219276 || (splitX && maxX >= this .component .getMinX ()))) {
220- return right .containsTriangle (minX , maxX , minY , maxY , aX , aY , bX , bY , cX , cY );
277+ return right .containsTriangle (minX , maxX , minY , maxY , aX , aY , bX , bY , cX , cY , ! splitX );
221278 }
222279 }
223280 return false ;
@@ -274,21 +331,25 @@ public WithinRelation withinTriangle(
274331
275332 @ Override
276333 public Relation relate (double minX , double maxX , double minY , double maxY ) {
334+ return relate (minX , maxX , minY , maxY , ROOT_SPLITX );
335+ }
336+
337+ private Relation relate (double minX , double maxX , double minY , double maxY , boolean splitX ) {
277338 if (minY <= this .maxY && minX <= this .maxX ) {
278339 Relation relation = component .relate (minX , maxX , minY , maxY );
279340 if (relation != Relation .CELL_OUTSIDE_QUERY ) {
280341 return relation ;
281342 }
282343 if (left != null ) {
283- relation = left .relate (minX , maxX , minY , maxY );
344+ relation = left .relate (minX , maxX , minY , maxY , ! splitX );
284345 if (relation != Relation .CELL_OUTSIDE_QUERY ) {
285346 return relation ;
286347 }
287348 }
288349 if (right != null
289350 && ((splitX == false && maxY >= this .component .getMinY ())
290351 || (splitX && maxX >= this .component .getMinX ()))) {
291- relation = right .relate (minX , maxX , minY , maxY );
352+ relation = right .relate (minX , maxX , minY , maxY , ! splitX );
292353 return relation ;
293354 }
294355 }
@@ -300,7 +361,7 @@ static Component2D create(Component2D[] components) {
300361 if (components .length == 1 ) {
301362 return components [0 ];
302363 }
303- ComponentTree root = createTree (components , 0 , components .length - 1 , false );
364+ ComponentTree root = createTree (components , 0 , components .length - 1 , ROOT_SPLITX );
304365 // pull up min values for the root node so it contains a consistent bounding box
305366 for (Component2D component : components ) {
306367 root .minY = Math .min (root .minY , component .getMinY ());
@@ -318,12 +379,12 @@ private static ComponentTree createTree(
318379 final int mid = (low + high ) >>> 1 ;
319380 if (low < high ) {
320381 if (splitX ) {
321- ArrayUtil .select (components , low , high + 1 , mid , XComparator );
382+ ArrayUtil .select (components , low , high + 1 , mid , X_COMPARATOR );
322383 } else {
323- ArrayUtil .select (components , low , high + 1 , mid , YComparator );
384+ ArrayUtil .select (components , low , high + 1 , mid , Y_COMPARATOR );
324385 }
325386 }
326- ComponentTree newNode = new ComponentTree (components [mid ], splitX );
387+ ComponentTree newNode = new ComponentTree (components [mid ]);
327388 // find children
328389 newNode .left = createTree (components , low , mid - 1 , !splitX );
329390 newNode .right = createTree (components , mid + 1 , high , !splitX );
0 commit comments