public Tabs(LineStrip boundary, float toolRadius, bool inside = false) { originalBoundary = new Slice(new LineStrip[] { boundary }, new Plane(Vector3.UnitZ, Vector3.Zero)); float offset = toolRadius; if (inside) { offset = -offset; } Slice slice = new Slice(originalBoundary); slice.Offset(offset); this.boundary = slice.GetLines(Slice.LineType.Outside).First(s => true); this.toolRadius = toolRadius; float length = this.boundary.Length(LineStrip.Type.Closed); int numTabs = (int)(length / desiredSpacing); if (numTabs < minTabs) { numTabs = 0; } float tabSpacing = length / numTabs; tabLocations = new List<Vector3>(); foreach (var point in this.boundary.PointsAlongLine(tabSpacing, tabSpacing / 2.0f)) { tabLocations.Add(point); } }
public void GenerateTabPaths(float toolRadius) { tabs.Clear(); try { Slice s = new Slice(this, new Plane(Vector3.UnitZ, new Vector3(0, 0, MinPoint.Z + 0.002f))); foreach (var line in s.GetLines(Slice.LineType.Outside)) { tabs.Add(new TabsGUI(line, toolRadius, false)); } foreach (var line in s.GetLines(Slice.LineType.Hole)) { tabs.Add(new TabsGUI(line, toolRadius, true)); } } catch (Exception) { } this.Offset = offset; // Force the offset update in the tabs }
public Slice(TriangleMesh mesh, Plane plane) { //GL.Disable(EnableCap.Lighting); //GL.LineWidth(2); //GL.Begin(PrimitiveType.Lines); //float height = 0; // Slice at 3 levels and combine all segments - this obviates dealing with triangles that are exactly on the plane. for (int i = -1; i <= 1; i++) { Vector3 offset = plane.Normal * 0.0001f * (float)i; LineHandler lineHandler = new LineHandler(0.0f); Plane testPlane = new Plane(plane.Normal, plane.Point + offset); foreach (Triangle t in mesh.Triangles) { var intersect = new TrianglePlaneIntersect(t, testPlane); if (intersect.Intersects) { lineHandler.AddSegment(intersect.PointA, intersect.PointB); //GL.Color3(Color.Blue); //GL.Vertex3(intersect.PointA + new Vector3(0, 0, height + .01f)); //GL.Color3(Color.Red); //GL.Vertex3(intersect.PointB + new Vector3(0, 0, height + .01f)); } else if (intersect.all_intersect && Vector3.Dot(t.Plane.Normal, testPlane.Normal) > 0.5f) { // Entire triangle intersects // Add all the triangle edges (TODO: clean this up...) List<Vector3> vertices = new List<Vector3>(t.Vertices); for (int a = 0; a < 3; a++) { Vector3 v1 = vertices[a]; Vector3 v2 = vertices[(a + 1) % 3]; lineHandler.AddSegment(v1, v2); } } } if (this.polyTree == null) { Init(lineHandler.GetOuterLoops(), plane); } else { Slice s = new Slice(lineHandler.GetOuterLoops(), plane); this.Union(s); } } //GL.End(); //GL.Enable(EnableCap.Lighting); //GL.LineWidth(1); }
private Slice GetPairs(bool outside) { Slice s = new Slice(this); PolyNode n = polyTree.GetFirst(); Paths polygons = new Paths(); while (null != n) { int depth = 0; PolyNode parent = n.Parent; while (parent != null) { depth++; parent = parent.Parent; } int test = (depth - 1) % 4; if ((outside && test < 2) || (!outside && test >= 2)) { polygons.Add(n.Contour); } n = n.GetNext(); } s.polyTree = PolygonsToPolyTree(polygons); return s; }
public void Union(Slice other) { Clipper c = new Clipper(); c.Clear(); c.AddPaths(Clipper.PolyTreeToPaths(polyTree), PolyType.ptSubject, true); c.AddPaths(Clipper.PolyTreeToPaths(other.polyTree), PolyType.ptClip, true); polyTree = new PolyTree(); c.Execute(ClipType.ctUnion, polyTree); }
public void SubtractFrom(Slice other) { Clipper c = new Clipper(); c.Clear(); c.AddPaths(PolyTreeToPolygons(other.polyTree), PolyType.ptSubject, true); c.AddPaths(PolyTreeToPolygons(polyTree), PolyType.ptClip, true); polyTree = new PolyTree(); c.Execute(ClipType.ctDifference, polyTree); }
public Slice PolygonsWithoutHoles() { Slice s = new Slice(this); PolyNode n = polyTree.GetFirst(); Paths polygons = new Paths(); while (null != n) { if (!n.IsHole && n.ChildCount == 0) { polygons.Add(n.Contour); } n = n.GetNext(); } s.polyTree = PolygonsToPolyTree(polygons); return s; }
/// <summary> /// Get all the polygons which contain holes /// </summary> /// <returns></returns> public Slice PolygonsWithHoles() { Slice s = new Slice(this); PolyNode n = polyTree.GetFirst(); Paths polygons = new Paths(); while (null != n) { if (n.IsHole) { if (!polygons.Contains(n.Parent.Contour)) { polygons.Add(n.Parent.Contour); } polygons.Add(n.Contour); } n = n.GetNext(); } s.polyTree = PolygonsToPolyTree(polygons); return s; }
public IEnumerable<Slice> IndividualPolygons() { PolyNode n = polyTree.GetFirst(); Paths polygons = new Paths(); while (null != n) { if (!n.IsHole && polygons.Count > 0) { Slice s = new Slice(this); s.polyTree = PolygonsToPolyTree(polygons); yield return s; polygons = new Paths(); } polygons.Add(n.Contour); n = n.GetNext(); } if (polygons.Count > 0) { Slice s = new Slice(this); s.polyTree = PolygonsToPolyTree(polygons); yield return s; } }
public bool Contains(Slice other) { // To contain another slice: // 1. Area of the union must be the same // 2. Area of this - other must be less float thisArea = this.Area(); Paths otherPolygons = Clipper.PolyTreeToPaths(other.polyTree); Paths thesePolygons = Clipper.PolyTreeToPaths(polyTree); Slice s = new Slice(this); Clipper c = new Clipper(); c.Clear(); c.AddPaths(thesePolygons, PolyType.ptSubject, true); c.AddPaths(otherPolygons, PolyType.ptClip, true); s.polyTree = new PolyTree(); c.Execute(ClipType.ctUnion, s.polyTree); float area_union = s.Area(); if (area_union > thisArea) { return false; } return true; //c.Clear(); //c.AddPaths(thesePolygons, PolyType.ptSubject, true); //c.AddPaths(otherPolygons, PolyType.ptClip, true); //s.polyTree = new PolyTree(); //c.Execute(ClipType.ctDifference, s.polyTree); //float area_difference = s.Area(); //if (area_difference < thisArea) //{ // return true; //} //return false; }
public Slice(Slice fromSlice) { this.plane = fromSlice.plane; this.transform = fromSlice.transform; this.inverseTransform = fromSlice.inverseTransform; this.polyTree = fromSlice.polyTree; }
public void Draw() { GL.PushMatrix(); GL.Translate(locationOffset); if (mouseHovering) { var ticks = DateTime.Now.Ticks; int alpha = (int)(100 * (Math.Sin(((double)(ticks / 10000))/300.0d) + 1)); Vector3 location = hoveredPoint; GL.Color4(Color.FromArgb(alpha, Color.Green)); if (selectedTabIndex >= 0) { location = tabLocations[selectedTabIndex]; GL.Color3(Color.Blue); } Polyhedra.DrawCylinderWireMesh(location, location + new Vector3(0, 0, tabHeight), this.tabRadius); } GL.Color3(Color.Orange); if (drawSliceDisplayList > 0) { GL.CallList(drawSliceDisplayList); } else { if (useDisplayLists) { drawSliceDisplayList = GL.GenLists(1); GL.NewList(drawSliceDisplayList, ListMode.CompileAndExecute); } GL.Begin(PrimitiveType.Triangles); GL.Normal3(drawSlice.Plane.Normal); foreach (var triangle in drawSlice.Triangles()) { foreach (var point in triangle.Vertices) { GL.Vertex3(point); } } GL.End(); if (useDisplayLists) { GL.EndList(); } } if (tabLocations.Count == 0) { GL.Color3(Color.DarkRed); if (obliterateIndicateDisplayList > 0) { GL.CallList(obliterateIndicateDisplayList); } else { Slice s = new Slice(Boundary); s.Subtract(drawSlice); obliterateIndicateDisplayList = GL.GenLists(1); GL.NewList(obliterateIndicateDisplayList, ListMode.CompileAndExecute); GL.Begin(PrimitiveType.Triangles); GL.Normal3(s.Plane.Normal); foreach (var triangle in s.Triangles()) { foreach (var point in triangle.Vertices) { GL.Vertex3(point); } } GL.End(); GL.EndList(); } } GL.Color3(Color.DarkOrange); int i = 0; foreach (var tab in tabLocations) { if (!selectedTabDraggedOff || i != selectedTabIndex) { Polyhedra.DrawCylinder(tab + new Vector3(0, 0, .001f), tab + new Vector3(0, 0, tabHeight), this.tabRadius); } i++; } GL.PopMatrix(); }
public TabsGUI(LineStrip boundary, float toolRadius, bool inside = false) : base(boundary, toolRadius, inside) { drawSlice = new Slice(this.TabPath, toolRadius * 2.0f, new Plane(Vector3.UnitZ, Vector3.Zero), true); }