Skip to content

Commit 28979c2

Browse files
committed
Extrusion API improved. This will make extruding along paths much easier to implement.
1 parent 44d50fb commit 28979c2

File tree

2 files changed

+174
-2
lines changed

2 files changed

+174
-2
lines changed

gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
group = eu.mihosoft.vrl.jcsg
2-
version = 0.5.6-SNAPSHOT
2+
version = 0.5.6

src/main/java/eu/mihosoft/jcsg/Extrude.java

+173-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* Extrude.java
33
*
4-
* Copyright 2014-2014 Michael Hoffer <[email protected]>. All rights
4+
* Copyright 2014-2017 Michael Hoffer <[email protected]>. All rights
55
* reserved.
66
*
77
* Redistribution and use in source and binary forms, with or without
@@ -33,6 +33,7 @@
3333
*/
3434
package eu.mihosoft.jcsg;
3535

36+
import eu.mihosoft.vvecmath.Transform;
3637
import eu.mihosoft.vvecmath.Vector3d;
3738
import eu.mihosoft.jcsg.ext.org.poly2tri.PolygonUtil;
3839
import java.util.ArrayList;
@@ -82,6 +83,105 @@ public static CSG points(Vector3d dir, List<Vector3d> points) {
8283

8384
return extrude(dir, Polygon.fromPoints(toCCW(newList)));
8485
}
86+
87+
/**
88+
* Extrudes the specified path (convex or concave polygon without holes or
89+
* intersections, specified in CCW) into the specified direction.
90+
*
91+
* @param dir direction
92+
* @param points path (convex or concave polygon without holes or
93+
* intersections)
94+
*
95+
* @return a list containing the extruded polygon
96+
*/
97+
public static List<Polygon> points(Vector3d dir, boolean top, boolean bottom, Vector3d... points) {
98+
99+
return extrude(dir, Polygon.fromPoints(toCCW(Arrays.asList(points))), top, bottom);
100+
}
101+
102+
/**
103+
* Extrudes the specified path (convex or concave polygon without holes or
104+
* intersections, specified in CCW) into the specified direction.
105+
*
106+
* @param dir direction
107+
* @param points1 path (convex or concave polygon without holes or
108+
* intersections)
109+
* @param points1 path (convex or concave polygon without holes or
110+
* intersections)
111+
*
112+
* @return a list containing the extruded polygon
113+
*/
114+
public static List<Polygon> points(Vector3d dir, boolean top, boolean bottom, List<Vector3d> points1) {
115+
116+
List<Vector3d> newList1 = new ArrayList<>(points1);
117+
118+
return extrude(dir, Polygon.fromPoints(toCCW(newList1)), top, bottom);
119+
}
120+
121+
/**
122+
* Combines two polygons into one CSG object. Polygons p1 and p2 are treated as top and
123+
* bottom of a tube segment with p1 and p2 as the profile. <b>Note:</b> both polygons must have the
124+
* same number of vertices. This method does not guarantee intersection-free CSGs. It is in the
125+
* responsibility of the caller to ensure that the orientation of p1 and p2 allow for
126+
* intersection-free combination of both.
127+
*
128+
* @param p1 first polygon
129+
* @param p2 second polygon
130+
* @return List of polygons
131+
*/
132+
public static CSG combine(Polygon p1, Polygon p2) {
133+
return CSG.fromPolygons(combine(p1,p2,true,true));
134+
}
135+
136+
/**
137+
* Combines two polygons into one CSG object. Polygons p1 and p2 are treated as top and
138+
* bottom of a tube segment with p1 and p2 as the profile. <b>Note:</b> both polygons must have the
139+
* same number of vertices. This method does not guarantee intersection-free CSGs. It is in the
140+
* responsibility of the caller to ensure that the orientation of p1 and p2 allow for
141+
* intersection-free combination of both.
142+
*
143+
* @param p1 first polygon
144+
* @param p2 second polygon
145+
* @param bottom defines whether to close the bottom of the tube
146+
* @param top defines whether to close the top of the tube
147+
* @return List of polygons
148+
*/
149+
public static List<Polygon> combine(Polygon p1, Polygon p2, boolean bottom, boolean top) {
150+
List<Polygon> newPolygons = new ArrayList<>();
151+
152+
if (p1.vertices.size() != p2.vertices.size()) {
153+
throw new RuntimeException("Polygons must have the same number of vertices");
154+
}
155+
156+
int numVertices = p1.vertices.size();
157+
158+
if (bottom) {
159+
newPolygons.add(p1.flipped());
160+
}
161+
162+
for (int i = 0; i < numVertices; i++) {
163+
164+
int nexti = (i + 1) % numVertices;
165+
166+
Vector3d bottomV1 = p1.vertices.get(i).pos;
167+
Vector3d topV1 = p2.vertices.get(i).pos;
168+
Vector3d bottomV2 = p1.vertices.get(nexti).pos;
169+
Vector3d topV2 = p2.vertices.get(nexti).pos;
170+
171+
List<Vector3d> pPoints;
172+
173+
pPoints = Arrays.asList(bottomV2, topV2, topV1);
174+
newPolygons.add(Polygon.fromPoints(pPoints, p1.getStorage()));
175+
pPoints = Arrays.asList(bottomV2, topV1, bottomV1);
176+
newPolygons.add(Polygon.fromPoints(pPoints, p1.getStorage()));
177+
}
178+
179+
if (top) {
180+
newPolygons.add(p2);
181+
}
182+
183+
return newPolygons;
184+
}
85185

86186
private static CSG extrude(Vector3d dir, Polygon polygon1) {
87187
List<Polygon> newPolygons = new ArrayList<>();
@@ -118,6 +218,78 @@ private static CSG extrude(Vector3d dir, Polygon polygon1) {
118218

119219
}
120220

221+
222+
private static List<Polygon> extrude(Vector3d dir, Polygon polygon1, boolean top, boolean bottom) {
223+
List<Polygon> newPolygons = new ArrayList<>();
224+
225+
226+
if (bottom) {
227+
newPolygons.addAll(PolygonUtil.concaveToConvex(polygon1));
228+
}
229+
230+
Polygon polygon2 = polygon1.translated(dir);
231+
232+
Transform rot = Transform.unity();
233+
234+
Vector3d a = polygon2.plane.getNormal().normalized();
235+
Vector3d b = dir.normalized();
236+
237+
Vector3d c = a.crossed(b);
238+
239+
double l = c.magnitude(); // sine of angle
240+
241+
if (l > 1e-9) {
242+
243+
Vector3d axis = c.times(1.0 / l);
244+
double angle = a.angle(b);
245+
246+
double sx = 0;
247+
double sy = 0;
248+
double sz = 0;
249+
250+
int n = polygon2.vertices.size();
251+
252+
for (Vertex v : polygon2.vertices) {
253+
sx += v.pos.x();
254+
sy += v.pos.y();
255+
sz += v.pos.z();
256+
}
257+
258+
Vector3d center = Vector3d.xyz(sx / n, sy / n, sz / n);
259+
260+
rot = rot.rot(center, axis, angle * Math.PI / 180.0);
261+
262+
for (Vertex v : polygon2.vertices) {
263+
v.pos = rot.transform(v.pos);
264+
}
265+
}
266+
267+
int numvertices = polygon1.vertices.size();
268+
for (int i = 0; i < numvertices; i++) {
269+
270+
int nexti = (i + 1) % numvertices;
271+
272+
Vector3d bottomV1 = polygon1.vertices.get(i).pos;
273+
Vector3d topV1 = polygon2.vertices.get(i).pos;
274+
Vector3d bottomV2 = polygon1.vertices.get(nexti).pos;
275+
Vector3d topV2 = polygon2.vertices.get(nexti).pos;
276+
277+
List<Vector3d> pPoints = Arrays.asList(bottomV2, topV2, topV1, bottomV1);
278+
279+
newPolygons.add(Polygon.fromPoints(pPoints, polygon1.getStorage()));
280+
}
281+
282+
polygon2 = polygon2.flipped();
283+
List<Polygon> topPolygons = PolygonUtil.concaveToConvex(polygon2);
284+
if (top) {
285+
newPolygons.addAll(topPolygons);
286+
}
287+
288+
return newPolygons;
289+
290+
}
291+
292+
121293
static List<Vector3d> toCCW(List<Vector3d> points) {
122294

123295
List<Vector3d> result = new ArrayList<>(points);

0 commit comments

Comments
 (0)