void Cleanup() { for (int i = 0; i < edges.Count; ++i) { ConvexHullEdge edge = edges[i]; if (edge.remove) { Vector3D point1 = edge.pointA; Vector3D point2 = edge.pointB; int keyToEvict = Key2Edge(point1, point2); edgeMap.Remove(keyToEvict); edges.RemoveAt(i--); } } for (int i = 0; i < faces.Count; ++i) { ConvexHullFace face = faces[i]; if (face.visible) { faces.RemoveAt(i--); } } }
public void Erase(ConvexHullFace face) { if (adjface2 == face) { adjface2 = null; } else { adjface1 = null; } }
private void CreateEdge(Vector3D pointA, Vector3D pointB, ConvexHullFace face) { int key = Key2Edge(pointA, pointB); if (!edgeMap.ContainsKey(key)) { ConvexHullEdge edge = new ConvexHullEdge(pointA, pointB); edges.Add(edge); edgeMap.Add(key, edge); } edgeMap[key].LinkAdjFace(face); }
void AddOneFace(Vector3D pointA, Vector3D pointB, Vector3D pointC, Vector3D innerPoint) { faces.Add(new ConvexHullFace(pointA, pointB, pointC)); ConvexHullFace face = faces[faces.Count - 1]; if (VolumeSign(face, innerPoint) < 0) { face.Reverse(); } CreateEdge(pointA, pointB, face); CreateEdge(pointA, pointC, face); CreateEdge(pointB, pointC, face); }
public bool BuildFirstHull(List <Vector3D> points) { int pointCount = points.Count; if (pointCount <= 3) { return(false); } int i = 2; while (Colinear(points[i], points[i - 1], points[i - 2])) { if (i++ == pointCount - 1) { return(false); } } ConvexHullFace face = new ConvexHullFace(points[i], points[i - 1], points[i - 2]); int j = i; while (VolumeSign(face, points[j]) == 0) { if (j++ == pointCount - 1) { return(false); } } Vector3D pointA = points[i]; Vector3D pointB = points[i - 1]; Vector3D pointC = points[i - 2]; Vector3D pointD = points[j]; processedPoints.Add(pointA); processedPoints.Add(pointB); processedPoints.Add(pointC); processedPoints.Add(pointD); AddOneFace(pointA, pointB, pointC, pointD); AddOneFace(pointA, pointB, pointD, pointC); AddOneFace(pointA, pointC, pointD, pointB); AddOneFace(pointB, pointC, pointD, pointA); return(true); }
public void LinkAdjFace(ConvexHullFace face) { if (adjface1 != null && adjface2 != null) { return; } if (adjface1 == null) { adjface1 = face; } else { adjface2 = face; } }
Vector3D FindInnerPoint(ConvexHullFace f, ConvexHullEdge e) { if (!f.pointA.Equals(e.pointA) && !f.pointA.Equals(e.pointB)) { return(f.pointA); } if (!f.pointB.Equals(e.pointA) && !f.pointB.Equals(e.pointB)) { return(f.pointB); } if (!f.pointC.Equals(e.pointA) && !f.pointC.Equals(e.pointB)) { return(f.pointC); } return(null); }
void IncrementHull(Vector3D pt) { bool vis = false; foreach (ConvexHullFace face in faces) { if (VolumeSign(face, pt) < 0) { face.visible = vis = true; } } if (!vis) { return; } for (int i = 0; i < edges.Count; ++i) { ConvexHullEdge edge = edges[i]; ConvexHullFace face1 = edge.adjface1; ConvexHullFace face2 = edge.adjface2; if (face1 == null || face2 == null) { continue; } else if (face1.visible && face2.visible) { edge.remove = true; } else if (face1.visible || face2.visible) { if (face1.visible) { ConvexHullFace faceT = face2; face2 = face1; face1 = faceT; } Vector3D innerPoint = FindInnerPoint(face2, edge); edge.Erase(face2); AddOneFace(edge.pointA, edge.pointB, pt, innerPoint); } } }
int VolumeSign(ConvexHullFace face, Vector3D p) { double vol; double ax, ay, az, bx, by, bz, cx, cy, cz; ax = face.pointA.X - p.X; ay = face.pointA.Y - p.Y; az = face.pointA.Z - p.Z; bx = face.pointB.X - p.X; by = face.pointB.Y - p.Y; bz = face.pointB.Z - p.Z; cx = face.pointC.X - p.X; cy = face.pointC.Y - p.Y; cz = face.pointC.Z - p.Z; vol = ax * (by * cz - bz * cy) + ay * (bz * cx - bx * cz) + az * (bx * cy - by * cx); if (vol == 0) { return(0); } return(vol < 0 ? -1 : 1); }