1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.hipparchus.geometry.partitioning;
23
24 import java.util.HashMap;
25 import java.util.Map;
26
27 import org.hipparchus.geometry.Space;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 public abstract class AbstractSubHyperplane<S extends Space, T extends Space>
43 implements SubHyperplane<S> {
44
45
46 private final Hyperplane<S> hyperplane;
47
48
49 private final Region<T> remainingRegion;
50
51
52
53
54
55 protected AbstractSubHyperplane(final Hyperplane<S> hyperplane,
56 final Region<T> remainingRegion) {
57 this.hyperplane = hyperplane;
58 this.remainingRegion = remainingRegion;
59 }
60
61
62
63
64
65
66 protected abstract AbstractSubHyperplane<S, T> buildNew(Hyperplane<S> hyper,
67 Region<T> remaining);
68
69
70 @Override
71 public AbstractSubHyperplane<S, T> copySelf() {
72 return buildNew(hyperplane.copySelf(), remainingRegion);
73 }
74
75
76
77
78 @Override
79 public Hyperplane<S> getHyperplane() {
80 return hyperplane;
81 }
82
83
84
85
86
87
88
89
90 public Region<T> getRemainingRegion() {
91 return remainingRegion;
92 }
93
94
95 @Override
96 public double getSize() {
97 return remainingRegion.getSize();
98 }
99
100
101 @Override
102 public AbstractSubHyperplane<S, T> reunite(final SubHyperplane<S> other) {
103 @SuppressWarnings("unchecked")
104 AbstractSubHyperplane<S, T> o = (AbstractSubHyperplane<S, T>) other;
105 return buildNew(hyperplane,
106 new RegionFactory<T>().union(remainingRegion, o.remainingRegion));
107 }
108
109
110
111
112
113
114
115
116
117
118
119 public AbstractSubHyperplane<S, T> applyTransform(final Transform<S, T> transform) {
120 final Hyperplane<S> tHyperplane = transform.apply(hyperplane);
121
122
123 final Map<BSPTree<T>, BSPTree<T>> map = new HashMap<>();
124 final BSPTree<T> tTree =
125 recurseTransform(remainingRegion.getTree(false), tHyperplane, transform, map);
126
127
128 for (final Map.Entry<BSPTree<T>, BSPTree<T>> entry : map.entrySet()) {
129 if (entry.getKey().getCut() != null) {
130 @SuppressWarnings("unchecked")
131 BoundaryAttribute<T> original = (BoundaryAttribute<T>) entry.getKey().getAttribute();
132 if (original != null) {
133 @SuppressWarnings("unchecked")
134 BoundaryAttribute<T> transformed = (BoundaryAttribute<T>) entry.getValue().getAttribute();
135 for (final BSPTree<T> splitter : original.getSplitters()) {
136 transformed.getSplitters().add(map.get(splitter));
137 }
138 }
139 }
140 }
141
142 return buildNew(tHyperplane, remainingRegion.buildNew(tTree));
143
144 }
145
146
147
148
149
150
151
152
153 private BSPTree<T> recurseTransform(final BSPTree<T> node,
154 final Hyperplane<S> transformed,
155 final Transform<S, T> transform,
156 final Map<BSPTree<T>, BSPTree<T>> map) {
157
158 final BSPTree<T> transformedNode;
159 if (node.getCut() == null) {
160 transformedNode = new BSPTree<>(node.getAttribute());
161 } else {
162
163 @SuppressWarnings("unchecked")
164 BoundaryAttribute<T> attribute = (BoundaryAttribute<T>) node.getAttribute();
165 if (attribute != null) {
166 final SubHyperplane<T> tPO = (attribute.getPlusOutside() == null) ?
167 null : transform.apply(attribute.getPlusOutside(), hyperplane, transformed);
168 final SubHyperplane<T> tPI = (attribute.getPlusInside() == null) ?
169 null : transform.apply(attribute.getPlusInside(), hyperplane, transformed);
170
171 attribute = new BoundaryAttribute<>(tPO, tPI, new NodesSet<>());
172 }
173
174 transformedNode = new BSPTree<>(transform.apply(node.getCut(), hyperplane, transformed),
175 recurseTransform(node.getPlus(), transformed, transform, map),
176 recurseTransform(node.getMinus(), transformed, transform, map),
177 attribute);
178 }
179
180 map.put(node, transformedNode);
181 return transformedNode;
182
183 }
184
185
186 @Override
187 public abstract SplitSubHyperplane<S> split(Hyperplane<S> hyper);
188
189
190 @Override
191 public boolean isEmpty() {
192 return remainingRegion.isEmpty();
193 }
194
195 }