public GraphPoint(GraphPoint other) { if (other == null) return; index = DataSeries_Funcs.GetCurrentDataSeries().GetPointCount(); pos = other.pos; if (other.pendingEdges != null) { foreach (int edge in other.pendingEdges) AddEdge(edge); } if (other.edges != null) { foreach (GraphPoint edge in other.edges) AddEdge(edge); } }
public GraphPoint[] GetEdgemostPoints(bool returnClones = false) { if(DataPoints.Count == 0) return null; GraphPoint[] ret = new GraphPoint[] { (GraphPoint)DataPoints[0], (GraphPoint)DataPoints[0], (GraphPoint)DataPoints[0], (GraphPoint)DataPoints[0], (GraphPoint)DataPoints[0], (GraphPoint)DataPoints[0] }; GraphPoint curPoint = null; for (int i = 0; i < DataPoints.Count; i++) { curPoint = (GraphPoint)DataPoints[i]; if (curPoint.pos.X < ret[0].pos.X) ret[0] = curPoint; if (curPoint.pos.X > ret[1].pos.X) ret[1] = curPoint; if (curPoint.pos.Y < ret[2].pos.Y) ret[2] = curPoint; if (curPoint.pos.Y > ret[3].pos.Y) ret[3] = curPoint; if (curPoint.pos.Z < ret[4].pos.Z) ret[4] = curPoint; if (curPoint.pos.Z > ret[5].pos.Z) ret[5] = curPoint; } if (returnClones) { for (int i = 0; i < ret.Length; i++) ret[i] = new GraphPoint(ret[i]); } return ret; }
public List<uint> FormTrianglesWith(GraphPoint other, List<GraphPoint> alreadyMadeEdgesWith, bool bForQuadRendering = false) { List<uint> results = new List<uint>(); if (edges == null || other.edges == null || other.hasSetIndices) return results; List<GraphPoint> intersection = edges.Intersect(other.edges).ToList(); for (int i = 0; i < intersection.Count; i++) { if (intersection[i].hasSetIndices || intersection[i] == this || intersection[i] == other || alreadyMadeEdgesWith.Contains(intersection[i])) continue; if (bForQuadRendering) results.Add((uint)index); results.Add((uint)index); results.Add((uint)other.index); results.Add((uint)intersection[i].index); } return results; }
public double DistanceFromSq(GraphPoint other) { return (pos - other.pos).LengthSquared; }
public List<uint> FormQuadsWith(GraphPoint other) { List<uint> results = new List<uint>(); if (edges == null || other.hasSetIndices) return results; foreach (GraphPoint edge1 in edges) { if (edge1.edges == null) continue; foreach (GraphPoint edge2 in edges) { if (edge1 == edge2 || edge2.edges == null) continue; List<GraphPoint> intersection = edge1.edges.Intersect(edge2.edges).ToList(); if (intersection.Count > 0) { for (int i = 0; i < intersection.Count; i++) { if (intersection[i].hasSetIndices || intersection[i] == this || intersection[i] == edge1 || intersection[i] == edge2) continue; results.Add((uint)index); results.Add((uint)edge1.index); results.Add((uint)intersection[i].index); results.Add((uint)edge2.index); } } else if (edge1.edges.Contains(edge2)) //Add a tri instead if possible { results.Add((uint)index); results.Add((uint)index); results.Add((uint)edge1.index); results.Add((uint)edge2.index); } } } return results; }
public double DistanceFrom(GraphPoint other) { return (pos - other.pos).Length; }
public double DistanceFromLineSegSq(GraphPoint segA, GraphPoint segB) { Vector3 ta = (segA.pos - this.pos); Vector3 tb = (segB.pos - this.pos); Vector3 ab = (segB.pos - segA.pos); float e = Vector3.Dot(tb, ta); if (e < 0) return Vector3.Dot(tb, tb); float f = Vector3.Dot(ta, ta); if (e >= f) return Vector3.Dot(ab, ab); return Vector3.Dot(tb, tb) - e * e / f; }
public static GraphPoint GetMidpoint(GraphPoint a, GraphPoint b) { return new GraphPoint(a.pos + (b.pos - a.pos) * 0.5f); }
public void AddEdge(GraphPoint edge) { if (edges == null) edges = new List<GraphPoint>(); if (!edges.Contains(edge)) edges.Add(edge); }
public static DataSeries CreateHullFromSeries(DataSeries source, int iterationCount) { GraphPoint[] edges = source.GetEdgemostPoints(true); if (edges == null) return null; MaxIterationCount = iterationCount; for (int i = 0; i < edges.Length; i++) edges[i] = new GraphPoint(edges[i]); PendingFaces.Clear(); ActiveFaces.Clear(); List<GraphPoint> AvailablePoints = new List<GraphPoint>(); foreach (object point in source.DataPoints) AvailablePoints.Add(new GraphPoint((GraphPoint)point)); //DataSeries hullSeries = new DataSeries(source.Name + "_Hull", source.DrawColor); DataSeries hullSeries = new DataSeries(source.Name + "_Hull", null); GraphPoint baseLine1 = null, baseLine2 = null, farthestBaseLine = null, farthestBaseFace = null; double bestDist = 0, curDist = 0; for (int i = 0; i < edges.Length; i++) { for (int j = 1; j < edges.Length; j++) { if (i == j) continue; curDist = edges[i].DistanceFromSq(edges[j]); if (curDist > bestDist) { baseLine1 = edges[i]; baseLine2 = edges[j]; bestDist = curDist; } } } bestDist = 0; for (int i = 0; i < edges.Length; i++) { if (edges[i].pos == baseLine1.pos || edges[i].pos == baseLine2.pos) continue; curDist = edges[i].DistanceFromLineSegSq(baseLine1, baseLine2); if (curDist > bestDist) { farthestBaseLine = edges[i]; bestDist = curDist; } } Vector3 triangleNormal = GetTriangleNormal(baseLine1.pos, baseLine2.pos, farthestBaseLine.pos); Vector3 triangleCenter = GetTriangleCenter(baseLine1.pos, baseLine2.pos, farthestBaseLine.pos); float triangleDot = Vector3.Dot(triangleNormal, baseLine1.pos); bestDist = 0; bool bFlipWinding = false; for (int i = 0; i < AvailablePoints.Count; i++) { if (AvailablePoints[i] == baseLine1 || AvailablePoints[i] == baseLine2 || AvailablePoints[i] == farthestBaseLine) continue; //curDist = (AvailablePoints[i].pos - triangleCenter).LengthSquared; curDist = Math.Abs(Vector3.Dot(AvailablePoints[i].pos, triangleNormal) - triangleDot); if (curDist > bestDist) { farthestBaseFace = AvailablePoints[i]; bestDist = curDist; bFlipWinding = Vector3.Dot(triangleNormal, (AvailablePoints[i].pos - triangleCenter).Normalized()) > 0; } } if (farthestBaseFace == null) //2D series { ClojureEngine.Log("[HULL BUILD] Series is 2D, and the hull builder cannot currently work with 2D data sets"); return null; } if (bFlipWinding) { GraphPoint temp = baseLine1; baseLine1 = baseLine2; baseLine2 = temp; } List<HullFace> initialFaces = new List<HullFace>() { new HullFace(baseLine2, baseLine1, farthestBaseLine), new HullFace(baseLine1, baseLine2, farthestBaseFace), new HullFace(baseLine1, farthestBaseFace, farthestBaseLine), new HullFace(baseLine2, farthestBaseLine, farthestBaseFace), }; AssignPointsToFaces(AvailablePoints, initialFaces); for (int i = 0; i < initialFaces.Count; i++) { ActiveFaces.Add(initialFaces[i]); if(initialFaces[i].points.Count > 0) PendingFaces.Add(initialFaces[i]); } BuildFromStack(0); int unassignedPoints = 0; for (int i = 0; i < ActiveFaces.Count; i++) { ActiveFaces[i].a.AddEdges(ActiveFaces[i].b, ActiveFaces[i].c); ActiveFaces[i].b.AddEdges(ActiveFaces[i].a, ActiveFaces[i].c); ActiveFaces[i].c.AddEdges(ActiveFaces[i].a, ActiveFaces[i].b); hullSeries.AddDataPoints(new List<GraphPoint>() { ActiveFaces[i].a, ActiveFaces[i].b, ActiveFaces[i].c }); unassignedPoints += ActiveFaces[i].points.Count; //if(ActiveFaces[i].points.Count > 0) // new DataSeries(PersistentVector.create1(ActiveFaces[i].points)); } if(unassignedPoints > 0) ClojureEngine.Log("[HULL BUILD] " + unassignedPoints + " points remain outside the hull"); else ClojureEngine.Log("[HULL BUILD] All points are contained within the hull"); hullSeries.SetDrawMode(DrawMode.Triangles); return hullSeries; }
public bool IsAVertex(GraphPoint p) { return p == a || p == b || p == c; }
public HullFace(GraphPoint nA, GraphPoint nB, GraphPoint nC, List<GraphPoint> nMyPoints) : this(nA, nB, nC) { points = nMyPoints; }
public HullFace(GraphPoint nA, GraphPoint nB, GraphPoint nC) { a = nA; b = nB; c = nC; ab = new HullEdge(a, b); bc = new HullEdge(b, c); ca = new HullEdge(c, a); normal = GetTriangleNormal(a.pos, b.pos, c.pos); center = GetTriangleCenter(a.pos, b.pos, c.pos); points = new List<GraphPoint>(); }
public HullEdge(GraphPoint nA, GraphPoint nB) { a = nA; b = nB; }