34 package eu.mihosoft.vrl.v3d;
36 import java.util.ArrayList;
37 import com.piro.bezier.BezierPath;
38 import eu.mihosoft.vrl.v3d.Transform;
39 import eu.mihosoft.vrl.v3d.svg.*;
40 import java.util.Arrays;
41 import java.util.Collections;
42 import java.util.List;
46 import eu.mihosoft.vrl.v3d.ext.org.poly2tri.PolygonUtil;
47 import eu.mihosoft.vrl.v3d.ext.quickhull3d.HullUtil;
68 List<Vector3d> newList =
new ArrayList<>(
points);
82 return monotoneExtrude(dir, polygon1);
86 List<Polygon> newPolygons =
new ArrayList<>();
92 int numvertices = polygon1.
vertices.size();
93 for (
int i = 0; i < numvertices; i++) {
95 int nexti = (i + 1) % numvertices;
102 List<Vector3d> pPoints = Arrays.asList(bottomV2, topV2, topV1, bottomV1);
111 newPolygons.addAll(topPolygons);
127 throw new AssertionError(
"Don't instantiate me!",
null);
142 List<Polygon> newPolygons =
new ArrayList<>();
146 throw new RuntimeException(
"These polygons do not match");
149 int numvertices = polygon1.
vertices.size();
150 for (
int i = 0; i < numvertices; i++) {
152 int nexti = (i + 1) % numvertices;
159 List<Vector3d> pPoints = Arrays.asList(bottomV2, topV2, topV1, bottomV1);
168 newPolygons.addAll(topPolygons);
174 public static ArrayList<CSG>
polygons(eu.mihosoft.vrl.v3d.Polygon polygon1, ArrayList<Transform> transforms) {
175 if (transforms.size() == 1)
178 if (transforms.size() < 2) {
181 ArrayList<CSG> parts =
new ArrayList<>();
184 for (
int i = 0; i < transforms.size() - 1; i++) {
185 CSG tmp =
polygons(polygon1.transformed(transform).transformed(transforms.get(i)),
186 polygon1.transformed(transform).transformed(transforms.get(i + 1)));
193 public static ArrayList<CSG>
polygons(eu.mihosoft.vrl.v3d.Polygon polygon1,
Transform... transformparts) {
195 return polygons(polygon1, (ArrayList<Transform>) Arrays.asList(transformparts));
226 List<Vector3d> result =
new ArrayList<>(
points);
229 Collections.reverse(result);
241 static List<Vector3d> toCW(List<Vector3d>
points) {
243 List<Vector3d> result =
new ArrayList<>(
points);
246 Collections.reverse(result);
263 throw new IllegalArgumentException(
"Only polygons with at least 3 vertices are supported!");
267 int highestLeftVertexIndex = 0;
269 for (
int i = 0; i < polygon.
vertices.size(); i++) {
272 if (v.
pos.
y > highestLeftVertex.
pos.
y) {
273 highestLeftVertex = v;
274 highestLeftVertexIndex = i;
275 }
else if (v.
pos.
y == highestLeftVertex.
pos.
y && v.
pos.
x < highestLeftVertex.
pos.
x) {
276 highestLeftVertex = v;
277 highestLeftVertexIndex = i;
282 int nextVertexIndex = (highestLeftVertexIndex + 1) % polygon.
vertices.size();
283 int prevVertexIndex = highestLeftVertexIndex - 1;
284 if (prevVertexIndex < 0) {
285 prevVertexIndex = polygon.
vertices.size() - 1;
300 selectedVIndex = nextVertexIndex;
302 selectedVIndex = prevVertexIndex;
305 if (selectedVIndex == 0 && highestLeftVertexIndex == polygon.
vertices.size() - 1) {
306 selectedVIndex = polygon.
vertices.size();
309 if (highestLeftVertexIndex == 0 && selectedVIndex == polygon.
vertices.size() - 1) {
310 highestLeftVertexIndex = polygon.
vertices.size();
315 return selectedVIndex > highestLeftVertexIndex;
346 public static CSG byPath(List<List<Vector3d>>
points,
double height,
int resolution) {
348 ArrayList<Vector3d> finalPath =
new ArrayList<>();
350 javax.vecmath.Vector3d t1 =
new javax.vecmath.Vector3d();
351 tr.getInternalMatrix().get(t1);
353 finalPath.add(finalPoint);
367 String pathStringA =
"M " + start.
x +
"," + start.
y;
368 String pathStringB = pathStringA;
370 for (List<Vector3d> sections :
points) {
371 if (sections.size() == 4) {
372 Vector3d controlA = sections.get(1);
373 Vector3d controlB = sections.get(2);
374 Vector3d endPoint = sections.get(3);
387 pathStringA += (
"C " + controlA.
x +
"," + controlA.
y +
" " + controlB.
x +
"," + controlB.
y +
" "
388 + endPoint.
x +
"," + endPoint.
y +
"\n");
389 pathStringB += (
"C " + controlA.
x +
"," + controlA.
z +
" " + controlB.
x +
"," + controlB.
z +
" "
390 + endPoint.
x +
"," + endPoint.
z +
"\n");
395 }
else if (sections.size() == 1) {
397 pathStringA +=
"L " + (double) sections.get(0).
x +
"," + (double) sections.get(0).
y +
"\n";
398 pathStringB +=
"L " + (double) sections.get(0).
x +
"," + (double) sections.get(0).
z +
"\n";
422 path.
parsePathString(
"C " + controlA.
x +
"," + controlA.
y +
" " + controlB.
x +
"," + controlB.
y +
" "
423 + endPoint.
x +
"," + endPoint.
y);
425 path2.
parsePathString(
"C " + controlA.
x +
"," + controlA.
z +
" " + controlB.
x +
"," + controlB.
z +
" "
426 + endPoint.
x +
"," + endPoint.
z);
433 if (parts.size() == 3)
435 if (parts.size() == 2)
436 return bezierToTransforms(parts.get(0), parts.get(0), parts.get(1), parts.get(1), iterations);
437 if (parts.size() == 1)
440 return bezierToTransforms(parts.get(0), parts.get(1), parts.get(2), parts.get(3), iterations);
450 double d = 1.0 / (double) iterations;
451 ArrayList<Transform> p =
new ArrayList<Transform>();
454 double x = pointAStart.
x, y = pointAStart.
y, z = pointBStart.
y;
455 double lastx = x, lasty = y, lastz = z;
458 if (controlA !=
null) {
460 double ydiff = controlA.
y - y;
461 double zdiff = controlA.
z - z;
462 double xdiff = controlA.
x - x;
464 double run = Math.sqrt((ydiff * ydiff) + (xdiff * xdiff));
465 double rotz = 90 - Math.toDegrees(Math.atan2(xdiff, ydiff));
467 double roty = Math.toDegrees(Math.atan2(rise, run));
484 for (
int i = startIndex; i < iterations - 1; i++) {
485 float pathFunction = (float) (((
float) i) / ((float) (iterations - 1)));
499 Vector3d pointAEst = pathA.
eval((
float) (pathFunction + d));
500 Vector3d pointBEst = pathB.
eval((
float) (pathFunction + d));
501 double xest = pointAEst.
x;
502 double yest = pointAEst.
y;
503 double zest = pointBEst.
y;
510 run = Math.sqrt((ydiff * ydiff) + (xdiff * xdiff));
511 rotz = 90 - Math.toDegrees(Math.atan2(xdiff, ydiff));
513 roty = Math.toDegrees(Math.atan2(rise, run));
536 if (controlB !=
null) {
547 run = Math.sqrt((ydiff * ydiff) + (xdiff * xdiff));
548 rotz = 90 - Math.toDegrees(Math.atan2(xdiff, ydiff));
549 roty = Math.toDegrees(Math.atan2(rise, run));
559 Vector3d endPoint,
int iterations) {
560 String startString =
"M " + start.
x +
"," + start.
y +
"\n" +
"C " + controlA.
x +
"," + controlA.
y +
" "
561 + controlB.
x +
"," + controlB.
y +
" " + endPoint.
x +
"," + endPoint.
y;
562 String b =
"M " + start.
x +
"," + start.
z +
"\n" +
"C " + controlA.
x +
"," + controlA.
z +
" " + controlB.
x +
","
563 + controlB.
z +
" " + endPoint.
x +
"," + endPoint.
z;
575 public static ArrayList<CSG>
revolve(
CSG slice,
double radius,
int numSlices) {
576 return revolve(slice, radius, 360.0,
null, numSlices);
580 return revolve(poly, 0, numSlices);
583 public static ArrayList<CSG>
revolve(
Polygon poly,
double radius,
int numSlices) {
584 ArrayList<CSG> parts =
new ArrayList<CSG>();
585 ArrayList<Polygon> slices =
new ArrayList<Polygon>();
587 for (
int i = 0; i < numSlices; i++) {
588 double angle = 360.0 / ((double) numSlices) * ((double) i);
591 for (
int i = 0; i < slices.size(); i++) {
593 if (next == slices.size())
602 public static ArrayList<CSG>
revolve(
CSG slice,
double radius,
double archLen,
int numSlices) {
603 return revolve(slice, radius, archLen,
null, numSlices);
606 public static ArrayList<CSG>
revolve(
CSG slice,
double radius,
double archLen, List<List<Vector3d>>
points,
608 ArrayList<CSG> parts =
new ArrayList<CSG>();
609 double slices = (double) numSlices;
610 double increment = archLen / slices;
611 CSG slicePRofile = slice.
movey(radius);
613 for (
double i = 0; i < (archLen + increment); i += increment) {
614 parts.add(slicePRofile.
rotz(i));
618 for (
int i = 0; i < parts.size(); i++) {
623 for (
int i = 0; i < parts.size() - 1; i++) {
632 public static ArrayList<CSG>
bezier(
CSG slice, ArrayList<Double> controlA, ArrayList<Double> controlB,
633 ArrayList<Double> endPoint,
int numSlices) {
634 ArrayList<CSG> parts =
new ArrayList<CSG>();
636 for (
int i = 0; i < numSlices; i++) {
637 parts.add(0, slice.
clone());
639 return bezier(parts, controlA, controlB, endPoint);
642 public static ArrayList<CSG>
bezier(ArrayList<CSG> s, ArrayList<Double> controlA, ArrayList<Double> controlB,
643 ArrayList<Double> endPoint) {
644 ArrayList<CSG> slice =
moveBezier(s, controlA, controlB, endPoint);
646 for (
int i = 0; i < slice.size() - 1; i++) {
657 public static ArrayList<CSG>
hull(ArrayList<CSG> s, ArrayList<Transform> p) {
658 ArrayList<CSG> slice =
move(s, p);
659 for (
int i = 0; i < slice.size() - 1; i++) {
670 public static ArrayList<CSG>
hull(
CSG c, ArrayList<Transform> p) {
671 ArrayList<CSG> s =
new ArrayList<>();
672 for (
int i = 0; i < p.size(); i++) {
678 public static ArrayList<CSG>
linear(ArrayList<CSG> s, ArrayList<Double> endPoint) {
679 ArrayList<Double> start = (ArrayList<Double>) Arrays.asList(0.0, 0.0, 0.0);
680 return bezier(s, start, endPoint, endPoint);
683 public static ArrayList<CSG>
linear(
CSG s, ArrayList<Double> endPoint,
int numSlices) {
684 ArrayList<Double> start = (ArrayList<Double>) Arrays.asList(0.0, 0.0, 0.0);
686 return bezier(s, start, endPoint, endPoint, numSlices);
689 public static ArrayList<CSG>
move(ArrayList<CSG> slice, ArrayList<Transform> p) {
694 public static ArrayList<CSG>
move(
CSG slice, ArrayList<Transform> p) {
695 return slice.
move(p);
698 public static ArrayList<CSG>
moveBezier(
CSG slice, ArrayList<Double> controlA, ArrayList<Double> controlB,
699 ArrayList<Double> endPoint,
int numSlices) {
703 return move(slice, p);
706 public static ArrayList<CSG>
moveBezier(ArrayList<CSG> slice, ArrayList<Double> controlA,
707 ArrayList<Double> controlB, ArrayList<Double> endPoint) {
709 int numSlices = slice.size();
712 return move(slice, p);
717 return new Vector3d(controlA.get(0), controlA.get(1), controlA.get(2));
722 String zpath =
"C 0,0 " + pointA.
x +
"," + pointA.
y +
" " + pointA.
x +
"," + pointA.
y;
726 return moveBezier(slice, pathA, pathB, numSlices);
733 return move(slice, p);
738 if (!
isCCW(concave)) {
740 List<Vector3d> result =
new ArrayList<>(
points);
741 Collections.reverse(result);
void parsePathString(String d)
Vector3d eval(float interp)
CSG transformed(Transform transform)
CSG rotz(Number degreesToRotate)
CSG move(Number x, Number y, Number z)
static CSG hullAll(CSG... csgs)
CSG movey(Number howFarToMove)
static CSG fromPolygons(List< Polygon > polygons)
static boolean isCCW(Polygon polygon)
static ArrayList< CSG > moveBezier(CSG slice, BezierPath pathA, int numSlices)
static ArrayList< CSG > revolve(Polygon poly, int numSlices)
static ArrayList< Transform > pathToTransforms(List< List< Vector3d >> points, int resolution)
static ArrayList< CSG > bezier(CSG slice, ArrayList< Double > controlA, ArrayList< Double > controlB, ArrayList< Double > endPoint, int numSlices)
static ArrayList< CSG > revolve(CSG slice, double radius, double archLen, int numSlices)
static List< Vector3d > toCCW(List< Vector3d > points)
static ArrayList< CSG > polygons(eu.mihosoft.vrl.v3d.Polygon polygon1, Transform... transformparts)
static ArrayList< CSG > moveBezier(CSG slice, ArrayList< Double > controlA, ArrayList< Double > controlB, ArrayList< Double > endPoint, int numSlices)
static double normalizedX(Vector3d v1, Vector3d v2)
static ArrayList< CSG > revolve(Polygon poly, double radius, int numSlices)
static CSG points(Vector3d dir, Vector3d... points)
static CSG points(Vector3d dir, List< Vector3d > points)
static void setExtrusionEngine(IExtrusion extrusionEngine)
static Polygon toCCW(Polygon concave)
static ArrayList< CSG > moveAlongProfile(CSG object, List< List< Vector3d >> points, int resolution)
static CSG byPath(List< List< Vector3d >> points, double height, int resolution)
static Vector3d fromDouble(ArrayList< Double > controlA)
static ArrayList< CSG > bezier(ArrayList< CSG > s, ArrayList< Double > controlA, ArrayList< Double > controlB, ArrayList< Double > endPoint)
static ArrayList< CSG > moveBezier(ArrayList< CSG > slice, ArrayList< Double > controlA, ArrayList< Double > controlB, ArrayList< Double > endPoint)
static ArrayList< Transform > bezierToTransforms(Vector3d start, Vector3d controlA, Vector3d controlB, Vector3d endPoint, int iterations)
static ArrayList< CSG > linear(CSG s, ArrayList< Double > endPoint, int numSlices)
static ArrayList< CSG > hull(CSG c, ArrayList< Transform > p)
static ArrayList< Transform > bezierToTransforms(Vector3d controlA, Vector3d controlB, Vector3d endPoint, int iterations)
static ArrayList< CSG > move(ArrayList< CSG > slice, ArrayList< Transform > p)
static ArrayList< CSG > revolve(CSG slice, double radius, double archLen, List< List< Vector3d >> points, int numSlices)
static ArrayList< Transform > bezierToTransforms(BezierPath pathA, BezierPath pathB, int iterations, Vector3d controlA, Vector3d controlB)
static ArrayList< CSG > linear(ArrayList< CSG > s, ArrayList< Double > endPoint)
static ArrayList< Transform > bezierToTransforms(List< Vector3d > parts, int iterations)
static IExtrusion extrusionEngine
static ArrayList< CSG > revolve(CSG slice, double radius, int numSlices)
static ArrayList< CSG > move(CSG slice, ArrayList< Transform > p)
static CSG polygons(Polygon polygon1, Polygon polygon2)
static CSG polygons(Polygon polygon1, Number zDistance)
static ArrayList< CSG > polygons(eu.mihosoft.vrl.v3d.Polygon polygon1, ArrayList< Transform > transforms)
static IExtrusion getExtrusionEngine()
static ArrayList< CSG > hull(ArrayList< CSG > s, ArrayList< Transform > p)
static ArrayList< CSG > moveBezier(CSG slice, BezierPath pathA, BezierPath pathB, int iterations)
static CSG byPath(List< List< Vector3d >> points, double height)
final List< Vertex > vertices
List< Vector3d > getPoints()
static Polygon fromPoints(List< Vector3d > points, PropertyStorage shared)
Polygon translated(Vector3d v)
PropertyStorage getStorage()
Polygon transformed(Transform transform)
static final Vector3d X_ONE
static Vector3d y(double y)
Vector3d minus(Vector3d v)
static Vector3d z(double z)
static Vector3d x(double x)
Vector3d dividedBy(double a)
static List< eu.mihosoft.vrl.v3d.Polygon > concaveToConvex(eu.mihosoft.vrl.v3d.Polygon incoming)
static CSG hull(List<?> points)
CSG extrude(Vector3d dir, List< Vector3d > points)