public void SetCrossSection2D(Flat plane) { var paths = new List <List <PointLight> >(); var positivePath = new PolygonLight(MiscFunctions.Get2DProjectionPointsAsLight(PositiveLoop.VertexLoop, plane.Normal).ToList()); if (positivePath.Area < 0) { positivePath.Path.Reverse(); } paths.Add(positivePath.Path); foreach (var loop in NegativeLoops) { var negativePath = new PolygonLight(MiscFunctions.Get2DProjectionPointsAsLight(loop.VertexLoop, plane.Normal).ToList()); if (negativePath.Area > 0) { negativePath.Path.Reverse(); } paths.Add(negativePath.Path); } CrossSection2D = PolygonOperations.Union(paths).Select(p => new PolygonLight(p)).ToList(); }
internal CoincidentEdgeContactElement(Edge edge, Flat plane) { var avgFaceNormal = edge.OwnedFace.Normal.add(edge.OtherFace.Normal).divide(2); var edgeDir = plane.Normal.crossProduct(avgFaceNormal); if (edgeDir.dotProduct(edge.Vector) > 0) { StartVertex = edge.From; EndVertex = edge.To; SplitFacePositive = edge.OwnedFace; // the owned face is "above the flat plane SplitFaceNegative = edge.OtherFace; // the other face is below it } else { StartVertex = edge.To; EndVertex = edge.From; SplitFacePositive = edge.OtherFace; // the reverse from above. The other face is above the flat SplitFaceNegative = edge.OwnedFace; ReverseDirection = true; } ContactEdge = edge; // ContactEdge = new Edge(ReferenceStart, ReferenceEnd, null, null); }
internal ContactData(IEnumerable <SolidContactData> solidContactData, IEnumerable <IntersectionGroup> intersectionGroups, Flat plane) { SolidContactData = new List <SolidContactData>(solidContactData); IntersectionGroups = new List <IntersectionGroup>(intersectionGroups); Plane = plane; }
internal static Boolean FindNegativeAndPositiveFaces(Flat plane, Vertex onPlaneVertex, double[] vertexDistancesToPlane, out PolygonalFace negativeFace, out PolygonalFace positiveFace) { negativeFace = null; positiveFace = null; foreach (var face in onPlaneVertex.Faces) { var otherEdge = face.OtherEdge(onPlaneVertex); var toDistance = vertexDistancesToPlane[otherEdge.To.IndexInList]; var fromDistance = vertexDistancesToPlane[otherEdge.From.IndexInList]; if ((toDistance > 0 && fromDistance < 0) || (toDistance < 0 && fromDistance > 0)) if ((toDistance > 0) == (face == otherEdge.OwnedFace)) positiveFace = face; else negativeFace = face; } return (negativeFace != null && positiveFace != null); }
internal ThroughFaceContactElement(Flat plane, Edge edge, double toDistance) { PolygonalFace negativeFace, positiveFace; if (toDistance > 0) { positiveFace = edge.OtherFace; negativeFace = edge.OwnedFace; } else { negativeFace = edge.OtherFace; positiveFace = edge.OwnedFace; } SplitEdge = edge; SplitFaceNegative = negativeFace; SplitFacePositive = positiveFace; StartVertex = GeometryFunctions.PointOnPlaneFromIntersectingLine( plane.Normal, plane.DistanceToOrigin, edge.From, edge.To); }
/// <summary> /// Gets the in plane flat. /// </summary> /// <param name="startFace">The start face.</param> /// <returns>Flat.</returns> private static Flat GetInPlaneFlat(PolygonalFace startFace) { var flat = new Flat(new List<PolygonalFace>(new[] { startFace })); var visitedFaces = new HashSet<PolygonalFace>(startFace.AdjacentFaces); visitedFaces.Add(startFace); var stack = new Stack<PolygonalFace>(visitedFaces); while (stack.Any()) { var face = stack.Pop(); if (!flat.IsNewMemberOf(face)) continue; flat.UpdateWith(face); foreach (var adjacentFace in face.AdjacentFaces) if (!visitedFaces.Contains(adjacentFace)) { visitedFaces.Add(adjacentFace); stack.Push(adjacentFace); } } return flat; }
internal static void MakeInPlaneContactElement(Flat plane, Edge edge, HashSet<Edge> edgeHashSet, double[] vertexDistancesToPlane, List<CoincidentEdgeContactElement> contactElts) { // the edge is in the plane. Let's look at details on the two faces that meet at that edge. // ownedFaceOtherVertex is the vertex of the face of the in-plane edge that is NOT on the plane... // it's the "other" vertex var ownedFaceOtherVertex = edge.OwnedFace.OtherVertex(edge); // the distance to the flat plane for the other vertex. var distPlaneOwned = vertexDistancesToPlane[ownedFaceOtherVertex.IndexInList]; // repeat for the other face of the in-plane edge var otherFaceOtherVertex = edge.OtherFace.OtherVertex(edge); var distPlaneOther = vertexDistancesToPlane[otherFaceOtherVertex.IndexInList]; // here, we check to see if the faces are on either side of the flat plane, if they are // then we make a if ((distPlaneOwned > 0 && distPlaneOther < 0) || (distPlaneOwned < 0 && distPlaneOther > 0)) { RemoveNeighboringEdgesToo(edgeHashSet, edge); //remove the edges of the faces from the hash to speed things along contactElts.Add(new CoincidentEdgeContactElement(edge, plane)); return; } // if faces are not on either side, check to see if one of the faces is // in the same plane as flat. If so, then do a depth first search with "GetInPlaneFlat" // to build up that section of faces. Flat inPlaneFlat; if (StarMath.IsNegligible(distPlaneOwned)) inPlaneFlat = GetInPlaneFlat(edge.OwnedFace); else if (StarMath.IsNegligible(distPlaneOther)) inPlaneFlat = GetInPlaneFlat(edge.OtherFace); else //if neither face is in the plane then you have an edge which is a knife on the plane { // either on the positive side or the negative side. Doesn't matter which one - we don't want it (i.e. continue). RemoveNeighboringEdgesToo(edgeHashSet, edge); //remove the edges of the faces from the hash to speed things along return; } foreach (var innerEdge in inPlaneFlat.InnerEdges) edgeHashSet.Remove(innerEdge); foreach (var outerEdge in inPlaneFlat.OuterEdges) { edgeHashSet.Remove(outerEdge); contactElts.Add(new CoincidentEdgeContactElement(outerEdge, plane)); } }