/// <summary> /// Merges a point to a convex hull that is a line segment. /// </summary> /// <param name="point">The point.</param> private void GrowLinearConvex(Vector3F point) { Debug.Assert(_mesh != null); Debug.Assert(_mesh.Vertices.Count == 2, "DCEL mesh with 2 vertices was expected."); Debug.Assert(_type == ConvexHullType.Linear); Debug.Assert(!Vector3F.AreNumericallyEqual(_mesh.Vertex.Position, point)); Debug.Assert(!Vector3F.AreNumericallyEqual(_mesh.Vertices[1].Position, point)); // Abort if the point is equal to an existing point. if (Vector3F.AreNumericallyEqual(point, _mesh.Vertex.Position) || Vector3F.AreNumericallyEqual(point, _mesh.Vertex.Edge.Twin.Origin.Position)) return; var edge = _mesh.Vertex.Edge; var collinearity = DcelMesh.GetCollinearity(point, _mesh.Vertex.Edge); switch (collinearity) { case Collinearity.CollinearBefore: // The point is the new start of the line segment. edge.Origin.Position = point; _mesh.Dirty = true; return; case Collinearity.CollinearAfter: // The point is the new end of the line segment. edge.Twin.Origin.Position = point; _mesh.Dirty = true; return; case Collinearity.CollinearContained: // The point is in the line segment. // Point is in convex hull. return; } Debug.Assert(collinearity == Collinearity.NotCollinear || collinearity == Collinearity.NotCollinearBehind || collinearity == Collinearity.NotCollinearInFront); // Not Collinear --> Make triangle. _type = ConvexHullType.Planar; // Create new components. DcelVertex v0 = _mesh.Vertex; DcelVertex v1 = edge.Twin.Origin; DcelVertex v2 = new DcelVertex(point, null); DcelEdge e01 = edge; DcelEdge e10 = e01.Twin; DcelEdge e12 = new DcelEdge(); DcelEdge e21 = new DcelEdge(); DcelEdge e02 = new DcelEdge(); DcelEdge e20 = new DcelEdge(); DcelFace f012 = new DcelFace(); DcelFace f210 = new DcelFace(); // Link with existing components. e01.Next = e12; e01.Previous = e20; e10.Next = e02; e10.Previous = e21; // Link new components. v2.Edge = e20; e12.Origin = v1; e21.Origin = v2; e20.Origin = v2; e02.Origin = v0; e12.Twin = e21; e21.Twin = e12; e20.Twin = e02; e02.Twin = e20; e12.Previous = e01; e21.Previous = e02; e20.Previous = e12; e02.Previous = e10; e12.Next = e20; e21.Next = e10; e20.Next = e01; e02.Next = e21; // Link face. f012.Boundary = e01; f210.Boundary = e21; e01.Face = e12.Face = e20.Face = f012; e21.Face = e10.Face = e02.Face = f210; // Update _faces. _faces.Add(f012); _faces.Add(f210); _mesh.Dirty = true; Debug.Assert(_mesh.Faces.Count == _faces.Count, "Internal error in ConvexHullBuilder."); Debug.Assert(_mesh.IsTriangleMesh(), "DCEL mesh should be a triangle mesh."); Debug.Assert(_mesh.IsTwoSidedPolygon(), "DCEL mesh should be a two-sided polygon."); }
/// <summary> /// Merges a point to an empty convex hull. /// </summary> /// <param name="point">The point.</param> private void GrowEmptyConvex(Vector3F point) { Debug.Assert(_mesh != null); Debug.Assert(_mesh.Vertices.Count == 0, "DCEL mesh is not empty."); Debug.Assert(_type == ConvexHullType.Empty); // Create a single vertex. _mesh.Vertex = new DcelVertex(point, null); _mesh.Dirty = true; _type = ConvexHullType.Point; }
/// <summary> /// Merges a point to a convex hull that is also a point. /// </summary> /// <param name="point">The point.</param> private void GrowPointConvex(Vector3F point) { Debug.Assert(_mesh != null); Debug.Assert(_mesh.Vertices.Count == 1, "DCEL mesh with 1 vertex was expected."); Debug.Assert(_type == ConvexHullType.Point); // Abort if the point is equal to the existing point in the mesh. if (Vector3F.AreNumericallyEqual(_mesh.Vertex.Position, point)) return; DcelVertex newVertex = new DcelVertex(point, null); DcelEdge edge = new DcelEdge(); DcelEdge twin = new DcelEdge(); // Link everything. edge.Origin = _mesh.Vertex; twin.Origin = newVertex; edge.Twin = twin; twin.Twin = edge; _mesh.Vertex.Edge = edge; newVertex.Edge = twin; _mesh.Dirty = true; _type = ConvexHullType.Linear; }
public void Reset() { // Reset fields. _faces = new List<DcelFace>(); _taggedEdges = new List<DcelEdge>(); _isPlanar = false; _type = ConvexHullType.Empty; _mesh = new DcelMesh(); }
/// <summary> /// Removes the given face and connects the face edges to the given point. /// </summary> /// <param name="face">The face.</param> /// <param name="point">The point.</param> private void GrowPlanarConvexToSpatial(DcelFace face, Vector3F point) { _faces.Remove(face); // Create a new vertex for the point. DcelVertex newVertex = new DcelVertex(point, null); // Traverse the boundary of the face. DcelEdge currentEdge = face.Boundary; DcelEdge previousEdge = null; do { // Create new face. DcelFace newface = new DcelFace(); newface.Boundary = currentEdge; currentEdge.Face = newface; _faces.Add(newface); // Create 2 half-edges. currentEdge.Next = new DcelEdge(); currentEdge.Previous = new DcelEdge(); currentEdge.Next.Face = newface; currentEdge.Next.Origin = currentEdge.Twin.Origin; currentEdge.Next.Previous = currentEdge; currentEdge.Next.Next = currentEdge.Previous; currentEdge.Previous.Face = newface; currentEdge.Previous.Origin = newVertex; currentEdge.Previous.Previous = currentEdge.Next; currentEdge.Previous.Next = currentEdge; // Link new face with previous new face. if (previousEdge != null) { previousEdge.Next.Twin = currentEdge.Previous; currentEdge.Previous.Twin = previousEdge.Next; } // Go to next edge. previousEdge = currentEdge; currentEdge = currentEdge.Twin.Previous.Twin; // Go on until no edge points to face anymore. } while (currentEdge.Face == face); // Link the last new face with the first new face. previousEdge.Next.Twin = currentEdge.Previous; currentEdge.Previous.Twin = previousEdge.Next; Debug.Assert(previousEdge != null); Debug.Assert(currentEdge == face.Boundary); Debug.Assert(currentEdge.Face != face); // Set the data for the new vertex. newVertex.Edge = currentEdge.Previous; _mesh.Dirty = true; _type = ConvexHullType.Spatial; Debug.Assert(_mesh.Faces.Count == _faces.Count, "Internal error in ConvexHullBuilder."); }