public void Build(List <Polygon> polygons) { if (polygons.Count == 0) { return; } if (Plane == null) { Plane = polygons[0].Plane.Clone(); } var pp = Plane.ToPrecisionPlane(); var front = new List <Polygon>(); var back = new List <Polygon>(); foreach (var polygon in polygons.Select(x => x.ToPrecisionPolygon())) { polygon.Split(pp, out var b, out var f, out var cb, out var cf); if (f != null) { front.Add(f.ToStandardPolygon()); } if (b != null) { back.Add(b.ToStandardPolygon()); } if (cf != null) { front.Add(cf.ToStandardPolygon()); } if (cb != null) { back.Add(cb.ToStandardPolygon()); } } if (front.Count > 0) { if (Front == null) { Front = new CsgNode(); } Front.Build(front); } if (back.Count > 0) { if (Back == null) { Back = new CsgNode(); } Back.Build(back); } }
private List <Polygon> ClipPolygons(IEnumerable <Polygon> polygons) { if (Plane == null) { return(polygons.ToList()); } var pp = Plane.ToPrecisionPlane(); var front = new List <Polygon>(); var back = new List <Polygon>(); foreach (var polygon in polygons.Select(x => x.ToPrecisionPolygon())) { polygon.Split(pp, out var b, out var f, out var cb, out var cf); if (f != null) { front.Add(f.ToStandardPolygon()); } if (b != null) { back.Add(b.ToStandardPolygon()); } if (cf != null) { front.Add(cf.ToStandardPolygon()); } if (cb != null) { back.Add(cb.ToStandardPolygon()); } } if (Front != null) { front = Front.ClipPolygons(front); } back = Back != null?Back.ClipPolygons(back) : new List <Polygon>(); return(front.Concat(back).ToList()); }
protected override void Render(MapDocument document, BufferBuilder builder, ResourceCollector resourceCollector) { base.Render(document, builder, resourceCollector); if (_state != ClipState.None && _clipPlanePoint1 != null && _clipPlanePoint2 != null && _clipPlanePoint3 != null) { // Draw the lines var p1 = _clipPlanePoint1.Value; var p2 = _clipPlanePoint2.Value; var p3 = _clipPlanePoint3.Value; builder.Append( new [] { new VertexStandard { Position = p1, Colour = Vector4.One, Tint = Vector4.One }, new VertexStandard { Position = p2, Colour = Vector4.One, Tint = Vector4.One }, new VertexStandard { Position = p3, Colour = Vector4.One, Tint = Vector4.One }, }, new uint [] { 0, 1, 1, 2, 2, 0 }, new [] { new BufferGroup(PipelineType.Wireframe, CameraType.Both, 0, 6) } ); if (!p1.EquivalentTo(p2) && !p2.EquivalentTo(p3) && !p1.EquivalentTo(p3) && !document.Selection.IsEmpty) { var plane = new Plane(p1, p2, p3); var pp = plane.ToPrecisionPlane(); // Draw the clipped solids var faces = new List <Polygon>(); foreach (var solid in document.Selection.OfType <Solid>().ToList()) { var s = solid.ToPolyhedron().ToPrecisionPolyhedron(); s.Split(pp, out var back, out var front); if (_side != ClipSide.Front && back != null) { faces.AddRange(back.Polygons.Select(x => x.ToStandardPolygon())); } if (_side != ClipSide.Back && front != null) { faces.AddRange(front.Polygons.Select(x => x.ToStandardPolygon())); } } var verts = new List <VertexStandard>(); var indices = new List <int>(); foreach (var polygon in faces) { var c = verts.Count; verts.AddRange(polygon.Vertices.Select(x => new VertexStandard { Position = x, Colour = Vector4.One, Tint = Vector4.One })); for (var i = 0; i < polygon.Vertices.Count; i++) { indices.Add(c + i); indices.Add(c + (i + 1) % polygon.Vertices.Count); } } builder.Append( verts, indices.Select(x => (uint)x), new[] { new BufferGroup(PipelineType.Wireframe, CameraType.Both, 0, (uint)indices.Count) } ); // Draw the clipping plane var poly = new DataStructures.Geometric.Precision.Polygon(pp); var bbox = document.Selection.GetSelectionBoundingBox(); var point = bbox.Center; foreach (var boxPlane in bbox.GetBoxPlanes()) { var proj = boxPlane.Project(point); var dist = (point - proj).Length() * 0.1f; var pln = new Plane(boxPlane.Normal, proj + boxPlane.Normal * Math.Max(dist, 100)).ToPrecisionPlane(); if (poly.Split(pln, out var b, out _)) { poly = b; } } verts.Clear(); indices.Clear(); var clipPoly = poly.ToStandardPolygon(); var colour = Color.FromArgb(64, Color.Turquoise).ToVector4(); // Add the face in both directions so it renders on both sides var polies = new[] { clipPoly.Vertices.ToList(), clipPoly.Vertices.Reverse().ToList() }; foreach (var p in polies) { var offs = verts.Count; verts.AddRange(p.Select(x => new VertexStandard { Position = x, Colour = Vector4.One, Tint = colour, Flags = VertexFlags.FlatColour })); for (var i = 2; i < clipPoly.Vertices.Count; i++) { indices.Add(offs); indices.Add(offs + i - 1); indices.Add(offs + i); } } builder.Append( verts, indices.Select(x => (uint)x), new[] { new BufferGroup(PipelineType.TexturedAlpha, CameraType.Perspective, p1, 0, (uint)indices.Count) } ); } } }
/// <summary> /// Creates a polygon from a plane and a radius. /// Expands the plane to the radius size to create a large polygon with 4 vertices. /// This constructor uses high-precision operations. /// </summary> /// <param name="plane">The polygon plane</param> /// <param name="radius">The polygon radius</param> public Polygon(Plane plane, float radius = 100000f) { Vertices = new Precision.Polygon(plane.ToPrecisionPlane(), radius).Vertices.Select(x => x.ToStandardVector3()).ToList(); }