/// <summary> /// Splits a <see cref="Polygon"/> by this plane if needed. After that it puts the /// polygons or the polygon fragments in the appropriate lists /// (<c>front</c>, <c>back</c>). Coplanar polygons go into either /// <c>coplanarFront</c>, <c>coplanarBack</c> depending on their /// orientation with respect to this plane. Polygons in front or back of this /// plane go into either <c>front</c> or <c>back</c>. /// </summary> /// <param name="polygon">polygon to split</param> /// <param name="coplanarFront">"coplanar front" polygons</param> /// <param name="coplanarBack">"coplanar back" polygons</param> /// <param name="front">front polygons</param> /// <param name="back">back polgons</param> /// public void splitPolygon( Polygon polygon, List <Polygon> coplanarFront, List <Polygon> coplanarBack, List <Polygon> front, List <Polygon> back) { const int COPLANAR = 0; const int FRONT = 1; const int BACK = 2; const int SPANNING = 3; // == some in the FRONT + some in the BACK // Classify each point as well as the entire polygon into one of the // above four classes. int polygonType = 0; List <int> types = new List <int>(polygon.vertices.Count); for (int i = 0; i < polygon.vertices.Count; i++) { double t = this.normal.dot(polygon.vertices[i].pos) - this.dist; int type = (t < -Plane.EPSILON) ? BACK : (t > Plane.EPSILON) ? FRONT : COPLANAR; polygonType |= type; types.Add(type); } //System.out.println("> switching"); // Put the polygon in the correct list, splitting it when necessary. switch (polygonType) { case COPLANAR: //System.out.println(" -> coplanar"); (this.normal.dot(polygon._csg_plane.normal) > 0 ? coplanarFront : coplanarBack).Add(polygon); break; case FRONT: //System.out.println(" -> front"); front.Add(polygon); break; case BACK: //System.out.println(" -> back"); back.Add(polygon); break; case SPANNING: //System.out.println(" -> spanning"); List <Vertex> f = new List <Vertex>(); List <Vertex> b = new List <Vertex>(); for (int i = 0; i < polygon.vertices.Count; i++) { int j = (i + 1) % polygon.vertices.Count; int ti = types[i]; int tj = types[j]; Vertex vi = polygon.vertices[i]; Vertex vj = polygon.vertices[j]; if (ti != BACK) { f.Add(vi); } if (ti != FRONT) { b.Add(ti != BACK ? vi.clone() : vi); } if ((ti | tj) == SPANNING) { double t = (this.dist - this.normal.dot(vi.pos)) / this.normal.dot(vj.pos.minus(vi.pos)); Vertex v = vi.interpolate(vj, t); f.Add(v); b.Add(v.clone()); } } if (f.Count >= 3) { front.Add(new Polygon(f, polygon.getStorage())); } if (b.Count >= 3) { back.Add(new Polygon(b, polygon.getStorage())); } break; } }
/// <summary> /// Decomposes the specified concave polygon into convex polygons. /// </summary> /// <param name="points">the points that define the polygon</param> /// <returns>the decomposed concave polygon (list of convex polygons)</returns> /// public static List <Polygon> fromConcavePoints(params IVector3d[] points) { Polygon p = fromPoints(points); return(PolygonUtil.concaveToConvex(p)); }