예제 #1
0
        public void test1()
        {
            Solid s1  = Builtin_Solids.CreateCube("s1", 5);
            bsp3d bsp = new bsp3d(s1);

            Assert.AreEqual(PointInPoly.Inside, bsp.PointInPolyhedron(new xyz(1, 1, -1)));
            Assert.AreEqual(PointInPoly.Outside, bsp.PointInPolyhedron(new xyz(6, 6, -6)));
        }
예제 #2
0
        public void test_seginside_thing()
        {
            Solid s1 = Builtin_Solids.CreateCube("s1", 10);
            Solid s2 = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), "cut2", 6, 6, 6);

            s2.Translate(2, 2, -1);
            Solid s3 = bool3d.Subtract(s1, s2);

            bsp3d bsp = new bsp3d(s3);

            bool b = s3.SegmentInside(bsp, new xyz(5, 2, 2), new xyz(8, 2, 2));
        }
예제 #3
0
파일: bool3d.cs 프로젝트: thild/sawdust
        public static Solid Subtract(Solid s1, Solid s2)
        {
            bsp3d bsp1 = new bsp3d(s1);
            bsp3d bsp2 = new bsp3d(s2);

            BoundingBox3d bb1 = s1.GetBoundingBox();
            BoundingBox3d bb2 = s2.GetBoundingBox();

            Solid s3 = new Solid(s1.name, s1.material);

            if (s1.board_origin != null)
            {
                s3.board_origin = s1.board_origin.copy();
                s3.board_u      = s1.board_u.copy();
                s3.board_v      = s1.board_v.copy();
                s3.board_w      = s1.board_w.copy();
            }

            List <segpile> piles = new List <segpile>();

            for (int ndx_f1 = 0; ndx_f1 < s1.Faces.Count; ndx_f1++)
            {
                Face f1 = s1.Faces[ndx_f1];
                piles.Add(PartitionFace(s3, f1, s2, bb1, bb2, bsp1, bsp2, false));
            }

            for (int ndx_f2 = 0; ndx_f2 < s2.Faces.Count; ndx_f2++)
            {
                Face f2 = s2.Faces[ndx_f2];
                piles.Add(PartitionFace(s3, f2, s1, bb1, bb2, bsp2, bsp1, true));
            }

            foreach (segpile sp in piles)
            {
                if (sp.segs.Count > 0)
                {
                    s3.CreateFacesFromPileOfSegments(sp.name, sp.OriginalName, sp.Shade, sp.segs, sp.reverse);
                }
            }

            s3.FixCollinearTrios();

            return(s3);
        }
예제 #4
0
        public void test_cube()
        {
            Solid         s1  = Builtin_Solids.CreateCube("s1", 5);
            bsp3d         bsp = new bsp3d(s1);
            BoundingBox3d bb  = BoundingBox3d.FromArrayOfPoints(s1.Vertices);

            foreach (xyz v in s1.Vertices)
            {
                Assert.AreEqual(PointInPoly.Coincident, bsp.PointInPolyhedron(v));
                Assert.IsTrue(bb.PointInside(v));
            }
            foreach (Face f in s1.Faces)
            {
                xyz v = f.GetCenter();
                xyz n = f.UnitNormal();
                Assert.AreEqual(PointInPoly.Coincident, bsp.PointInPolyhedron(v));
                Assert.AreEqual(PointInPoly.Outside, bsp.PointInPolyhedron(v + n));
                Assert.AreEqual(PointInPoly.Inside, bsp.PointInPolyhedron(v - n));
                Assert.IsTrue(bb.PointInside(v));
                Assert.IsFalse(bb.PointInside(v + n));
                Assert.IsTrue(bb.PointInside(v - n));
            }
            foreach (Face f in s1.Faces)
            {
                foreach (HalfEdge h in f.MainLoop)
                {
                    xyz v = h.Center();
                    xyz n = h.GetInwardNormal();
                    Assert.IsTrue(bb.PointInside(v));
                    Assert.IsTrue(bb.PointInside(v + n));
                    Assert.IsFalse(bb.PointInside(v - n));
                    Assert.AreEqual(PointInPoly.Coincident, bsp.PointInPolyhedron(v));
                    Assert.AreEqual(PointInPoly.Coincident, bsp.PointInPolyhedron(v + n));
                    Assert.AreEqual(PointInPoly.Outside, bsp.PointInPolyhedron(v - n));
                }
            }
            Assert.AreEqual(PointInPoly.Inside, bsp.PointInPolyhedron(s1.GetCenter()));
            Assert.IsTrue(bb.PointInside(s1.GetCenter()));
        }
예제 #5
0
파일: bool3d.cs 프로젝트: thild/sawdust
        public static segpile PartitionFace(Solid s3, Face f1, Solid s2, BoundingBox3d bb1, BoundingBox3d bb2, bsp3d bsp1, bsp3d bsp2, bool reverse)
        {
#if BOOL_DEBUG
            Console.Out.WriteLine("PartitionFace: f1.name={0} s2={1} reverse={2}", f1.name, s2.name, reverse);
#endif

            List <seg3d> segs = f1.CollectAllSegments();
#if BOOL_DEBUG
            ut.DumpSegments3d("CollectAllSegments", segs);
#endif

            PartitionFace_CalcFaceIntersections(segs, f1, s2, reverse);
#if BOOL_DEBUG
            ut.DumpSegments3d("CalcFaceIntersections", segs);
#endif

            PartitionFace_HandleOverlaps(segs, f1, s2, reverse);
#if BOOL_DEBUG
            ut.DumpSegments3d("HandleOverlaps", segs);
#endif

            PartitionFace_SplitEdges(segs, s2, bb2, reverse);
#if BOOL_DEBUG
            ut.DumpSegments3d("SplitEdges", segs);
#endif

#if true
            // TODO:  If we remove this call, only one unit test fails.
            // that means we usually don't need it.  I'd love to find a
            // way to decide when we need it so we can save the call
            // most of the time.  The failing unit test is the two
            // mortises overlapping, a case which should never happen
            // in practice, AFAIK.

            if (!reverse) // TODO for now, only call this on the !reverse pass
            {
                PartitionFace_SplitEdges(segs, f1.solid, bb1, !reverse);
            }
#if BOOL_DEBUG
            ut.DumpSegments3d("SplitEdges2", segs);
#endif
#endif

            PartitionFace_RemoveObvious(segs, f1, s2, bsp2, reverse);
#if BOOL_DEBUG
            ut.DumpSegments3d("RemoveObvious", segs);
#endif

            PartitionFace_HandleCoplanarStuff(segs, f1, s2, reverse);
#if BOOL_DEBUG
            ut.DumpSegments3d("HandleCoplanarStuff", segs);
#endif

            PartitionFace_RemoveByDirection(segs, f1, s2, reverse);
#if BOOL_DEBUG
            ut.DumpSegments3d("RemoveByDirection", segs);
#endif

            PartitionFace_Edges_StuffInOtherSolid(segs, s2, bsp2, reverse);
#if BOOL_DEBUG
            ut.DumpSegments3d("StuffInOtherSolid", segs);
#endif

            PartitionFace_HandleEdges(segs, f1, s2, bsp2, reverse);
#if BOOL_DEBUG
            ut.DumpSegments3d("HandleEdges", segs);
#endif

            Debug.Assert((segs.Count == 0) || (segs.Count >= 3));

            string name;
            if (reverse)
            {
                name = string.Format("{0}_{1}", f1.solid.name, f1.name);
            }
            else
            {
                name = f1.name;
            }

            return(new segpile(segs, name, f1.OriginalName, f1.Shade, reverse));
        }
예제 #6
0
파일: bool3d.cs 프로젝트: thild/sawdust
        public static void PartitionFace_Edges_StuffInOtherSolid(List <seg3d> segs, Solid s2, bsp3d bsp2, bool reverse)
        {
            // TODO this function feels like such a hack.

            List <seg3d> rm = new List <seg3d>();

            foreach (seg3d s in segs)
            {
                bool bkeep;

                if (reverse)
                {
                    bkeep = false;
                    if (s2.SegmentInside(bsp2, s.a, s.b))
                    {
                        bkeep = true;
                    }
                    else if (s2.SegmentOnSurface(bsp2, s.a, s.b))
                    {
                        bkeep = true;
                    }
                }
                else
                {
                    bkeep = true;
                    if (
                        s2.SegmentInside(bsp2, s.a, s.b) &&
                        !(s2.SegmentOnSurface(bsp2, s.a, s.b))
                        )
                    {
                        bkeep = false;
                    }
                }

                if (!bkeep)
                {
                    rm.Add(s);
                }
            }
            foreach (seg3d s in rm)
            {
                segs.Remove(s);
            }
        }
예제 #7
0
파일: bool3d.cs 프로젝트: thild/sawdust
        public static void PartitionFace_HandleEdges(List <seg3d> segs, Face f1, Solid s2, bsp3d bsp2, bool reverse)
        {
            List <seg3d> rm = new List <seg3d>();

            segs.ForEach(delegate(seg3d s)
            {
                HalfEdge he1a;
                if (f1.IsAnEdge(s, out he1a))
                {
                    HalfEdge he1b = he1a.Opposite();
                    for (int ndx_f2 = 0; ndx_f2 < s2.Faces.Count; ndx_f2++)
                    {
                        Face f2       = s2.Faces[ndx_f2];
                        HalfEdge he2a = null;
                        if (f2.IsAnEdge(s, out he2a))
                        {
                            HalfEdge he2b = he2a.Opposite();

                            bool bkeep;

                            xyz n1  = he1a.GetInwardNormal();
                            xyz n2a = he2a.GetInwardNormal();
                            xyz n2b = he2b.GetInwardNormal();

                            bkeep = bool3d.SplitsVEP(n1, n2a, n2b, he2a.face.UnitNormal(), he2b.face.UnitNormal());

                            if (reverse)
                            {
                            }
                            else
                            {
                                bkeep = !bkeep;
                            }

                            if (!bkeep)
                            {
                                rm.Add(s);
                            }
                            break;
                        }

                        PointFaceIntersection pfi_a;
                        PointFaceIntersection pfi_b;
                        if (f2.CalcSegmentFaceIntersection_SamePlane(s, out pfi_a, out pfi_b))
                        {
                            bool bProceed = false;

                            if (
                                (
                                    (pfi_a == PointFaceIntersection.Inside) &&
                                    (pfi_b == PointFaceIntersection.Inside)
                                )
                                ||
                                (
                                    (pfi_a == PointFaceIntersection.Inside) &&
                                    (pfi_b == PointFaceIntersection.OnEdge)
                                )
                                ||
                                (
                                    (pfi_a == PointFaceIntersection.OnEdge) &&
                                    (pfi_b == PointFaceIntersection.Inside)
                                )
                                )
                            {
                                bProceed = true;
                            }
                            else if (
                                (
                                    (pfi_a == PointFaceIntersection.OnEdge) &&
                                    (pfi_b == PointFaceIntersection.OnEdge)
                                )
                                )
                            {
                                if (f2.solid.SegmentOnSurface(bsp2, s.a, s.b))
                                {
                                    bProceed = true;
                                }
                            }

                            if (bProceed)
                            {
                                bool bkeep;

                                double dot = xyz.dot(he1a.GetInwardNormal(), f2.UnitNormal());

                                if (fp.eq_dot_unit(dot, 0))
                                {
                                    // this occurs on the outside of f2
                                    bkeep = true;
                                }
                                else if (dot < 0)
                                {
                                    // this intersect occurs on the inside of f2
                                    bkeep = false;
                                }
                                else
                                {
                                    // this occurs on the outside of f2
                                    bkeep = true;
                                }

                                if (reverse)
                                {
                                    bkeep = !bkeep;
                                }

                                if (!bkeep)
                                {
                                    rm.Add(s);
                                    if (rm.Count == segs.Count)
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
#if false // so far, it looks like we don't need this code.  It was written when CreateTenonInFaceWithHoleBool3dBug turned up.  I rewrote tenon to use the 4-cut method again and the bug "went away".  :-)
                    foreach (Face f2 in s2.Faces)
                    {
                        HalfEdge he2a = null;
                        if (f2.IsAnEdge(s, out he2a))
                        {
                            HalfEdge he2b = he2a.Opposite();

                            bool bkeep;

                            xyz n1 = xyz.cross((s.b - s.a).normalize_in_place(), f1.UnitNormal()).normalize_in_place();

                            xyz n2a = he2a.GetInwardNormal();
                            xyz n2b = he2b.GetInwardNormal();

                            if (bool3d.SplitsVEP(n1, n2a, n2b, he2a.face.UnitNormal(), he2b.face.UnitNormal()))
                            {
                                bkeep = true;
                            }
                            else if (bool3d.SplitsVEP(-n1, n2a, n2b, he2a.face.UnitNormal(), he2b.face.UnitNormal()))
                            {
                                bkeep = true;
                            }
                            else
                            {
                                bkeep = false;
                            }

                            if (reverse)
                            {
                            }
                            else
                            {
                                bkeep = !bkeep;
                            }

                            if (!bkeep)
                            {
                                rm.Add(s);
                            }
                            break;
                        }
                    }
#endif
                }
            }
                         );
            foreach (seg3d s in rm)
            {
                segs.Remove(s);
            }
        }
예제 #8
0
파일: bool3d.cs 프로젝트: thild/sawdust
        public static void PartitionFace_RemoveObvious(List <seg3d> segs, Face f1, Solid s2, bsp3d bsp2, bool reverse)
        {
            List <seg3d> rm = new List <seg3d>();

            foreach (seg3d s in segs)
            {
                PointInPoly pip_a = bsp2.PointInPolyhedron(s.a);
                if (pip_a == PointInPoly.Coincident)
                {
                    break;
                }
                PointInPoly pip_b = bsp2.PointInPolyhedron(s.b);
                if (pip_b == PointInPoly.Coincident)
                {
                    break;
                }

                if (pip_a != pip_b)
                {
                    break;
                }

#if false // coverage says this never gets hit
                bool bNone = true;
                foreach (Face f2 in s2.Faces)
                {
                    if (f2.SegmentTouches(s))
                    {
                        // coverage says this line is never hit
                        // which may mean this entire check is
                        // unneeded.
                        bNone = false;
                        break;
                    }
                }
                if (bNone)
#endif
                {
                    bool bKeep = false;
                    if (s2.PointInside(bsp2, s.b))
                    {
                        bKeep = false;
                    }
                    else
                    {
                        bKeep = true;
                    }
                    if (reverse)
                    {
                        bKeep = !bKeep;
                    }
                    if (!bKeep)
                    {
                        rm.Add(s);
                    }
                }
            }
            foreach (seg3d s in rm)
            {
                segs.Remove(s);
            }
        }
예제 #9
0
파일: bool3d.cs 프로젝트: thild/sawdust
        public static bool CheckIfTwoSolidsShareAnySpace(Solid s1, Solid s2)
        {
            BoundingBox3d bb1 = s1.GetBoundingBox();
            BoundingBox3d bb2 = s2.GetBoundingBox();

            if (!BoundingBox3d.intersect(bb1, bb2))
            {
                return(false);
            }

            BoundingBox3d bb3 = BoundingBox3d.CalcIntersection(bb1, bb2);

            if (fp.eq_tol(bb3.volume, 0, 0.0001))
            {
                return(false);
            }

            bsp3d bsp1 = new bsp3d(s1);
            bsp3d bsp2 = new bsp3d(s2);

            xyz c1 = s1.GetCenter();

            if (
                (bsp1.PointInPolyhedron(c1) == PointInPoly.Inside) &&
                (bsp2.PointInPolyhedron(c1) == PointInPoly.Inside)
                )
            {
                return(true);
            }
            xyz c2 = s2.GetCenter();

            if (
                (bsp2.PointInPolyhedron(c2) == PointInPoly.Inside) &&
                (bsp1.PointInPolyhedron(c2) == PointInPoly.Inside)
                )
            {
                return(true);
            }

            foreach (Face f1 in s1.Faces)
            {
                xyz p = f1.GetCenter() - f1.UnitNormal() * 0.01;
                if (
                    (bsp2.PointInPolyhedron(p) == PointInPoly.Inside) &&
                    (bsp1.PointInPolyhedron(p) == PointInPoly.Inside)
                    )
                {
                    return(true);
                }
            }

            foreach (Face f2 in s2.Faces)
            {
                xyz p = f2.GetCenter() - f2.UnitNormal() * 0.01;
                if (
                    (bsp1.PointInPolyhedron(p) == PointInPoly.Inside) &&
                    (bsp2.PointInPolyhedron(p) == PointInPoly.Inside)
                    )
                {
                    return(true);
                }
            }

            if (s1.AnyEdgePiercesAnyFace(s2))
            {
                return(true);
            }

            if (s2.AnyEdgePiercesAnyFace(s1))
            {
                return(true);
            }

            // TODO we apparently need another testhere

            return(false);
        }