//public bool IsOtherEndClipped(PlanarEdge linkedEdge) //{ // var commonVert = GetCommonVertex(linkedEdge); // if (PrevEdgeInfo != null && PrevEdgeInfo.CommonVertex != commonVert) // return PrevEdgeInfo.IsObtuse; // if (NextEdgeInfo != null && NextEdgeInfo.CommonVertex != commonVert) // return NextEdgeInfo.IsObtuse; // return false; //} public static float CalculateAngleBetween(PlanarEdge edge1, PlanarEdge edge2) { Vector3 commonVert; if (edge2.Contains(edge1.P1)) { commonVert = edge1.P1; } else if (edge2.Contains(edge1.P2)) { commonVert = edge1.P2; } else { return(0); } var opp1 = edge1.GetOppositeVertex(commonVert); var dir1 = (opp1 - commonVert).Normalized(); var avgNormal = Vector3.Avg(edge1.OutlineDirection, edge2.OutlineDirection).Normalized(); var edgeAngleDiff = Vector3.AngleBetween(avgNormal, dir1); return(edgeAngleDiff * 2f); }
public PlanarEdgePair(PlanarEdge edge1, PlanarEdge edge2) { Edge1 = edge1; Edge2 = edge2; CommonVertex = edge1.GetCommonVertex(edge2); TotalAngle = PlanarEdge.CalculateAngleBetween(edge1, edge2); AngleDiff = Vector3.AngleBetween(edge1.OutlineDirection, edge2.OutlineDirection); OutlineBisector = Vector3.Avg(edge1.OutlineDirection, edge2.OutlineDirection); }
public bool Colinear(PlanarEdge other) { if (!(other.Contains(P1) || other.Contains(P2))) { return(false); } float angleDiff = Vector3.AngleBetween(Direction, other.Direction); return(float.IsNaN(angleDiff) || angleDiff < 0.08); }
public PlanarEdge GetOtherEdge(PlanarEdge edge) { if (Edge1 == edge) { return(Edge2); } if (Edge2 == edge) { return(Edge1); } return(null); }
public Vector3 GetCommonVertex(PlanarEdge otherEdge) { if (otherEdge.Contains(P1)) { return(P1); } else if (otherEdge.Contains(P2)) { return(P2); } return(Vector3.Empty); }
public PlanarEdgePair GetConnectionInfo(PlanarEdge otherEdge) { if (PrevEdgeInfo?.ContainsEdge(otherEdge) ?? false) { return(PrevEdgeInfo); } if (NextEdgeInfo?.ContainsEdge(otherEdge) ?? false) { return(NextEdgeInfo); } return(null); }
public bool IsConnectedTo(PlanarEdge other) { if (other == this) { return(false); } if (NextEdgeInfo != null && NextEdgeInfo.ContainsEdge(other)) { return(true); } if (PrevEdgeInfo != null && PrevEdgeInfo.ContainsEdge(other)) { return(true); } return(false); }
public void ValidateValues() { var minPos = Vector2.Min(P1, P2, P3); var maxPos = Vector2.Max(P1, P2, P3); if (minPos.Y < 0 && Math.Abs(minPos.Y) > LineThickness) { NeedsToBeClipped = true; } if (maxPos.Y < LineThickness && (maxPos.Y - minPos.Y) > LineThickness) { IsOutsideTriangle = true; } //Dead End if (!PlanarEdge.IsVertexLinked(TargetVertex)) { //TO IMPROVE IsDeadEnd = true; NeedsToBeClipped = true; } }
static ProjectedEdge CreateClippingEdge(ProjectedEdge baseEdge, Vector3 edgeEnd, Plane facePlane) { var triangle = baseEdge.PlanarEdge.Face; var oppVert = baseEdge.PlanarEdge.GetOppositeVertex(edgeEnd); var outlineDir = (edgeEnd - oppVert).Normalized(); var interEdge = new HardEdge( edgeEnd, edgeEnd + baseEdge.PlanarEdge.OutlineDirection, facePlane.Normal, outlineDir); interEdge.CorrectOrder(); var planarEndEdge = new PlanarEdge(interEdge, triangle, facePlane); var interProjected = planarEndEdge.ProjectTriangle(triangle, edgeEnd); interProjected.NeedsToBeClipped = true; baseEdge.CombineWith = interProjected; interProjected.CombineWith = baseEdge; return(interProjected); }
public static void GenerateOutlines(IEnumerable <Triangle> triangles, float breakAngle) { float breakAngleRad = breakAngle / 180f * fPI; var triangleList = triangles.ToList(); var sw = Stopwatch.StartNew(); var hardEdgeDict = new HardEdgeDictionary(); hardEdgeDict.Initialize(triangleList, breakAngle); sw.Stop(); Console.WriteLine($"Calculate Hard Edges => {sw.Elapsed}"); sw.Restart(); //var tp1 = new Vector3(-0.254556f, 0.254556f, 0f); //var tp2 = new Vector3(-0.332604f, 0.137772f, 0f); //var tp3 = new Vector3(-0.295648f, 0.122464f, 0f); foreach (var triangle in triangleList) { var facePlane = new Plane(triangle.GetCenter(), triangle.Normal); var planarEdges = CalculatePlanarEdges(triangle, hardEdgeDict); var projectedEdges = new List <ProjectedEdge>(); //if (triangle.ContainsVertex(tp1) && triangle.ContainsVertex(tp2) && triangle.ContainsVertex(tp3)) //{ //} foreach (var vert in triangle.Vertices) { var edgesConnectedToVertex = planarEdges.Where(x => x.Contains(vert.Position)).ToList(); // remove edges that must be intersected with edges that are not connected to the current vertex if (edgesConnectedToVertex.Any(x => x.IsUsedInIntersection)) { var interEdges = edgesConnectedToVertex.Where(x => x.IsUsedInIntersection).ToList(); foreach (var edge in interEdges) { if (!edgesConnectedToVertex.Any(e => edge.IsConnectedTo(e))) { edgesConnectedToVertex.Remove(edge); } } } var projections = edgesConnectedToVertex.Select(x => x.ProjectTriangle(triangle, vert.Position)).ToList(); //if (vert.Position.Equals(new Vector3(-0.254556f, 0.254556f, 0f), 0.001f) || // vert.Position.Equals(new Vector3(3.85456f, 0.254556f, -2f), 0.001f) // //&& triangle.Vertices.Any(v=>v.Position.Y == 2.07874f) // //&& triangle.Normal.Equals(Vector3.UnitZ, 0.8f) // ) //{ //} projections.RemoveAll(p => p.IsOutsideTriangle); if (projections.Count(p => p.IsDeadEnd) >= 2) { var deadEnds = projections.Where(p => p.IsDeadEnd); var triCenter = triangle.GetCenter(); var projectionToKeep = deadEnds.OrderBy(p => Vector3.Distance(vert.Position + p.PlanarEdge.OutlineDirection, triCenter)).First(); projections.RemoveAll(p => p.IsDeadEnd && p != projectionToKeep); } if (projections.Count == 2) { var edge1 = projections[0].PlanarEdge; var edge2 = projections[1].PlanarEdge; var projection1 = projections[0]; var projection2 = projections[1]; if (edge1.Colinear(edge2) && !(projection1.NeedsToBeClipped || projection2.NeedsToBeClipped)) { projectedEdges.Add(projection1); } else { bool mustIntersect = false; var edgeLinkInfo = edge1.GetConnectionInfo(edge2); if (edgeLinkInfo != null) { mustIntersect = edgeLinkInfo.IsObtuse; } else { var angleBetweenEdges = PlanarEdge.CalculateAngleBetween(edge1, edge2); mustIntersect = angleBetweenEdges >= fPI; } if (mustIntersect) { projection1.NeedsToBeClipped = true; projection2.NeedsToBeClipped = true; } projection1.CombineWith = projection2; projection2.CombineWith = projection1; projectedEdges.Add(projection1); projectedEdges.Add(projection2); } } else if (projections.Count == 1) { var projection = projections[0]; projectedEdges.Add(projection); if (projection.NeedsToBeClipped) { projectedEdges.Add(CreateClippingEdge(projection, vert.Position, facePlane)); } } else if (projections.Count > 2) { } } if (projectedEdges.Any()) { int pairIdx = 0; bool combineStandAlones = projectedEdges.Count() > 3; while (pairIdx < 3 && projectedEdges.Any()) { var projection = projectedEdges.OrderByDescending(x => x.CombineWith != null) .FirstOrDefault(); projectedEdges.Remove(projection); var nextEdge = projection.CombineWith; //if (combineStandAlones && nextEdge == null) //{ // nextEdge = projectedEdges // .Where(x => !projection.NeedsToBeClipped && x.IntersectWith == null) // .FirstOrDefault(); //} if (nextEdge != null) { projectedEdges.Remove(nextEdge); } SetOutlineCoords(triangle, pairIdx++, projection, nextEdge); } } } sw.Stop(); Console.WriteLine($"Calculate Outlines => {sw.Elapsed}"); }
public bool ContainsEdge(PlanarEdge edge) { return(Edge1 == edge || Edge2 == edge); }