/// <summary> /// creates the concave hull based on the convex hull and an angle threshold /// </summary> /// <param name="pConvexEdges">edges of convex hull</param> /// <param name="pPoints">the point cloud data set</param> /// <param name="pMaxAngle">angle threshold</param> /// <returns>list of concave hull edges</returns> static List <tEdge> CreateConvaveHullFromConvexEdges(List <DefaultConvexFace <Vertex> > pConvexEdges, HashSet <Vertex> pPoints, double pMaxAngle) { //initialize arrays List <tEdge> convexHull = new List <tEdge>(); foreach (var v in pConvexEdges) { convexHull.Add(new tEdge(v.Vertices[0], v.Vertices[1])); } List <tEdge> concaveHull = new List <tEdge>(); //iterate through convex hull until concave hull is found while (convexHull.Count > 0) { //find longest edge in convex hull list tEdge longestEdge = convexHull.MaxBy(t => t.length); //remove longest edge from convex hull convexHull.Remove(longestEdge); //find nearest point List <tEdge> edges = convexHull.Concat(concaveHull).ToList(); tVector nextPoint = FindPointWithSmallestAngle(pPoints, longestEdge, edges, pMaxAngle); if (nextPoint == null) //if no next point found { concaveHull.Add(longestEdge); continue; } //create edges based on nearest point tEdge e2 = new tEdge(longestEdge.v1, nextPoint.vector); tEdge e3 = new tEdge(longestEdge.v2, nextPoint.vector); //check if e2 and e3 intersect bool intersect = false; foreach (tEdge e1 in edges) { if (Intersects(e2, e1) || Intersects(e3, e1)) { intersect = true; break; } } //add e2 and e3 to List A again, if no intersection if (intersect == false) { convexHull.Add(e2); convexHull.Add(e3); continue; } //if no concaviction found, add longest edge to concaveHull list concaveHull.Add(longestEdge); } return(concaveHull); }
/// <summary> /// finds the point with the smallest angle from a given dataset towards an edge /// </summary> /// <param name="pPoints">the dataset</param> /// <param name="pLine">the edge to calculate the angle towards</param> /// <param name="pBoundaries">boundaries</param> /// <param name="pMaxAngle">angle threshold</param> /// <returns></returns> static tVector FindPointWithSmallestAngle(HashSet <Vertex> pPoints, tEdge pLine, List <tEdge> pBoundaries, double pMaxAngle) { tVector bestFit = null; Object lockObject = new object(); Parallel.ForEach(pPoints, v => { //check if point is on concave hull if (!IsPointOnConcaveHull(v, pBoundaries)) { //calculate new potential edges tEdge t1 = new tEdge(pLine.v1, v); tEdge t2 = new tEdge(pLine.v2, v); //check if local maximum < edge length if (t1.length < pLine.length && t2.length < pLine.length) { //calculate the highest angle between lines and the new point double maxAngle; double angleA = Math.Abs(CalculateAngleBetweenTwoLines(pLine, t1)); double angleB = Math.Abs(CalculateAngleBetweenTwoLines(pLine, t2)); if (angleA > angleB) { maxAngle = angleA; } else { maxAngle = angleB; } //check if highest angle is smaller than threshold if (maxAngle < pMaxAngle) { //check if bestFit has been initialized tVector currentFit = new tVector(v, maxAngle); lock (lockObject) if (bestFit == null) { bestFit = currentFit; } //check if current point has a better fit lock (lockObject) if (currentFit.maxAngle < bestFit.maxAngle) { bestFit = currentFit; } } } } }); return(bestFit); }
public override IDerivation Visit(AlternativeSet aAlternativeSet, DerivationContext aContext) { for (int i = 0; i < aAlternativeSet.Count; i++) { IPhrase phr = aAlternativeSet.Phrases[i]; if (OmmitTerminals && phr is Terminal) { continue; } tEdge edge = addEdge(aContext, phr, aAlternativeSet.Parent); edge.CustomAttributes = phr.IsCyclic ? GrammarGraphEdgeAttrs.IsCyclic : GrammarGraphEdgeAttrs.None; phr.Accept(NewContext(aAlternativeSet, aContext)); } return(null); }
public override IDerivation Visit(Seqence aSeqence, DerivationContext aContext) { for (int i = 0; i < aSeqence.Count; i++) { IPhrase phr = aSeqence.Phrases[i]; if (OmmitTerminals && phr is Terminal) { continue; } tEdge edge = addEdge(aContext, phr, aSeqence.Parent); edge.CustomAttributes = GrammarGraphEdgeAttrs.IsSequence | (phr.IsCyclic ? GrammarGraphEdgeAttrs.IsCyclic : GrammarGraphEdgeAttrs.None); phr.Accept(NewContext(aSeqence, aContext)); } return(null); }
/// <summary> /// checks if two edges are intersecting /// </summary> /// <param name="AB">edge 1</param> /// <param name="CD">edge 2</param> /// <returns>true if intersects, false if not</returns> static bool Intersects(tEdge AB, tEdge CD) { //http://www.codeproject.com/Tips/862988/Find-the-Intersection-Point-of-Two-Line-Segments Vector ABs = new Vector(AB.v1.Position[0], AB.v1.Position[1]); Vector ABe = new Vector(AB.v2.Position[0], AB.v2.Position[1]); Vector CDs = new Vector(CD.v1.Position[0], CD.v1.Position[1]); Vector CDe = new Vector(CD.v2.Position[0], CD.v2.Position[1]); Vector intersection; bool intersects = LineSegmentIntersection.LineSegementsIntersect(ABs, ABe, CDs, CDe, out intersection); if (intersects) { if (intersection.Equals(ABs) || intersection.Equals(ABe) || intersection.Equals(CDs) || intersection.Equals(CDe)) { return(false); } } return(intersects); }
public override IDerivation Visit(NonTerminal aSymbol, DerivationContext aContext) { tGraph graph = (aContext as BuildGraphContext).BuildingGraph; if ((aSymbol.CycicKind & CycicKind.CyclicOrigin) > 0) { graph.ensureExistsNode(aSymbol.CounterName, aSymbol.Text); graph.ensureExistsNode(aSymbol.CyclicToOccurence, aSymbol.Text); tEdge e = graph.addEdge(aSymbol.CounterName, aSymbol.CyclicToOccurence); if (e != null) { e.CustomAttributes = GrammarGraphEdgeAttrs.IsPunktir; } } if (aSymbol.CycicKind == CycicKind.None || aSymbol.CycicKind == CycicKind.CyclicPropagated) { aSymbol.FindItsRule().Expand(aContext); } return(null); }
/// <summary> /// calculates the angle between two lines /// </summary> /// <param name="l1">line 1</param> /// <param name="l2">line 2</param> /// <returns>the angle between line 1 and line 2</returns> static double CalculateAngleBetweenTwoLines(tEdge l1, tEdge l2) { //https://social.msdn.microsoft.com/Forums/vstudio/en-US/fa0cfeb6-70b7-4181-bc9b-fe625cd5e159/angle-between-two-lines //Double Angle = Math.Atan2(y2-y1, x2-x1) - Math.Atan2(y4-y3,x4-x3); return(Math.Atan2(l1.v2.Position[1] - l1.v1.Position[1], l1.v2.Position[0] - l1.v1.Position[0]) - Math.Atan2(l2.v2.Position[1] - l2.v1.Position[1], l2.v2.Position[0] - l2.v1.Position[0])); /* * //http://usb.unitedsb.de/topic/72776-java-winkel-zwischen-2-geraden-berechnen-wie/ * //calculate new vectors // l1.v1 == l2.v1 * Vertex P1P2 = new Vertex(l1.v2.Position[0] - l1.v1.Position[0], l1.v2.Position[1] - l1.v1.Position[1]); * Vertex P1P3 = new Vertex(l2.v2.Position[0] - l1.v1.Position[0], l2.v2.Position[1] - l1.v1.Position[1]); * * //calculate length of vectors * double norm1 = Math.Sqrt((P1P2.Position[0] * P1P2.Position[0]) + (P1P2.Position[1] * P1P2.Position[1])); * double norm2 = Math.Sqrt((P1P3.Position[0] * P1P3.Position[0]) + (P1P3.Position[1] * P1P3.Position[1])); * * //scalar product * double skpr = (P1P2.Position[0] * P1P3.Position[0]) + (P1P2.Position[1] * P1P3.Position[1]); * * //calc angle (radial, bogenmaß) * double alpha = Math.Acos(skpr / (norm1 * norm2)); * * return ((180 / Math.PI) * alpha);*/ }
private tEdge addEdge(DerivationContext aContext, IPhrase aPhr, IPhrase aParent) { tGraph graph = (aContext as BuildGraphContext).BuildingGraph; string fromName = "unk"; string toName = "unk"; // determine fromName if (aParent == null) { fromName = aContext.Grammar.MainSymbol.CounterName; graph.ensureExistsNode(fromName, aContext.Grammar.MainSymbol.Text); } else { NonTerminal parentNt = aParent as NonTerminal; if (parentNt != null) { fromName = parentNt.CounterName; graph.ensureExistsNode(parentNt.CounterName, parentNt.Text); } else { fromName = (aContext as BuildGraphContext).GeneratedToName; Debug.Assert(!string.IsNullOrEmpty(fromName), "Не должно быть"); } } // determine toName NonTerminal nonTerminal = aPhr as NonTerminal; Terminal terminal = aPhr as Terminal; if (nonTerminal != null) { toName = nonTerminal.CounterName; string text = nonTerminal.Text; if ((nonTerminal.CycicKind & CycicKind.SkippedAsSeen) > 0) { text += " *"; } graph.ensureExistsNode(toName, text); } else if (terminal != null) { string text = string.IsNullOrEmpty(terminal.Text) ? "e" : terminal.Text; tNode n = graph.addNonUniqueNode(text); toName = n.Name; n.CustomAttributes = "term"; } else { toName = graph.addNonUniqueNode(aPhr.ToString()).Name; //надо запомнить это в контексте (aContext as BuildGraphContext).GeneratedToName = toName; } tEdge e = graph.addEdge(fromName, toName); if (e == null) { Debug.WriteLine("не создалась дуга, потому что нет вершин"); } return(e); }