public static Solid CreateFromIntersectingPlanes(IEnumerable<Plane> planes, IDGenerator generator) { var solid = new Solid(generator.GetNextObjectID()); var list = planes.ToList(); for (var i = 0; i < list.Count; i++) { // Split the polygon by all the other planes var poly = new Polygon(list[i]); for (var j = 0; j < list.Count; j++) { if (i != j) poly.Split(list[j]); } // The final polygon is the face var face = new Face(generator.GetNextFaceID()) { Plane = poly.Plane , Parent = solid }; face.Vertices.AddRange(poly.Vertices.Select(x => new Vertex(x, face))); face.UpdateBoundingBox(); face.AlignTextureToWorld(); solid.Faces.Add(face); } // Ensure all the faces point outwards var origin = solid.GetOrigin(); foreach (var face in solid.Faces) { if (face.Plane.OnPlane(origin) >= 0) face.Flip(); } solid.UpdateBoundingBox(); return solid; }
public void BenchmarkSolidConstruction() { var idg = new IDGenerator(); var box = new Box(Coordinate.One * -100, Coordinate.One * 100); var planes = new CylinderBrush().Create(idg, box, null, 2).OfType<Solid>().SelectMany(x => x.Faces).Select(x => x.Plane).ToList(); var stopwatch = new Stopwatch(); stopwatch.Start(); for (var b = 0; b < 1000; b++) { Solid.CreateFromIntersectingPlanes(planes, idg); } stopwatch.Stop(); Debug.WriteLine(stopwatch.Elapsed); stopwatch.Restart(); for (var b = 0; b < 1000; b++) { var polys = new List<Polygon>(); for (var i = 0; i < planes.Count; i++) { var poly = new Polygon(planes[i]); for (var j = 0; j < planes.Count; j++) { if (i != j) poly.Split(planes[j]); } polys.Add(poly); } var solid = new Solid(idg.GetNextObjectID()); foreach (var polygon in polys) { var face = new Face(idg.GetNextFaceID()) {Plane = polygon.Plane}; face.Vertices.AddRange(polygon.Vertices.Select(x => new Vertex(x, face))); face.UpdateBoundingBox(); face.AlignTextureToWorld(); solid.Faces.Add(face); } solid.UpdateBoundingBox(); } stopwatch.Stop(); Debug.WriteLine(stopwatch.Elapsed); }
private void Split(object sender) { var face = GetSplitFace(); if (face == null) return; var solid = face.Parent; var sel = MainTool.Points.Where(x => x.IsSelected).ToList(); var p1 = sel[0]; var p2 = sel[1]; if (p1.IsMidPoint) AddAdjacentPoint(face, p1); if (p2.IsMidPoint) AddAdjacentPoint(face, p2); var polygon = new Polygon(face.Vertices.Select(x => x.Location)); var clip = new Plane(p1.Coordinate, p2.Coordinate, p1.Coordinate + face.Plane.Normal * 10); Polygon back, front; polygon.Split(clip, out back, out front); if (back == null || front == null) return; solid.Faces.Remove(face); face.Parent = null; CreateFace(back, solid, face); CreateFace(front, solid, face); solid.UpdateBoundingBox(); MainTool.SetDirty(true, true); }
private void Render3D(Viewport3D vp) { if (_state == ClipState.None || _clipPlanePoint1 == null || _clipPlanePoint2 == null || _clipPlanePoint3 == null || Document.Selection.IsEmpty()) return; // Nothing to draw at this point TextureHelper.Unbind(); // Draw points if (!_clipPlanePoint1.EquivalentTo(_clipPlanePoint2) && !_clipPlanePoint2.EquivalentTo(_clipPlanePoint3) && !_clipPlanePoint1.EquivalentTo(_clipPlanePoint3)) { var plane = new Plane(_clipPlanePoint1, _clipPlanePoint2, _clipPlanePoint3); // Draw clipped solids GL.Enable(EnableCap.LineSmooth); GL.Hint(HintTarget.LineSmoothHint, HintMode.Nicest); var faces = new List<Face>(); var idg = new IDGenerator(); foreach (var solid in Document.Selection.GetSelectedObjects().OfType<Solid>().ToList()) { Solid back, front; if (solid.Split(plane, out back, out front, idg)) { if (_side != ClipSide.Front) faces.AddRange(back.Faces); if (_side != ClipSide.Back) faces.AddRange(front.Faces); } } GL.LineWidth(2); GL.Color3(Color.White); Rendering.Immediate.MapObjectRenderer.DrawWireframe(faces, true, false); GL.LineWidth(1); GL.Hint(HintTarget.LineSmoothHint, HintMode.Fastest); GL.Disable(EnableCap.LineSmooth); // Draw the clipping plane var poly = new Polygon(plane); var bbox = Document.Selection.GetSelectionBoundingBox(); var point = bbox.Center; foreach (var boxPlane in bbox.GetBoxPlanes()) { var proj = boxPlane.Project(point); var dist = (point - proj).VectorMagnitude() * 0.1m; poly.Split(new Plane(boxPlane.Normal, proj + boxPlane.Normal * Math.Max(dist, 100))); } GL.Disable(EnableCap.CullFace); GL.Begin(PrimitiveType.Polygon); GL.Color4(Color.FromArgb(100, Color.Turquoise)); foreach (var c in poly.Vertices) GL.Vertex3(c.DX, c.DY, c.DZ); GL.End(); GL.Enable(EnableCap.CullFace); } }
public void TestPolygonSplitting() { var planes = new[] { new Plane(new Coordinate(-64, 64, 64), new Coordinate(64, 64, 64), new Coordinate(64, -64, 64)), new Plane(new Coordinate(-64, -64, -64), new Coordinate(64, -64, -64), new Coordinate(64, 64, -64)), new Plane(new Coordinate(-64, 64, 64), new Coordinate(-64, -64, 64), new Coordinate(-64, -64, -64)), new Plane(new Coordinate(64, 64, -64), new Coordinate(64, -64, -64), new Coordinate(64, -64, 64)), new Plane(new Coordinate(64, 64, 64), new Coordinate(-64, 64, 64), new Coordinate(-64, 64, -64)), new Plane(new Coordinate(64, -64, -64), new Coordinate(-64, -64, -64), new Coordinate(-64, -64, 64)) }.ToList(); var polys = new List<Polygon>(); for (var i = 0; i < planes.Count; i++) { var poly = new Polygon(planes[i]); for (var j = 0; j < planes.Count; j++) { if (i != j) poly.Split(planes[j]); } polys.Add(poly); } Assert.AreEqual(6, polys.Count); }