1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.hipparchus.geometry.spherical.twod;
18
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import org.hipparchus.geometry.partitioning.BSPTree;
23 import org.hipparchus.geometry.partitioning.BSPTreeVisitor;
24 import org.hipparchus.geometry.partitioning.BoundaryAttribute;
25 import org.hipparchus.geometry.spherical.oned.Arc;
26 import org.hipparchus.geometry.spherical.oned.ArcsSet;
27 import org.hipparchus.geometry.spherical.oned.S1Point;
28 import org.hipparchus.util.FastMath;
29
30
31
32
33 class EdgesWithNodeInfoBuilder implements BSPTreeVisitor<Sphere2D, S2Point, Circle, SubCircle> {
34
35
36 private final double tolerance;
37
38
39 private final List<EdgeWithNodeInfo> edges;
40
41
42
43
44 EdgesWithNodeInfoBuilder(final double tolerance) {
45 this.tolerance = tolerance;
46 this.edges = new ArrayList<>();
47 }
48
49
50 @Override
51 public Order visitOrder(final BSPTree<Sphere2D, S2Point, Circle, SubCircle> node) {
52 return Order.MINUS_SUB_PLUS;
53 }
54
55
56 @Override
57 public void visitInternalNode(final BSPTree<Sphere2D, S2Point, Circle, SubCircle> node) {
58 @SuppressWarnings("unchecked")
59 final BoundaryAttribute<Sphere2D, S2Point, Circle, SubCircle> attribute =
60 (BoundaryAttribute<Sphere2D, S2Point, Circle, SubCircle>) node.getAttribute();
61 final Iterable<BSPTree<Sphere2D, S2Point, Circle, SubCircle>> splitters = attribute.getSplitters();
62 if (attribute.getPlusOutside() != null) {
63 addContribution(attribute.getPlusOutside(), node, splitters, false);
64 }
65 if (attribute.getPlusInside() != null) {
66 addContribution(attribute.getPlusInside(), node, splitters, true);
67 }
68 }
69
70
71 @Override
72 public void visitLeafNode(final BSPTree<Sphere2D, S2Point, Circle, SubCircle> node) {
73 }
74
75
76
77
78
79
80
81 private void addContribution(final SubCircle sub, final BSPTree<Sphere2D, S2Point, Circle, SubCircle> node,
82 final Iterable<BSPTree<Sphere2D, S2Point, Circle, SubCircle>> splitters,
83 final boolean reversed) {
84 final Circle circle = sub.getHyperplane();
85 final List<Arc> arcs = ((ArcsSet) sub.getRemainingRegion()).asList();
86 for (final Arc a : arcs) {
87
88
89 final Vertex startS = new Vertex(circle.toSpace(new S1Point(a.getInf())));
90 final Vertex endS = new Vertex(circle.toSpace(new S1Point(a.getSup())));
91
92
93 final BSPTree<Sphere2D, S2Point, Circle, SubCircle> startN = selectClosest(startS.getLocation(), splitters);
94 final BSPTree<Sphere2D, S2Point, Circle, SubCircle> endN = selectClosest(endS.getLocation(), splitters);
95
96 if (reversed) {
97 edges.add(new EdgeWithNodeInfo(endS, startS, a.getSize(), circle.getReverse(), node, endN, startN));
98 } else {
99 edges.add(new EdgeWithNodeInfo(startS, endS, a.getSize(), circle, node, startN, endN));
100 }
101
102 }
103 }
104
105
106
107
108
109
110 private BSPTree<Sphere2D, S2Point, Circle, SubCircle>
111 selectClosest(final S2Point point, final Iterable<BSPTree<Sphere2D, S2Point, Circle, SubCircle>> candidates) {
112
113 if (point == null) {
114 return null;
115 }
116
117 BSPTree<Sphere2D, S2Point, Circle, SubCircle> selected = null;
118
119 double min = Double.POSITIVE_INFINITY;
120 for (final BSPTree<Sphere2D, S2Point, Circle, SubCircle> node : candidates) {
121 final double distance = FastMath.abs(node.getCut().getHyperplane().getOffset(point));
122 if (distance < min) {
123 selected = node;
124 min = distance;
125 }
126 }
127
128 return min <= tolerance ? selected : null;
129
130 }
131
132
133
134
135 public List<EdgeWithNodeInfo> getEdges() {
136 return edges;
137 }
138
139 }