6 package eu.mihosoft.vrl.v3d;
8 import java.util.ArrayList;
9 import java.util.Collections;
10 import java.util.List;
11 import java.util.Objects;
12 import java.util.Optional;
13 import java.util.stream.Collectors;
14 import java.util.stream.Stream;
15 import eu.mihosoft.vrl.v3d.ext.org.poly2tri.PolygonUtil;
83 List<Edge> result =
new ArrayList<>();
85 for (
int i = 0; i < poly.
vertices.size(); i++) {
101 return edges.stream().map(e -> e.p1).collect(Collectors.toList());
110 public static List<Vector3d>
toPoints(List<Edge> edges) {
111 return edges.stream().map(e -> e.p1.pos).collect(Collectors.toList());
127 p.
vertices.stream().forEachOrdered((vertex) -> {
147 List<Vector3d> boundaryPath =
new ArrayList<>();
149 boolean[] used =
new boolean[boundaryEdges.size()];
150 Edge edge = boundaryEdges.get(0);
153 Edge finalEdge = edge;
155 boundaryPath.add(finalEdge.
p1.
pos);
157 int nextEdgeIndex = boundaryEdges.indexOf(boundaryEdges.stream().
158 filter(e -> finalEdge.
p2.
equals(e.p1)).findFirst().get());
160 if (used[nextEdgeIndex]) {
165 edge = boundaryEdges.get(nextEdgeIndex);
167 used[nextEdgeIndex] =
true;
170 List<Polygon> result =
new ArrayList<>();
172 System.out.println(
"#bnd-path-length: " + boundaryPath.size());
174 result.add(
toPolygon(boundaryPath, plane));
184 private static class Node<T> {
190 private final List<Node> children =
new ArrayList<>();
193 private final int index;
196 private final T value;
199 private boolean isHole;
207 public Node(
int index, T value) {
218 public void addChild(
int index, T value) {
219 children.add(
new Node(index, value));
227 public List<Node> getChildren() {
228 return this.children;
236 public Node getParent() {
245 public int getIndex() {
254 public T getValue() {
264 hash = 67 * hash + this.index;
272 public boolean equals(Object obj) {
276 if (getClass() != obj.getClass()) {
279 final Node<?> other = (Node<?>) obj;
280 if (this.index != other.index) {
291 public int distanceToRoot() {
294 Node pNode = getParent();
296 while (pNode !=
null) {
309 public boolean isIsHole() {
318 public void setIsHole(
boolean isHole) {
319 this.isHole = isHole;
336 map(p -> p.clone()).collect(Collectors.toList());
338 List<List<Integer>> parents =
new ArrayList<>();
339 boolean[] isHole =
new boolean[result.size()];
341 for (
int i = 0; i < result.size(); i++) {
343 List<Integer> parentsOfI =
new ArrayList<>();
344 parents.add(parentsOfI);
345 for (
int j = 0; j < result.size(); j++) {
348 if (
p2.contains(
p1)) {
353 isHole[i] = parentsOfI.size() % 2 != 0;
356 int[] parent =
new int[result.size()];
358 for (
int i = 0; i < parent.length; i++) {
362 for (
int i = 0; i < parents.size(); i++) {
363 List<Integer> par = parents.get(i);
367 for (
int pIndex : par) {
369 int pSize = parents.get(pIndex).size();
377 parent[i] = maxIndex;
379 if (!isHole[maxIndex] && isHole[i]) {
383 Optional<List<Polygon>> holesOpt = result.get(maxIndex).
386 if (holesOpt.isPresent()) {
387 holes = holesOpt.get();
389 holes =
new ArrayList<>();
390 result.get(maxIndex).getStorage().
394 holes.add(result.get(i));
408 List<Polygon> result =
new ArrayList<>();
410 boolean[] used =
new boolean[boundaryEdges.size()];
412 Edge edge = boundaryEdges.get(startIndex);
413 used[startIndex] =
true;
417 while (startIndex > 0) {
418 List<Vector3d> boundaryPath =
new ArrayList<>();
421 Edge finalEdge = edge;
423 boundaryPath.add(finalEdge.
p1.
pos);
427 Optional<Edge> nextEdgeResult = boundaryEdges.stream().
428 filter(e -> finalEdge.
p2.
equals(e.p1)).findFirst();
430 if (!nextEdgeResult.isPresent()) {
436 Edge nextEdge = nextEdgeResult.get();
438 int nextEdgeIndex = boundaryEdges.indexOf(nextEdge);
440 if (used[nextEdgeIndex]) {
446 used[nextEdgeIndex] =
true;
449 if (boundaryPath.size() < 3) {
456 if (startIndex > 0) {
457 edge = boundaryEdges.get(startIndex);
458 used[startIndex] =
true;
475 for (
int i = 0; i < usage.length; i++) {
476 if (usage[i] ==
false) {
493 List<Vector3d> boundaryPath =
new ArrayList<>();
495 boolean[] used =
new boolean[boundaryEdges.size()];
496 Edge edge = boundaryEdges.get(0);
499 Edge finalEdge = edge;
501 boundaryPath.add(finalEdge.
p1.
pos);
503 int nextEdgeIndex = boundaryEdges.indexOf(boundaryEdges.stream().
504 filter(e -> finalEdge.
p2.
equals(e.p1)).findFirst().get());
506 if (used[nextEdgeIndex]) {
511 edge = boundaryEdges.get(nextEdgeIndex);
513 used[nextEdgeIndex] =
true;
516 List<Polygon> result =
new ArrayList<>();
518 System.out.println(
"#bnd-path-length: " + boundaryPath.size());
520 result.add(
toPolygon(boundaryPath, plane));
537 double x1 = this.p1.
pos.
x;
538 double x2 = this.p2.
pos.
x;
541 double y1 = this.p1.
pos.
y;
542 double y2 = this.p2.
pos.
y;
545 double z1 = this.p1.
pos.
z;
546 double z2 = this.p2.
pos.
z;
548 double slopeSelfxy = (x1-x2)/(y1-y2);
549 double slopeSelfxz = (x1-x2)/(z1-z2);
550 double slopeSelfyz = (y1-y2)/(z1-z2);
553 double slopeTestxy = (x-x2)/(y-y2);
554 double slopeTestxz = (x-x2)/(z-z2);
555 double slopeTestyz = (y-y2)/(z-z2);
558 return Math.abs(slopeSelfxy - slopeTestxy) < TOL &&
559 Math.abs(slopeSelfxz - slopeTestxz) < TOL&&
560 Math.abs(slopeSelfyz - slopeTestyz) < TOL;
573 double x1 = this.p1.
pos.
x;
574 double x2 = this.p2.
pos.
x;
577 double y1 = this.p1.
pos.
y;
578 double y2 = this.p2.
pos.
y;
581 double z1 = this.p1.
pos.
z;
582 double z2 = this.p2.
pos.
z;
584 double AB = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) + (z2 - z1) * (z2 - z1));
585 double AP = Math.sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1) + (z - z1) * (z - z1));
586 double PB = Math.sqrt((x2 - x) * (x2 - x) + (y2 - y) * (y2 - y) + (z2 - z) * (z2 - z));
588 return Math.abs(AB - (AP + PB)) < TOL;
608 hash = 71 * hash + Objects.hashCode(this.p1);
609 hash = 71 * hash + Objects.hashCode(this.p2);
621 if (getClass() != obj.getClass()) {
631 if (!(Objects.equals(
this.p1, other.
p1) || Objects.equals(
this.p2, other.
p1))) {
634 if (!(Objects.equals(
this.p2, other.
p2) || Objects.equals(
this.p1, other.
p2))) {
647 return "[[" + this.p1.
getX() +
", " + this.p1.
getY() +
", " + this.p1.
getZ() +
"]" +
648 ", [" + this.p2.
getX() +
", " + this.p2.
getY() +
", " + this.p2.
getZ() +
"]]";
675 double n = 1 - cos * cos;
679 return Optional.empty();
683 final double norm2This = thisDelta.magnitudeSq();
686 final double norm2E = eDelta.magnitudeSq();
701 return Optional.of(
p1.
pos);
703 return Optional.of(
p2.
pos);
707 return Optional.of(closestP);
722 if (!closestPOpt.isPresent()) {
724 return Optional.empty();
727 Vector3d closestP = closestPOpt.get();
733 return Optional.empty();
744 List<Polygon> result =
new ArrayList<>();
760 List<Edge> edges =
new ArrayList<>();
762 Stream<Polygon> pStream;
764 if (planeGroup.size() > 200) {
765 pStream = planeGroup.parallelStream();
767 pStream = planeGroup.stream();
771 edges.addAll(pEdges);
774 Stream<Edge> edgeStream;
776 if (edges.size() > 200) {
777 edgeStream = edges.parallelStream();
779 edgeStream = edges.stream();
783 List<Edge> potentialBoundaryEdges =
new ArrayList<>();
784 edgeStream.forEachOrdered((e) -> {
785 int count = Collections.frequency(edges, e);
787 potentialBoundaryEdges.add(e);
795 Stream<Edge> bndEdgeStream;
797 if (potentialBoundaryEdges.size() > 200) {
798 bndEdgeStream = potentialBoundaryEdges.parallelStream();
800 bndEdgeStream = potentialBoundaryEdges.stream();
803 List<Edge> realBndEdges = bndEdgeStream.
804 filter(be -> edges.stream().filter(
806 ).count() == 0).collect(Collectors.toList());
822 List<Polygon> planeGroup) {
827 System.out.println(
"polygons: " + polygons.size());
829 List<Polygon> result =
new ArrayList<>(polygons.size());
833 Optional<List<Polygon>> holesOfPresult
837 if (!holesOfPresult.isPresent()) {
863 if (sharedEndPoints) {
877 List<List<Polygon>> planeGroups =
new ArrayList<>();
878 boolean[] used =
new boolean[polygons.size()];
879 System.out.println(
"#polys: " + polygons.size());
880 for (
int pOuterI = 0; pOuterI < polygons.size(); pOuterI++) {
886 Polygon pOuter = polygons.get(pOuterI);
888 List<Polygon> otherPolysInPlane =
new ArrayList<>();
890 otherPolysInPlane.add(pOuter);
892 for (
int pInnerI = 0; pInnerI < polygons.size(); pInnerI++) {
894 Polygon pInner = polygons.get(pInnerI);
896 if (pOuter.equals(pInner)) {
903 double angle = nOuter.
angle(nInner);
907 otherPolysInPlane.add(pInner);
908 used[pInnerI] =
true;
909 System.out.println(
"used: " + pOuterI +
" -> " + pInnerI);
913 if (!otherPolysInPlane.isEmpty()) {
914 planeGroups.add(otherPolysInPlane);
List< Polygon > getPolygons()
boolean isThisPointOneOfMine(Vertex test)
static int nextUnused(boolean[] usage)
boolean contains(Vector3d p)
static List< Polygon > toPolygons(List< Edge > boundaryEdges, Plane plane)
static boolean falseBoundaryEdgeSharedWithOtherEdge(Edge fbe, Edge e)
boolean colinear(Vector3d p)
Optional< Vector3d > getClosestPoint(Edge e)
static Polygon toPolygon(List< Vector3d > points, Plane plane)
Edge(Vertex p1, Vertex p2)
static List< List< Polygon > > searchPlaneGroups(List< Polygon > polygons)
static List< Vertex > toVertices(List< Edge > edges)
boolean contains(Vector3d p, double TOL)
static List< Edge > fromPolygon(Polygon poly)
static List< Polygon > _toPolygons(List< Edge > boundaryEdges, Plane plane)
boolean colinear(Vector3d p, double TOL)
static List< Polygon > boundaryPaths(List< Edge > boundaryEdges)
static final String KEY_POLYGON_HOLES
static List< Vector3d > toPoints(List< Edge > edges)
static List< Edge > boundaryEdgesOfPlaneGroup(List< Polygon > planeGroup)
static List< Polygon > boundaryPolygonsOfPlaneGroup(List< Polygon > planeGroup)
boolean equals(Object obj)
Optional< Vector3d > getIntersection(Edge e)
static List< Polygon > boundaryPolygons(CSG csg)
static List< Polygon > boundaryPathsWithHoles(List< Polygon > boundaryPaths)
static final double EPSILON
static final double EPSILON_Point
final List< Vertex > vertices
static Polygon fromPoints(List< Vector3d > points, PropertyStorage shared)
boolean equals(Object obj)
Vector3d plus(Vector3d v)
static Vector3d y(double y)
Vector3d minus(Vector3d v)
static Vector3d z(double z)
boolean test(Object obj, double epsilon)
static Vector3d x(double x)
boolean equals(Object obj)
static List< eu.mihosoft.vrl.v3d.Polygon > concaveToConvex(eu.mihosoft.vrl.v3d.Polygon incoming)