public double OpeningAngleDeg(int iVertex) { Vector2d e0 = Vector2d.Zero, e1 = Vector2d.Zero; NeighboursV(iVertex, ref e0, ref e1, true); return(Vector2d.AngleD(e0, e1)); }
/// <summary> /// Compute opening angle at vertex vID. /// If not a vertex, or valence != 2, returns invalidValue argument. /// If either edge is degenerate, returns invalidValue argument. /// </summary> public double OpeningAngle(int vID, double invalidValue = double.MaxValue) { if (vertices_refcount.isValid(vID) == false) { return(invalidValue); } List <int> vedges = vertex_edges[vID]; if (vedges.Count != 2) { return(invalidValue); } int nbra = edge_other_v(vedges[0], vID); int nbrb = edge_other_v(vedges[1], vID); Vector2d v = new Vector2d(vertices[2 * vID], vertices[2 * vID + 1]); Vector2d a = new Vector2d(vertices[2 * nbra], vertices[2 * nbra + 1]); Vector2d b = new Vector2d(vertices[2 * nbrb], vertices[2 * nbrb + 1]); a -= v; if (a.Normalize() == 0) { return(invalidValue); } b -= v; if (b.Normalize() == 0) { return(invalidValue); } return(Vector2d.AngleD(a, b)); }
/// <summary> /// Find and remove any junction (ie valence>2) vertices of the graph. /// At a junction, the pair of best-aligned (ie straightest) edges are left /// connected, and all the other edges are disconnected /// /// [TODO] currently there is no DGraph2.SetEdge(), so the 'other' edges /// are deleted and new edges inserted. Hence, edge IDs are not preserved. /// </summary> public static int DisconnectJunctions(DGraph2 graph) { var junctions = new List <int>(); // find all junctions foreach (int vid in graph.VertexIndices()) { if (graph.IsJunctionVertex(vid)) { junctions.Add(vid); } } foreach (int vid in junctions) { Vector2d v = graph.GetVertex(vid); int[] nbr_verts = graph.VtxVerticesItr(vid).ToArray(); // find best-aligned pair of edges connected to vid Index2i best_aligned = Index2i.Max; double max_angle = 0; for (int i = 0; i < nbr_verts.Length; ++i) { for (int j = i + 1; j < nbr_verts.Length; ++j) { double angle = Vector2d.AngleD( (graph.GetVertex(nbr_verts[i]) - v).Normalized, (graph.GetVertex(nbr_verts[j]) - v).Normalized); angle = Math.Abs(angle); if (angle > max_angle) { max_angle = angle; best_aligned = new Index2i(nbr_verts[i], nbr_verts[j]); } } } // for nbr verts that are not part of the best_aligned edges, // we remove those edges and add a new one connected to a new vertex for (int k = 0; k < nbr_verts.Length; ++k) { if (nbr_verts[k] == best_aligned.a || nbr_verts[k] == best_aligned.b) { continue; } int eid = graph.FindEdge(vid, nbr_verts[k]); graph.RemoveEdge(eid, true); if (graph.IsVertex(nbr_verts[k])) { var newpos = Vector2d.Lerp(graph.GetVertex(nbr_verts[k]), v, 0.99); int newv = graph.AppendVertex(newpos); graph.AppendEdge(nbr_verts[k], newv); } } } return(junctions.Count); }
public static double PlaneAngleSignedD(Vector2d vFrom, Vector2d vTo) { vFrom.Normalize(); vTo.Normalize(); double fSign = Math.Sign(vFrom.Cross(vTo)); double fAngle = fSign * Vector2d.AngleD(vFrom, vTo); return(fAngle); }
public void Chamfer(double chamfer_dist, double minConvexAngleDeg = 30, double minConcaveAngleDeg = 30) { if (IsClockwise) { throw new Exception("must be ccw?"); } List <Vector2d> NewV = new List <Vector2d>(); int N = Vertices.Count; int iCur = 0; do { Vector2d center = Vertices[iCur]; int iPrev = (iCur == 0) ? N - 1 : iCur - 1; Vector2d prev = Vertices[iPrev]; int iNext = (iCur + 1) % N; Vector2d next = Vertices[iNext]; Vector2d cp = prev - center; double cpdist = cp.Normalize(); Vector2d cn = next - center; double cndist = cn.Normalize(); // if degenerate, skip this vert if (cpdist < MathUtil.ZeroTolerancef || cndist < MathUtil.ZeroTolerancef) { iCur = iNext; continue; } double angle = Vector2d.AngleD(cp, cn); // TODO document what this means sign-wise double sign = cp.Perp.Dot(cn); bool bConcave = (sign > 0); double thresh = (bConcave) ? minConcaveAngleDeg : minConvexAngleDeg; // ok not too sharp if (angle > thresh) { NewV.Add(center); iCur = iNext; continue; } double prev_cut_dist = Math.Min(chamfer_dist, cpdist * 0.5); Vector2d prev_cut = center + prev_cut_dist * cp; double next_cut_dist = Math.Min(chamfer_dist, cndist * 0.5); Vector2d next_cut = center + next_cut_dist * cn; NewV.Add(prev_cut); NewV.Add(next_cut); iCur = iNext; } while (iCur != 0); vertices = NewV; Timestamp++; }