JavaCAD
Node.java
Go to the documentation of this file.
1 
34 package eu.mihosoft.vrl.v3d;
35 
36 import java.util.ArrayList;
37 import java.util.List;
38 import java.util.stream.Collectors;
39 import java.util.stream.Stream;
40 
41 // TODO: Auto-generated Javadoc
49 final class Node {
50 
54  private List<Polygon> polygons;
58  private Plane plane;
62  private Node front;
66  private Node back;
67 
68  private long maxDepth = -1;
69 
77  public Node(List<Polygon> polygons) {
78  this.polygons = new ArrayList<>();
79  if (polygons != null) {
80  this.build(polygons);
81  }
82  }
83 
87  public Node() {
88  this(null);
89  }
90 
91  /*
92  * (non-Javadoc)
93  *
94  * @see java.lang.Object#clone()
95  */
96  @Override
97  public Node clone() {
98  Node node = new Node();
99  node.plane = this.plane == null ? null : this.plane.clone();
100  node.front = this.front == null ? null : this.front.clone();
101  node.back = this.back == null ? null : this.back.clone();
102 // node.polygons = new ArrayList<>();
103 // polygons.parallelStream().forEach((Polygon p) -> {
104 // node.polygons.add(p.clone());
105 // });
106 
107  Stream<Polygon> polygonStream;
108 
109  if (polygons.size() > 200) {
110  polygonStream = polygons.parallelStream();
111  } else
112  polygonStream = polygons.stream();
113 
114  node.polygons = polygonStream.map(p -> p.clone()).collect(Collectors.toList());
115 
116  return node;
117  }
118 
122  public void invert() {
123 
124  Stream<Polygon> polygonStream;
125 
126  if (polygons.size() > 200) {
127  polygonStream = polygons.parallelStream();
128  } else
129  polygonStream = polygons.stream();
130 
131  polygonStream.forEach((polygon) -> {
132  polygon.flip();
133  });
134 
135  if (this.plane == null && !polygons.isEmpty()) {
136  this.plane = polygons.get(0).plane.clone();
137  } else if (this.plane == null && polygons.isEmpty()) {
138 
139  //System.err.println("Please fix me! I don't know what to do?");
140  throw new RuntimeException("Please fix me! I don't know what to do?");
141  // return;
142  }
143 
144  this.plane.flip();
145 
146  if (this.front != null) {
147  this.front.invert();
148  }
149  if (this.back != null) {
150  this.back.invert();
151  }
152  Node temp = this.front;
153  this.front = this.back;
154  this.back = temp;
155  }
156 
167  private List<Polygon> clipPolygons(List<Polygon> polygons) {
168 
169  if (this.plane == null) {
170  return new ArrayList<>(polygons);
171  }
172 
173  List<Polygon> frontP = new ArrayList<>();
174  List<Polygon> backP = new ArrayList<>();
175 
176  for (Polygon polygon : polygons) {
177  this.plane.splitPolygon(polygon, frontP, backP, frontP, backP);
178  }
179  if (this.front != null) {
180  frontP = this.front.clipPolygons(frontP);
181  }
182  if (this.back != null) {
183  backP = this.back.clipPolygons(backP);
184  } else {
185  backP = new ArrayList<>(0);
186  }
187 
188  frontP.addAll(backP);
189  return frontP;
190  }
191 
192  // Remove all polygons in this BSP tree that are inside the other BSP tree
193  // `bsp`.
202  public void clipTo(Node bsp) {
203  this.polygons = bsp.clipPolygons(this.polygons);
204  if (this.front != null) {
205  this.front.clipTo(bsp);
206  }
207  if (this.back != null) {
208  this.back.clipTo(bsp);
209  }
210  }
211 
217  public List<Polygon> allPolygons() {
218  List<Polygon> localPolygons = new ArrayList<>(this.polygons);
219  if (this.front != null) {
220  localPolygons.addAll(this.front.allPolygons());
221 // polygons = Utils.concat(polygons, this.front.allPolygons());
222  }
223  if (this.back != null) {
224 // polygons = Utils.concat(polygons, this.back.allPolygons());
225  localPolygons.addAll(this.back.allPolygons());
226  }
227 
228  return localPolygons;
229  }
230 
239  public final void build(List<Polygon> polygons) {
240  build(polygons, 0,polygons.size() );
241  }
242 
251  public final void build(List<Polygon> polygons, long depth, long maxDepth) {
252 // if (depth > maxDepth) {
253 // throw new RuntimeException("Impossible Node depth " + depth + " with " + polygons.size() + " remaining max = "+maxDepth );
254 // }
255 // if (depth > 200) {
256 // System.out.println("Node depth " + depth + " with " + polygons.size() + " remaining ");
257 // Plane.setUseDebugger(true);
258 // } else {
259 // Plane.setUseDebugger(false);
260 // }
261 
262  if (polygons.isEmpty()) {
263 
264  return;
265  }
266 
267  if (this.plane == null) {
268  this.plane = polygons.get(0).plane.clone();
269  }
270  //this.polygons.add(polygons.get(0));
271 
272  List<Polygon> frontP = new ArrayList<>();
273  List<Polygon> backP = new ArrayList<>();
274 
275  // parellel version does not work here
276  for(int i=0;i<polygons.size();i++) {
277  this.plane.splitPolygon(polygons.get(i), this.polygons, this.polygons, frontP, backP);
278  }
279  if (frontP.size() > 0) {
280  if (this.front == null) {
281  this.front = new Node();
282  }
283  this.front.build(frontP, depth + 1,maxDepth);
284  }
285  if (backP.size() > 0) {
286  if (this.back == null) {
287  this.back = new Node();
288  }
289  this.back.build(backP, depth + 1,maxDepth);
290  }
291  }
292 }