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