Beispiel #1
0
        Solid UnionSub(Solid csg, bool retesselate, bool canonicalize)
        {
            if (!MayOverlap(csg))
            {
                return(UnionForNonIntersecting(csg));
            }
            else
            {
                var a = new Tree(Bounds, Polygons);
                var b = new Tree(csg.Bounds, csg.Polygons);

                a.ClipTo(b, false);
                b.ClipTo(a);
                b.Invert();
                b.ClipTo(a);
                b.Invert();

                var newpolygons = new List <Polygon>(a.AllPolygons());
                newpolygons.AddRange(b.AllPolygons());
                var result = Solid.FromPolygons(newpolygons);
                result.Properties = Properties.Merge(csg.Properties);
                if (retesselate)
                {
                    result = result.Retesselated();
                }
                if (canonicalize)
                {
                    result = result.Canonicalized();
                }
                return(result);
            }
        }
Beispiel #2
0
        public static Solid Cube(CubeOptions options)
        {
            var c = options.Center;
            var r = options.Radius.Abs;             // negative radii make no sense

            if (r.X == 0.0 || r.Y == 0.0 || r.Z == 0.0)
            {
                return(new Solid());
            }
            var result = Solid.FromPolygons(cubeData.Select(info =>
            {
                //var normal = new Vector3D(info[1]);
                //var plane = new Plane(normal, 1);
                var vertices = info[0].Select(i =>
                {
                    var pos = new Vector3D(
                        c.X + r.X * (2 * ((i & 1) != 0 ? 1 : 0) - 1),
                        c.Y + r.Y * (2 * ((i & 2) != 0 ? 1 : 0) - 1),
                        c.Z + r.Z * (2 * ((i & 4) != 0 ? 1 : 0) - 1));
                    return(new Vertex(pos));
                });
                return(new Polygon(vertices.ToList()));
            }).ToList());

            return(result);
        }
Beispiel #3
0
        Solid IntersectSub(Solid csg, bool retesselate, bool canonicalize)
        {
            var a = new Tree(Bounds, Polygons);
            var b = new Tree(csg.Bounds, csg.Polygons);

            a.Invert();
            b.ClipTo(a);
            b.Invert();
            a.ClipTo(b);
            b.ClipTo(a);
            a.AddPolygons(b.AllPolygons());
            a.Invert();

            var result = Solid.FromPolygons(a.AllPolygons());

            result.Properties = Properties.Merge(csg.Properties);
            if (retesselate)
            {
                result = result.Retesselated();
            }
            if (canonicalize)
            {
                result = result.Canonicalized();
            }
            return(result);
        }
Beispiel #4
0
 Solid Retesselated()
 {
     if (IsRetesselated)
     {
         return(this);
     }
     else
     {
         var csg = this;
         var polygonsPerPlane = new Dictionary <string, List <Polygon> >();
         var isCanonicalized  = csg.IsCanonicalized;
         var fuzzyFactory     = new FuzzyCsgFactory();
         foreach (var polygon in csg.Polygons)
         {
             var plane  = polygon.Plane;
             var shared = polygon.Shared;
             if (!isCanonicalized)
             {
                 plane  = fuzzyFactory.GetPlane(plane);
                 shared = fuzzyFactory.GetPolygonShared(shared);
             }
             var            tag = plane.Tag + "/" + shared.Tag;
             List <Polygon> ppp;
             if (polygonsPerPlane.TryGetValue(tag, out ppp))
             {
                 ppp.Add(polygon);
             }
             else
             {
                 ppp = new List <Polygon>();
                 ppp.Add(polygon);
                 polygonsPerPlane.Add(tag, ppp);
             }
         }
         var destpolygons = new List <Polygon>();
         foreach (var planetag in polygonsPerPlane)
         {
             var sourcepolygons = planetag.Value;
             if (sourcepolygons.Count < 2)
             {
                 destpolygons.AddRange(sourcepolygons);
             }
             else
             {
                 var retesselatedpolygons = new List <Polygon>();
                 Solid.RetesselateCoplanarPolygons(sourcepolygons, retesselatedpolygons);
                 destpolygons.AddRange(retesselatedpolygons);
             }
         }
         var result = Solid.FromPolygons(destpolygons);
         result.IsRetesselated = true;
         result.Properties     = Properties;
         return(result);
     }
 }
Beispiel #5
0
        Solid UnionForNonIntersecting(Solid csg)
        {
            var newpolygons = new List <Polygon>(Polygons);

            newpolygons.AddRange(csg.Polygons);
            var result = Solid.FromPolygons(newpolygons);

            result.Properties      = Properties.Merge(csg.Properties);
            result.IsCanonicalized = IsCanonicalized && csg.IsCanonicalized;
            result.IsRetesselated  = IsRetesselated && csg.IsRetesselated;
            return(result);
        }
Beispiel #6
0
        public Solid GetCsg(Solid sourcecsg)
        {
            var newpolygons = new List <Polygon>();

            foreach (var polygon in sourcecsg.Polygons)
            {
                var newpolygon = GetPolygon(polygon);
                if (newpolygon.Vertices.Count >= 3)
                {
                    newpolygons.Add(newpolygon);
                }
            }
            return(Solid.FromPolygons(newpolygons));
        }
Beispiel #7
0
        public Solid Transform(Matrix4x4 matrix4x4)
        {
            var ismirror            = matrix4x4.IsMirroring;
            var transformedvertices = new Dictionary <int, Vertex>();
            var transformedplanes   = new Dictionary <int, Plane>();
            var newpolygons         = new List <Polygon>();

            foreach (var p in Polygons)
            {
                Plane newplane;
                var   plane    = p.Plane;
                var   planetag = plane.Tag;
                if (transformedplanes.ContainsKey(planetag))
                {
                    newplane = transformedplanes[planetag];
                }
                else
                {
                    newplane = plane.Transform(matrix4x4);
                    transformedplanes[planetag] = newplane;
                }
                var newvertices = new List <Vertex>();
                foreach (var v in p.Vertices)
                {
                    Vertex newvertex;
                    var    vertextag = v.Tag;
                    if (transformedvertices.ContainsKey(vertextag))
                    {
                        newvertex = transformedvertices[vertextag];
                    }
                    else
                    {
                        newvertex = v.Transform(matrix4x4);
                        transformedvertices[vertextag] = newvertex;
                    }
                    newvertices.Add(newvertex);
                }
                if (ismirror)
                {
                    newvertices.Reverse();
                }
                newpolygons.Add(new Polygon(newvertices, p.Shared, newplane));
            }
            var result = Solid.FromPolygons(newpolygons);

            result.Properties      = this.Properties.Transform(matrix4x4);
            result.IsRetesselated  = this.IsRetesselated;
            result.IsCanonicalized = this.IsCanonicalized;
            return(result);
        }
Beispiel #8
0
        Solid SubtractSub(Solid csg, bool retesselate, bool canonicalize)
        {
            var a = new Tree(Bounds, Polygons);
            var b = new Tree(csg.Bounds, csg.Polygons);

            a.Invert();
            a.ClipTo(b);
            b.ClipTo(a, true);
            a.AddPolygons(b.AllPolygons());
            a.Invert();

            var result = Solid.FromPolygons(a.AllPolygons());

            if (retesselate)
            {
                result = result.Retesselated();
            }
            if (canonicalize)
            {
                result = result.Canonicalized();
            }
            return(result);
        }
Beispiel #9
0
        public static Solid Sphere(SphereOptions options)
        {
            var center = options.Center;
            var radius = Math.Abs(options.Radius);

            if (radius == 0.0)
            {
                return(new Solid());
            }
            var resolution = options.Resolution;
            var xvector    = options.XAxis * radius;
            var yvector    = options.YAxis * radius;
            var zvector    = options.ZAxis * radius;

            if (resolution < 4)
            {
                resolution = 4;
            }
            var qresolution       = resolution / 4;
            var prevcylinderpoint = new Vector3D(0, 0, 0);
            var polygons          = new List <Polygon>();

            for (var slice1 = 0; slice1 <= resolution; slice1++)
            {
                var angle         = Math.PI * 2.0 * slice1 / resolution;
                var cylinderpoint = xvector * (Math.Cos(angle)) + (yvector * (Math.Sin(angle)));
                if (slice1 > 0)
                {
                    double prevcospitch = 0, prevsinpitch = 0;
                    for (var slice2 = 0; slice2 <= qresolution; slice2++)
                    {
                        var pitch    = 0.5 * Math.PI * (double)slice2 / qresolution;
                        var cospitch = Math.Cos(pitch);
                        var sinpitch = Math.Sin(pitch);
                        if (slice2 > 0)
                        {
                            var vertices = new List <Vertex>();
                            vertices.Add(new Vertex(center + (prevcylinderpoint * (prevcospitch) - (zvector * (prevsinpitch)))));
                            vertices.Add(new Vertex(center + (cylinderpoint * (prevcospitch) - (zvector * (prevsinpitch)))));
                            if (slice2 < qresolution)
                            {
                                vertices.Add(new Vertex(center + (cylinderpoint * (cospitch) - (zvector * (sinpitch)))));
                            }
                            vertices.Add(new Vertex(center + (prevcylinderpoint * (cospitch) - (zvector * (sinpitch)))));
                            polygons.Add(new Polygon(vertices));
                            vertices = new List <Vertex>();
                            vertices.Add(new Vertex(center + (prevcylinderpoint * (prevcospitch) + (zvector * (prevsinpitch)))));
                            vertices.Add(new Vertex(center + (cylinderpoint * (prevcospitch) + (zvector * (prevsinpitch)))));
                            if (slice2 < qresolution)
                            {
                                vertices.Add(new Vertex(center + (cylinderpoint * (cospitch) + (zvector * (sinpitch)))));
                            }
                            vertices.Add(new Vertex(center + (prevcylinderpoint * (cospitch) + (zvector * (sinpitch)))));
                            vertices.Reverse();
                            polygons.Add(new Polygon(vertices));
                        }
                        prevcospitch = cospitch;
                        prevsinpitch = sinpitch;
                    }
                }
                prevcylinderpoint = cylinderpoint;
            }
            var result = Solid.FromPolygons(polygons);

            return(result);
        }
Beispiel #10
0
        public static Solid Cylinder(CylinderOptions options)
        {
            var s      = options.Start;
            var e      = options.End;
            var r      = Math.Abs(options.RadiusStart);
            var rEnd   = Math.Abs(options.RadiusEnd);
            var rStart = r;
            var alpha  = options.SectorAngle;

            alpha = alpha > 360 ? alpha % 360 : alpha;

            if ((rEnd == 0) && (rStart == 0))
            {
                return(new Solid());
            }
            if (s.Equals(e))
            {
                return(new Solid());
            }

            var slices = options.Resolution;
            var ray    = e - (s);
            var axisZ  = ray.Unit;
            var axisX  = axisZ.RandomNonParallelVector().Unit;

            var axisY = axisX.Cross(axisZ).Unit;

            axisX = axisZ.Cross(axisY).Unit;
            var start    = new Vertex(s);
            var end      = new Vertex(e);
            var polygons = new List <Polygon>();

            Func <double, double, double, Vertex> point = (stack, slice, radius) =>
            {
                var angle = slice * Math.PI * alpha / 180;
                var outp  = axisX * (Math.Cos(angle)) + (axisY * (Math.Sin(angle)));
                var pos   = s + (ray * (stack)) + (outp * (radius));
                return(new Vertex(pos));
            };

            if (alpha > 0)
            {
                for (var i = 0; i < slices; i++)
                {
                    double t0 = (double)i / slices;
                    double t1 = (double)(i + 1) / slices;
                    if (rEnd == rStart)
                    {
                        polygons.Add(new Polygon(start, point(0, t0, rEnd), point(0, t1, rEnd)));
                        polygons.Add(new Polygon(point(0, t1, rEnd), point(0, t0, rEnd), point(1, t0, rEnd), point(1, t1, rEnd)));
                        polygons.Add(new Polygon(end, point(1, t1, rEnd), point(1, t0, rEnd)));
                    }
                    else
                    {
                        if (rStart > 0)
                        {
                            polygons.Add(new Polygon(start, point(0, t0, rStart), point(0, t1, rStart)));
                            polygons.Add(new Polygon(point(0, t0, rStart), point(1, t0, rEnd), point(0, t1, rStart)));
                        }
                        if (rEnd > 0)
                        {
                            polygons.Add(new Polygon(end, point(1, t1, rEnd), point(1, t0, rEnd)));
                            polygons.Add(new Polygon(point(1, t0, rEnd), point(1, t1, rEnd), point(0, t1, rStart)));
                        }
                    }
                }
                if (alpha < 360)
                {
                    polygons.Add(new Polygon(start, end, point(0, 0, rStart)));
                    polygons.Add(new Polygon(point(0, 0, rStart), end, point(1, 0, rEnd)));
                    polygons.Add(new Polygon(start, point(0, 1, rStart), end));
                    polygons.Add(new Polygon(point(0, 1, rStart), point(1, 1, rEnd), end));
                }
            }
            var result = Solid.FromPolygons(polygons);

            return(result);
        }