List <Segment2D> BuildContourSegments(Triangulation2D triangulation) { var triangles = teddy.triangulation.Triangles; var contour = new List <Segment2D>(); var table = new Dictionary <Segment2D, HashSet <Triangle2D> >(); for (int i = 0, n = triangles.Length; i < n; i++) { var t = triangles[i]; if (!table.ContainsKey(t.s0)) { table.Add(t.s0, new HashSet <Triangle2D>()); } if (!table.ContainsKey(t.s1)) { table.Add(t.s1, new HashSet <Triangle2D>()); } if (!table.ContainsKey(t.s2)) { table.Add(t.s2, new HashSet <Triangle2D>()); } table[t.s0].Add(t); table[t.s1].Add(t); table[t.s2].Add(t); } contour = table.Keys.ToList().FindAll(s => { return(table[s].Count == 1); }).ToList(); return(contour); }
void Awake() { // input points for a polygon2D contour List <Vector2> points = new List <Vector2>(); // When calling PopulateSquarePerimeter you should prefer // a factor of 4 for the 'res' argument. PopulateSquarePerimeter(points, 1000, 20); // construct Polygon2D Polygon2D polygon = Polygon2D.Contour(points.ToArray()); // construct Triangulation2D with Polygon2D and threshold angle (18f ~ 27f recommended) Triangulation2D triangulation = new Triangulation2D(polygon, 22.5f); // build a mesh from triangles in a Triangulation2D instance Mesh mesh = triangulation.Build(); // Initialize gameObject // assuming it starts out as an empty object gameObject.AddComponent <MeshFilter>(); // GetComponent<MeshFilter>().sharedMesh = mesh; //gameObject.GetComponent<MeshFilter>().sharedMesh = mesh; gameObject.GetComponent <MeshFilter>().mesh = mesh; // gameObject.AddComponent<MeshRenderer>(); //gameObject.AddComponent<MeshCollider>(); gameObject.SetActive(false); }
public void SetTriangulation(Triangulation2D triangulation) { var mesh = triangulation.Build(); GetComponent <MeshFilter>().sharedMesh = mesh; this.triangles = triangulation.Triangle2Ds; }
protected Dictionary <Vertex2D, VertexNetwork2D> BuildTable(Triangulation2D tri) { var table = new Dictionary <Vertex2D, VertexNetwork2D>(); var triangles = tri.Triangles; for (int i = 0, n = triangles.Length; i < n; i++) { var t = triangles[i]; Vertex2D a = t.a, b = t.b, c = t.c; if (!table.ContainsKey(a)) { table.Add(a, new VertexNetwork2D(a, ExternalPoint(a))); } if (!table.ContainsKey(b)) { table.Add(b, new VertexNetwork2D(b, ExternalPoint(b))); } if (!table.ContainsKey(c)) { table.Add(c, new VertexNetwork2D(c, ExternalPoint(c))); } } // tri.Points.ForEach(p => { // if(!table.ContainsKey(p)) table.Add(p, new VertexNetwork2D(p, ExternalPoint(p))); // }); return(table); }
public Teddy(List <Vector2> points) { var polygon = Polygon2D.Contour(points.ToArray()); triangulation = new Triangulation2D(polygon, 0f); Init(triangulation); }
protected void Sew(Triangulation2D triangulation, Chord2D chord, Dictionary <Vertex2D, float> heightTable, int division) { var triangles = triangulation.Triangles.ToList(); Dictionary <Triangle2D, bool> flags = new Dictionary <Triangle2D, bool>(); // 既にSew済みのTriangle2Dを再度Sewする必要があるケースが存在する // 特定のChord2DのSrcとDstを含むTriangle2Dなのに,それ以外のChord2Dと共通点を持っているがために // Spineと共通エッジを持つ場合のSewの処理がかけられず適切な分割ができていないケース Dictionary <Triangle2D, List <Triangle2D> > sews = new Dictionary <Triangle2D, List <Triangle2D> >(); triangles.ForEach(t => flags.Add(t, false)); SewRoutine(triangles, flags, sews, chord, null, division); }
/// <summary> /// This method returns a 3D representation of this area /// </summary> /// <param name="nodesDict">List of all the nodes on the map</param> /// <param name="map">bounds of the map</param> /// <param name="brush">Color of this area</param> /// <returns>ModelUIElement3D of this area</returns> public virtual ModelUIElement3D get3DSurface(Dictionary <long, OsmSharp.Osm.Node> nodesDict, Map map, System.Windows.Media.SolidColorBrush brush) { List <PointF> ptlist = getScaledPointsSurface(nodesDict, map); // Divide the polygons in triangles, this is code (and these two classes) are from: https://polygontriangulation.codeplex.com/ PolygonData poly = new PolygonData(ptlist); List <PointF[]> triangles = Triangulation2D.Triangulate(poly); // Surrounding tags of the mesh ModelUIElement3D model = new ModelUIElement3D(); GeometryModel3D geometryModel = new GeometryModel3D(); // Mesh and his his properties MeshGeometry3D mesh = new MeshGeometry3D(); DiffuseMaterial material = new DiffuseMaterial((System.Windows.Media.Brush)brush); Point3DCollection positions = new Point3DCollection(); Int32Collection indices = new Int32Collection(); // Add points and indices to their collection foreach (PointF[] points in triangles) { foreach (PointF point in points) { positions.Add(new Point3D(point.X, point.Y, height)); } int count = positions.Count; indices.Add(count - 3); indices.Add(count - 2); indices.Add(count - 1); } // Add these collections to the mesh mesh.Positions = positions; mesh.TriangleIndices = indices; // Set the color of front and back of the triangle geometryModel.Material = material; geometryModel.BackMaterial = material; // Add the mesh to the model geometryModel.Geometry = mesh; model.Model = geometryModel; return(model); }
void Build() { points = Utils2D.Constrain(points, threshold); var polygon = Polygon2D.Contour(points.ToArray()); var vertices = polygon.Vertices; if (vertices.Length < 3) { return; // error } var triangulation = new Triangulation2D(polygon, angle); var go = Instantiate(prefab); go.transform.SetParent(transform, false); go.GetComponent <DemoMesh>().SetTriangulation(triangulation); Clear(); }
//called when data for any output pin is requested public void Evaluate(int SpreadMax) { int i = 0; FOutput.SliceCount = FInput.SliceCount; foreach (var input in FInput) { if (FEnabled[i]) { if (input.Any()) { var polygon = new Polygon(input.ToList()); var triangles = Triangulation2D.Triangulate(polygon); FOutput[i].AssignFrom(triangles.SelectMany(t => t)); } } i++; } //FLogger.Log(LogType.Debug, "hi tty!"); }
void Init(Triangulation2D triangulation) { contourSegments = BuildContourSegments(triangulation); var triangles = triangulation.Triangles.ToList(); faces = Categorize(triangles); var terminal = faces.Find(f => f.Type == Face2DType.Terminal); chord = GetChordalAxis(terminal, faces); var terminalChords = Traverse(chord, null, (Chord2D c) => { return(c.Face.Type == Face2DType.Terminal); }); var convergence = new List <Vertex2D>(); terminalChords.ForEach(c => { Prune(c, convergence); }); Subdivide(chord); // var spine = GetSpinePoints(chord); var networkTable = BuildTable(triangulation); networks = BuildNetworks(triangulation, networkTable); Elevate(networks); heightTable = new Dictionary <Vertex2D, float>(); foreach (Vertex2D v in networkTable.Keys) { heightTable.Add(v, networkTable[v].Height); } Sew(triangulation, chord, heightTable, 3); }
protected List <VertexNetwork2D> BuildNetworks(Triangulation2D tri, Dictionary <Vertex2D, VertexNetwork2D> networkTable) { var network = new Dictionary <Vertex2D, HashSet <Vertex2D> >(); var triangles = tri.Triangles; for (int i = 0, n = triangles.Length; i < n; i++) { var t = triangles[i]; Segment2D s0 = t.s0, s1 = t.s1, s2 = t.s2; if (!network.ContainsKey(t.a)) { network.Add(t.a, new HashSet <Vertex2D>()); } if (!network.ContainsKey(t.b)) { network.Add(t.b, new HashSet <Vertex2D>()); } if (!network.ContainsKey(t.c)) { network.Add(t.c, new HashSet <Vertex2D>()); } network[s0.a].Add(s0.b); network[s0.b].Add(s0.a); network[s1.a].Add(s1.b); network[s1.b].Add(s1.a); network[s2.a].Add(s2.b); network[s2.b].Add(s2.a); } return(network.Keys.Select(v => { var n = networkTable[v]; foreach (Vertex2D to in network[v]) { n.Connect(networkTable[to]); } return n; }).ToList()); }
protected List <Triangle2D> Sew(Dictionary <Vertex2D, float> heightTable, Triangulation2D tri, Segment2D left, Segment2D right, int division) { Vertex2D top, lb, rb; if (left.a == right.a) { top = left.a; lb = left.b; rb = right.b; } else if (left.a == right.b) { top = left.a; lb = left.b; rb = right.a; } else if (left.b == right.a) { top = left.b; lb = left.a; rb = right.b; } else { top = left.b; lb = left.a; rb = right.a; } Vertex2D[] lp = new Vertex2D[division]; Vertex2D[] rp = new Vertex2D[division]; lp[division - 1] = lb; rp[division - 1] = rb; float inv = 1f / division; Vector2 ld = lb.Coordinate - top.Coordinate, rd = rb.Coordinate - top.Coordinate; float lm = ld.magnitude, rm = rd.magnitude; // float th = heightTable[top], lh = heightTable[lb], rh = heightTable[rb]; float th = heightTable[top], lh = heightTable[lb] - th, rh = heightTable[rb] - th; for (int i = 0; i < division - 1; i++) { float r = (float)(i + 1) * inv; lp[i] = triangulation.CheckAndAddVertex(top.Coordinate + ld * r); if (!heightTable.ContainsKey(lp[i])) { // heightTable.Add(lp[i], th + (lh - th) * inv * (i + 1)); heightTable.Add(lp[i], th + QuarterOval(lh, lm, inv * (i + 1))); } rp[i] = triangulation.CheckAndAddVertex(top.Coordinate + rd * r); if (!heightTable.ContainsKey(rp[i])) { // heightTable.Add(rp[i], th + (rh - th) * inv * (i + 1)); heightTable.Add(rp[i], th + QuarterOval(rh, rm, inv * (i + 1))); } } var triangles = new List <Triangle2D>(); triangles.Add(triangulation.AddTriangle(top, lp[0], rp[0])); for (int i = 0; i < division - 1; i++) { var tl = triangulation.AddTriangle(lp[i], rp[i], lp[i + 1]); var tr = triangulation.AddTriangle(rp[i], rp[i + 1], lp[i + 1]); triangles.Add(tl); triangles.Add(tr); } return(triangles); }
void Sew(Triangulation2D triangulation, Chord2D chord, Dictionary <Vertex2D, float> heightTable, int division) { var triangles = triangulation.Triangles.ToList(); Dictionary <Triangle2D, bool> flags = new Dictionary <Triangle2D, bool>(); // 既にSew済みのTriangle2Dを再度Sewする必要があるケースが存在する // 特定のChord2DのSrcとDstを含むTriangle2Dなのに,それ以外のChord2Dと共通点を持っているがために // Spineと共通エッジを持つ場合のSewの処理がかけられず適切な分割ができていないケース Dictionary <Triangle2D, List <Triangle2D> > sews = new Dictionary <Triangle2D, List <Triangle2D> >(); triangles.ForEach(t => flags.Add(t, false)); Action <Triangle2D, Segment2D[]> SewTriangle = (Triangle2D t, Segment2D[] segments) => { triangulation.RemoveTriangle(t); var sewTriangles = Sew(heightTable, triangulation, segments[0], segments[1], division); sews.Add(t, sewTriangles); flags[t] = true; }; Action <Chord2D, Chord2D> SewRoutine; SewRoutine = (Chord2D current, Chord2D from) => { if (!current.Pruned) { triangles.FindAll(t => { return(t.HasPoint(current.Src) && (t.HasPoint(current.Dst) || !sews.ContainsKey(t))); }).ForEach(t => { Segment2D[] segments; if (sews.ContainsKey(t)) { foreach (Triangle2D st in sews[t]) { triangulation.RemoveTriangle(st); } sews.Remove(t); } if (t.HasPoint(current.Dst)) { Segment2D s = t.CommonSegment(current.Src, current.Dst); segments = t.ExcludeSegment(s); } else { segments = t.CommonSegments(current.Src); } SewTriangle(t, segments); }); } var next = current.Connection.FindAll(con => con != from); // Prune後のSpineで末端にあたる頂点 bool terminal = next.All(con => con.Pruned); if (terminal && !current.Pruned) { triangles.FindAll(t => { return(!sews.ContainsKey(t) && t.HasPoint(current.Dst)); }).ForEach(t => { var segments = t.CommonSegments(current.Dst); SewTriangle(t, segments); }); } next.ForEach(to => { SewRoutine(to, current); }); }; SewRoutine(chord, null); }