Example #1
0
        public void test_cuts_naming()
        {
            for (int i = 0; i < 100; i++)
            {
                Solid s1 = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), "b1", 10, 24, 2);
                Solid s2 = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.PLYWOOD_OAK), "cut", 14, 2, 2);
                s2.Translate(-1, 8, 1);
                Solid s3 = bool3d.Subtract(s1, s2);

                Face f = s3.FindFace("btop");
                Assert.IsNull(f);

                Face f1 = s3.FindFace("top_1");
                Face f2 = s3.FindFace("top_2");

                Assert.IsNotNull(f1);
                Assert.IsNotNull(f2);

                //ut.DumpPoly3d("f1", f1.MainLoop.CollectAllVertices());
                //ut.DumpPoly3d("f2", f2.MainLoop.CollectAllVertices());

                PointFaceIntersection pfi1 = f1.CalcPointFaceIntersection(new xyz(0, 0, 0));
                Assert.AreEqual(PointFaceIntersection.OnEdge, pfi1);

                PointFaceIntersection pfi2 = f2.CalcPointFaceIntersection(new xyz(0, 0, 0));
                Assert.AreEqual(PointFaceIntersection.None, pfi2);
            }
        }
Example #2
0
        public static Solid CreateBoard(BoardMaterial bm, string name, Inches width, Inches length, Inches thickness)
        {
            Solid s = new Solid(name, bm);

            double dx = width;
            double dy = length;
            double dz = thickness;

            s.AddVertex(0, 0, 0);       // 0
            s.AddVertex(dx, 0, 0);      // 1
            s.AddVertex(dx, dy, 0);     // 2
            s.AddVertex(0, dy, 0);      // 3
            s.AddVertex(0, 0, -dz);     // 4
            s.AddVertex(dx, 0, -dz);    // 5
            s.AddVertex(dx, dy, -dz);   // 6
            s.AddVertex(0, dy, -dz);    // 7

            Face top    = s.CreateFace("top", 0, 1, 2, 3);
            Face right  = s.CreateFace("right", 1, 5, 6, 2);
            Face left   = s.CreateFace("left", 0, 3, 7, 4);
            Face bottom = s.CreateFace("bottom", 7, 6, 5, 4);
            Face end1   = s.CreateFace("end1", 0, 4, 5, 1);
            Face end2   = s.CreateFace("end2", 3, 2, 6, 7);

            s.board_origin = new xyz(0, 0, 0);
            s.board_u      = new xyz(dx, 0, 0);
            s.board_v      = new xyz(0, dy, 0);
            s.board_w      = new xyz(0, 0, -dz);

            s.RecalcFacePlanes();

            return(s);
        }
Example #3
0
        public void test_weird_case_1()
        {
            List <xyz>    a   = ut.MakePoly(new xyz(0, 0, 0), new xyz(5, 0, 0), new xyz(5, 3, 0), new xyz(3, 3, 0), new xyz(5, 5, 0), new xyz(3, 8, 0), new xyz(2, 5, 0), new xyz(0, 8, 0));
            CompoundSolid sol = Solid.Sweep("weird", BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), a, new xyz(0, 0, 12)).ToCompoundSolid();

            sol = wood.Mortise(sol, (sol[0].Faces[0]).MainLoop[0], new xy(1, 1), new xyz(3, 3, 20), "m");
            sol.DoGeomChecks();
        }
Example #4
0
        public void test_subtract_nothing()
        {
            Solid  sol = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), "b1", 12, 24, 2);
            double vol = sol.Volume();
            Solid  cut = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), "b2", 12, 36, 2);

            cut.Translate(0, 6, 2);
            sol = bool3d.Subtract(sol, cut);
            Assert.IsTrue(fp.eq_volume(sol.Volume(), vol));
        }
Example #5
0
        public static Solid CreateCubeWithHole(string solname)
        {
            Solid s = new Solid(solname, BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED));

            double d = 5;

            s.AddVertex(0, 0, 0);   // 0
            s.AddVertex(d, 0, 0);   // 1
            s.AddVertex(d, d, 0);   // 2
            s.AddVertex(0, d, 0);   // 3
            s.AddVertex(0, 0, -d);  // 4
            s.AddVertex(d, 0, -d);  // 5
            s.AddVertex(d, d, -d);  // 6
            s.AddVertex(0, d, -d);  // 7

            Face cut = s.CreateFace("top", 0, 1, 2, 3);

            s.CreateFace("right", 1, 5, 6, 2);
            s.CreateFace("left", 0, 3, 7, 4);
            Face cut2 = s.CreateFace("bottom", 4, 7, 6, 5);

            s.CreateFace("end1", 0, 4, 5, 1);
            s.CreateFace("end2", 3, 2, 6, 7);

            // another mortise, all the way through

            // TODO make this into a routine that can be called

            s.AddVertex(1, 1, 0);
            s.AddVertex(1, 4, 0);
            s.AddVertex(4, 4, 0);
            s.AddVertex(4, 1, 0);

            //cw
            cut.AddHole(8, 9, 10, 11);

            s.AddVertex(1, 1, -5);
            s.AddVertex(1, 4, -5);
            s.AddVertex(4, 4, -5);
            s.AddVertex(4, 1, -5);

            cut2.AddHole(12, 15, 14, 13);

            //ccw
            s.CreateFace("cube_hole_1", 8, 12, 13, 9);
            s.CreateFace("cube_hole_2", 13, 14, 10, 9);
            s.CreateFace("cube_hole_3", 10, 14, 15, 11);
            s.CreateFace("cube_hole_4", 11, 15, 12, 8);

            s.RecalcFacePlanes();

            return(s.DoGeomChecks());
        }
Example #6
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));
        }
Example #7
0
        public void test_cut_board_in_half()
        {
            // TODO fix this to create two solids?

            Solid b1 = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), "b1", 10, 24, 2);
            Solid b2 = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), "cut", 24, 2, 5);

            b2.Translate(-5, 10, -1);
            Solid b3 = bool3d.Subtract(b1, b2);

            b3.DoGeomChecks();
        }
Example #8
0
        public void test_chamfer()
        {
            CompoundSolid sol = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), "b1", 12, 24, 2).ToCompoundSolid();
            Face          f   = sol.FindFace("b1.top");
            HalfEdge      he  = f.FindEdge("right");

            sol = wood.DoChamfer(sol, he, 0.5, "c1");
            f   = sol.FindFace("b1.top");
            he  = f.FindEdge("end1");
            sol = wood.DoChamfer(sol, he, 0.5, "c2");
            sol.DoGeomChecks();
        }
Example #9
0
        public void test_subtract_through_mortise()
        {
            Solid s1 = Builtin_Solids.CreateCube("s1", 10);
            Solid s2 = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), "cut", 2, 2, 20);

            s2.Translate(2, 2, -2);

            double volume1 = s1.Volume();
            Solid  s3      = bool3d.Subtract(s1, s2);
            double volume2 = s3.Volume();

            s3.DoGeomChecks();
            Assert.Less(volume2, volume1);
        }
Example #10
0
        public void mortise_through_entire_bookshelf()
        {
            Plan p = test_plan.CreateBookShelf();

            p.Execute();
            CompoundSolid s1 = p.Result;

            Solid s2 = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), "cut", 2, 2, 50);

            s2.Translate(2, 10, -40);
            s2.RecalcFacePlanes();
            CompoundSolid s3 = bool3d.Subtract(s1, s2);

            s3.DoGeomChecks();
        }
Example #11
0
        public void test_two_mortises_connect_harder()
        {
            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 sj = bool3d.Subtract(s1, s2);

            Solid s3 = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), "cut3", 6, 6, 6);

            s3.Translate(5, 2, 2);
            Solid sk = bool3d.Subtract(sj, s3);

            sk.DoGeomChecks();
        }
Example #12
0
        public void test_two_through_mortises_same_face()
        {
            Solid s1 = Builtin_Solids.CreateCube("s1", 10);
            Solid s2 = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), "cut", 2, 2, 20);

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

            Solid s4 = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), "cut2", 2, 2, 20);

            s4.Translate(7, 7, -2);
            Solid s5 = bool3d.Subtract(s3, s4);

            s5.DoGeomChecks();
        }
Example #13
0
        public void test_two_mortises_that_connect()
        {
            Solid s1 = Builtin_Solids.CreateCube("s1", 10);
            Solid s2 = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), "cut", 6, 6, 6);

            s2.Translate(2, 2, -1);

            Solid s3 = bool3d.Subtract(s1, s2);

            Solid s4 = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), "cut2", 6, 6, 6);

            s4.Translate(5, 3, 2);

            Solid s5 = bool3d.Subtract(s3, s4);

            s5.DoGeomChecks();
        }
Example #14
0
        public void test_dado_and_through_mortise()
        {
            for (int i = 0; i < 10; i++)
            {
                Solid s1 = Builtin_Solids.CreateCube("s1", 10);
                Solid s2 = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), "cut_s2", 2, 2, 20);
                s2.Translate(2, -1, -2);

                Solid s3 = bool3d.Subtract(s1, s2);

                Solid s4 = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), "cut_s4", 2, 2, 20);
                s4.Translate(7, 7, -2);

                Solid s5 = bool3d.Subtract(s3, s4);
                s5.DoGeomChecks();
            }
        }
Example #15
0
 private static void init()
 {
     lock (mylock)
     {
         if (materials == null)
         {
             materials = new Dictionary <string, BoardMaterial>();
             materials[SOLID_OAK_RED]    = new BoardMaterial("solid.oak.red", 41.0 / (12 * 12 * 12), new RGB(183, 113, 28));
             materials[SOLID_OAK_WHITE]  = new BoardMaterial("solid.oak.white", 46.0 / (12 * 12 * 12), new RGB(189, 139, 54));
             materials[SOLID_MAPLE_HARD] = new BoardMaterial("solid.maple.hard", 43.0 / (12 * 12 * 12), new RGB(233, 217, 191));
             materials[SOLID_MAPLE_SOFT] = new BoardMaterial("solid.maple.soft", 33.0 / (12 * 12 * 12), new RGB(233, 217, 191));
             materials[SOLID_IPE]        = new BoardMaterial("solid.ipe", 70.0 / (12 * 12 * 12), new RGB(135, 57, 44));
             materials[PLYWOOD_OAK]      = new BoardMaterial("plywood.oak", 75.0 / (48 * 96 * .75), new RGB(183, 113, 28));
             materials[NONE]             = new BoardMaterial("none.none", 1, new RGB(0, 0, 0));
         }
     }
 }
Example #16
0
        public static Solid CreateTetrahedron(string solname, double d)
        {
            Solid s = new Solid(solname, BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED));

            s.AddVertex(d, d, d);
            s.AddVertex(-d, -d, d);
            s.AddVertex(d, -d, -d);
            s.AddVertex(-d, d, -d);

            s.CreateFace("tet_1", 0, 1, 2);
            s.CreateFace("tet_2", 1, 3, 2);
            s.CreateFace("tet_3", 0, 2, 3);
            s.CreateFace("tet_4", 0, 3, 1);

            s.RecalcFacePlanes();

            return(s.DoGeomChecks());
        }
Example #17
0
        public static CompoundSolid Drill(CompoundSolid sol, HalfEdge he, Inches x, Inches y, int count, Inches dx, Inches dy, double diameter, double depth, string id)
        {
            Face f = he.face;

            Solid cutter = new Solid(id, BoardMaterial.Find(BoardMaterial.NONE));

            for (int i = 0; i < count; i++)
            {
                CreateCutter_Drill(cutter, he, new xy(x, y), diameter, depth, (i + 1).ToString());
                x += dx;
                y += dy;
            }

            cutter.RecalcFacePlanes();

            CompoundSolid cs = bool3d.Subtract(sol, cutter);

            // find all the edges between slices we just drilled and mark those edges for no lines.
            // TODO this is probably not a very efficient way to do this, but it works
            foreach (Solid s in cs.Subs)
            {
#if not
                foreach (Edge e in s.Edges)
                {
                    string sf1 = e.a2b.face.name;
                    string sf2 = e.b2a.face.name;
                    if (sf1.StartsWith(id) && sf2.StartsWith(id) && (-1 != sf1.IndexOf("_slice_")) && (-1 != sf2.IndexOf("_slice_")))
                    {
                        e.NoLine = true;
                    }
                }
#endif

                foreach (Face fc in s.Faces)
                {
                    if (fc.name.StartsWith(id) && (-1 != fc.name.IndexOf("_slice")))
                    {
                        fc.Shade = true;
                    }
                }
            }

            return(cs);
        }
Example #18
0
        public void test_overlapping_mortises()
        {
            Solid s1 = Builtin_Solids.CreateCube("c1", 8);

            Solid s2a = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), "s2a", 2, 2, 12);

            s2a.Translate(1, 1, 0);

            Solid s3 = bool3d.Subtract(s1, s2a);

            Assert.IsTrue(fp.eq_volume(s3.Volume(), 8 * 8 * 8 - 2 * 2 * 8));

            Solid s2b = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), "s2b", 2, 2, 12);

            s2b.Translate(2, 2, 1);
            Solid s4 = bool3d.Subtract(s3, s2b);

            Assert.IsTrue(fp.eq_volume(s4.Volume(), 8 * 8 * 8 - 2 * 2 * 8 - 2 * 2 * 8 + 1 * 1 * 8));
        }
Example #19
0
        public static CompoundSolid Mortise(CompoundSolid sol, HalfEdge he, xy pos, xyz size, int count, Inches dx, Inches dy, string id)
        {
            Solid cutter;

            if (count == 1)
            {
                string[] fnames = new string[] {
                    "NA",
                    "right",
                    "left",
                    "bottom",
                    "front",
                    "back",
                };
                cutter = CreateCutter_Box(id, he, pos, size, fnames);
            }
            else
            {
                cutter = new Solid(id, BoardMaterial.Find(BoardMaterial.NONE));

                Inches x = pos.x;
                Inches y = pos.y;
                for (int i = 0; i < count; i++)
                {
                    string[] fnames = new string[] {
                        string.Format("NA_{0}", i + 1),
                        string.Format("right_{0}", i + 1),
                        string.Format("left_{0}", i + 1),
                        string.Format("bottom_{0}", i + 1),
                        string.Format("front_{0}", i + 1),
                        string.Format("back_{0}", i + 1),
                    };
                    CreateCutter_Box(cutter, he, new xy(x, y), size, fnames);
                    x += dx;
                    y += dy;
                }

                cutter.RecalcFacePlanes();
            }

            return(bool3d.Subtract(sol, cutter));
        }
Example #20
0
        public static Solid CreatePyramid(string solname, double side, double height)
        {
            Solid s = new Solid(solname, BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED));

            s.AddVertex(0, 0, 0);
            s.AddVertex(side, 0, 0);
            s.AddVertex(side, side, 0);
            s.AddVertex(0, side, 0);
            s.AddVertex(side / 2, side / 2, -height);

            s.CreateFaceCW("pyr_1", 0, 3, 2, 1);
            s.CreateFaceCW("pyr_2", 0, 1, 4);
            s.CreateFaceCW("pyr_3", 1, 2, 4);
            s.CreateFaceCW("pyr_4", 2, 3, 4);
            s.CreateFaceCW("pyr_5", 3, 0, 4);

            s.RecalcFacePlanes();

            return(s.DoGeomChecks());
        }
Example #21
0
        public static CompoundSolid EdgeTreatment(CompoundSolid sol, HalfEdge he, RouterBit bit, string name)
        {
            HalfEdge he1;
            double   length;

            FindActualEdge(he, out he1, out length);

            List <xyz> pts = bit.GetProfile(he1);

            xyz    uv    = he1.UnitVector();
            double extra = 200; // TODO this is a bit of an exaggeration
            xyz    tv    = -extra * uv;

            ut.TranslatePoints(pts, tv.x, tv.y, tv.z);

            Solid cut = Solid.Sweep(name, BoardMaterial.Find(BoardMaterial.NONE), pts, uv * (length + extra * 2));

            CompoundSolid result = bool3d.Subtract(sol, cut);

            return(result);
        }
Example #22
0
        private static Solid CreateCylinder(string solname, double radius, double height, int num_slices, string name_bottom, string name_top)
        {
            Solid s = new Solid(solname, BoardMaterial.Find(BoardMaterial.NONE));

            double degrees_per_slice = 360.0 / num_slices;

            int[] indices_bot = new int[num_slices];
            int[] indices_top = new int[num_slices];
            for (int i = 0; i < num_slices; i++)
            {
                double angle   = i * degrees_per_slice;
                double radians = angle * Math.PI / 180.0;

                double x = radius * Math.Cos(radians);
                double y = radius * Math.Sin(radians);
                indices_bot[i] = s.AddVertex(x, y, 0);
                indices_top[i] = s.AddVertex(x, y, height);
                if (i != 0)
                {
                    s.CreateFaceCW(string.Format("cyl_slice_{0}", i), indices_bot[i - 1], indices_bot[i], indices_top[i], indices_top[i - 1]);
                }
            }
            s.CreateFaceCW("cyl_final_slice", indices_bot[num_slices - 1], indices_bot[0], indices_top[0], indices_top[num_slices - 1]);
            int[] indices_bot_reversed = new int[num_slices];
            int   j = 0;

            for (int i = num_slices - 1; i >= 0; i--)
            {
                indices_bot_reversed[j++] = indices_bot[i];
            }

            s.CreateFaceCW(name_bottom, indices_bot_reversed);
            s.CreateFaceCW(name_top, indices_top);

            s.RecalcFacePlanes();

            return(s);
        }
Example #23
0
        public static Solid CreateSolidWithHoleAndMortise(string solname)
        {
            Solid s = new Solid(solname, BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED));

            s.AddVertex(0, 0, 0);   // 0
            s.AddVertex(5, 0, 0);   // 1
            s.AddVertex(5, 5, 0);   // 2
            s.AddVertex(0, 5, 0);   // 3

            s.AddVertex(0, 0, -30); // 4
            s.AddVertex(5, 0, -30); // 5
            s.AddVertex(5, 5, -30); // 6
            s.AddVertex(0, 5, -30); // 7

            //ccw
            s.CreateFace("f1", 0, 1, 2, 3);            // end near origin
            s.CreateFace("f2", 1, 5, 6, 2);
            Face cut = s.CreateFace("f3", 3, 2, 6, 7); // face with hole

            s.CreateFace("f4", 0, 3, 7, 4);            // left long face
            s.CreateFace("f5", 6, 5, 4, 7);            // other end
            Face cut2 = s.CreateFace("f6", 0, 4, 5, 1);

            s.RecalcFacePlanes();

            CompoundSolid cs = s.ToCompoundSolid();

            cs = wood.Mortise(cs, cut.MainLoop[1], new xy(8, 1.5), new xyz(16, 2, 2), "m1");

            cut = s.FindFace("f3");
            cs  = wood.Mortise(cs, cut.MainLoop[1], new xy(1.5, 1.5), new xyz(4, 2, 5), "m2");

            cs.DoGeomChecks();

            return(cs[0]);
        }
Example #24
0
        public void test_measure()
        {
            Solid    s  = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), "a", 10, 24, 1);
            Face     f  = s.FindFace("top");
            HalfEdge he = f.FindLongestEdge();

            Assert.IsTrue(fp.eq_inches(24, he.Length()));
            xyz p1 = he.Center();
            xyz p2 = f.Measure(he, p1);
            xyz q  = p2 - p1;

            Assert.IsTrue(fp.eq_inches(10, q.magnitude()));

            CompoundSolid cs = wood.Mortise(s.ToCompoundSolid(), he, new xy(3, 3), new xyz(18, 4, 2), "m1");

            f = cs.FindFace("a.top");
            Assert.AreEqual(2, f.loops.Count);
            he = f.FindLongestEdge();
            Assert.IsTrue(fp.eq_inches(24, he.Length()));
            p1 = he.Center();
            p2 = f.Measure(he, p1);
            q  = p2 - p1;
            Assert.IsTrue(fp.eq_inches(3, q.magnitude()));
        }
Example #25
0
        public void test_CheckIfTwoSolidsShareAnySpace()
        {
            Solid s1;
            Solid s2;

            // two identical cubes
            s1 = Builtin_Solids.CreateCube("c1", 5);
            s1.Translate(-(s1.board_origin.x), -(s1.board_origin.y), -(s1.board_origin.z));

            s2 = Builtin_Solids.CreateCube("c2", 5);
            check_share(s1, s2, true);

            // offset and overlapping
            s2.Translate(1, 1, 1);
            check_share(s1, s2, true);

            // too far apart
            s2.Translate(9, 9, 9);
            check_share(s1, s2, false);

            // sharing a face
            s2 = Builtin_Solids.CreateCube("c2", 5);
            s2.Translate(5, 0, 0);
            check_share(s1, s2, false);

            // sharing an edge
            s2 = Builtin_Solids.CreateCube("c2", 5);
            s2.Translate(5, 5, 0);
            check_share(s1, s2, false);

            // sharing one vertex
            s2 = Builtin_Solids.CreateCube("c2", 5);
            s2.Translate(5, 5, 5);
            check_share(s1, s2, false);

            // one smaller, inside the other, sharing faces
            s2 = Builtin_Solids.CreateCube("c2", 3);
            s2.Translate(-(s2.board_origin.x), -(s2.board_origin.y), -(s2.board_origin.z));
            check_share(s1, s2, true);

            // inside the other, not touching
            s2.Translate(1, 1, 1);
            check_share(s1, s2, true);

            s2 = Builtin_Solids.CreatePyramid("c2", 3, 5);
            check_share(s1, s2, true);
            s2.Translate(1, 1, 0);
            check_share(s1, s2, true);
            s2.Translate(0, 0, -5);
            check_share(s1, s2, false);
            s2.Translate(0, 0, 0.25);
            check_share(s1, s2, true);

            s2 = Builtin_Solids.CreatePyramid("c2", 3, 6);
            check_share(s1, s2, true);
            s2.Translate(1, 1, -0.5);
            check_share(s1, s2, true);

            // long stick and a cube
            s2 = wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), "c2", 2, 2, 12);
            check_share(s1, s2, true);
            s2.Translate(0, 0, -1);
            check_share(s1, s2, true);
            s2.Translate(1, 1, 0);
            check_share(s1, s2, true);

            Plan p = test_plan.CreateCubeIntoHole();

            p.Execute();
            s1 = p.Result.FindSub("c");
            s2 = p.Result.FindSub("b");
            check_share(s1, s2, false);
        }
Example #26
0
        internal void Execute()
        {
            Errors.Clear();
            Warnings.Clear();
            annotations_PP.Clear();
            facesToBeLabeled.Clear();
            prose = null;

            try
            {
                /*
                 * This switch statement must have one case for
                 * every kind of step action.
                 *
                 * Each case in this switch statement needs to:
                 *
                 * 1.  retrieve the parameters for the step
                 * 2.  do error checking on those parameters
                 * 3.  calculate the prose description of the step
                 * 4.  execute the step
                 * 5.  add faces to be labeled
                 * 6.  add annotations
                 * */

                switch (action)
                {
                case Action.INTRO:
                {
                    prose   = "";
                    _result = plan.LastStep.Result;
                    break;
                }

                case Action.DRILL:
                {
                    Inches x     = Get_Eval("x");
                    Inches y     = Get_Eval("y");
                    Inches diam  = Get_Eval("diam");
                    Inches depth = Get_Eval("depth");
                    string id    = Get_String("id");
                    Inches dx    = Get_Eval("dx");
                    Inches dy    = Get_Eval("dy");
                    int    count = Get_Eval_Integer("count");

                    CompoundSolid cs;
                    Solid         sol;
                    Face          f;
                    HalfEdge      he;
                    Lookup(Get_String("path"), out cs, out sol, out f, out he);

                    if (depth > Limits.MAX_DRILL_DEPTH)
                    {
                        Warnings.Add(string.Format("Drill depth is absurd"));
                    }

                    StringBuilder sb = new StringBuilder();
                    if (count > 1)
                    {
                        sb.AppendFormat("Drill {2} holes\r\n{0} in diameter and {1} deep\r\n", diam.GetProse(), depth.GetProse(), count);
                        sb.AppendFormat("in the '{0}' face of the board named '{1}'\r\n", f.name, sol.name);
                        sb.AppendFormat("\r\nstarting at {0}, {1} inches from\r\nthe edge between faces '{2}' and '{3}'.\r\n", x.GetStringWithoutUnits(), y.GetStringWithoutUnits(), f.name, he.Opposite().face.name);
                        // TODO what if dx and dy are both non-zero?
                        if (dx > 0)
                        {
                            sb.AppendFormat("{0} apart", dx.GetProse());
                        }
                        else
                        {
                            sb.AppendFormat("{0} apart", dy.GetProse());
                        }
                    }
                    else
                    {
                        sb.AppendFormat("Drill a hole\r\n{0} in diameter and {1} deep\r\n", diam.GetProse(), depth.GetProse());
                        sb.AppendFormat("in the '{0}' face of the board named '{1}'\r\n", f.name, sol.name);
                        sb.AppendFormat("\r\nat {0}, {1} inches from\r\nthe edge between faces '{2}' and '{3}'.\r\n", x.GetStringWithoutUnits(), y.GetStringWithoutUnits(), f.name, he.Opposite().face.name);
                    }
                    prose = sb.ToString();

                    _result = wood.Drill(cs, he, x, y, count, dx, dy, diam, depth, id);

                    facesToBeLabeled.Add(_result.FindFace(sol.name, f.name));

                    break;
                }

                case Action.TENON:
                {
                    Inches x     = Get_Eval("x");
                    Inches y     = Get_Eval("y");
                    Inches xsize = Get_Eval("xsize");
                    Inches ysize = Get_Eval("ysize");
                    Inches depth = Get_Eval("depth");
                    string id    = Get_String("id");

                    CompoundSolid cs;
                    Solid         sol;
                    Face          f;
                    HalfEdge      he;
                    Lookup(Get_String("path"), out cs, out sol, out f, out he);

                    StringBuilder sb = new StringBuilder();
                    sb.AppendFormat("Cut a tenon\r\n{0} by {1}\r\n{2} deep\r\n", xsize.GetProse(), ysize.GetProse(), depth.GetProse());
                    sb.AppendFormat("in the '{0}' face of the board named '{1}'\r\n", f.name, sol.name);
                    sb.AppendFormat("at {0}, {1} inches from\r\nthe edge between faces '{2}' and '{3}'.\r\n", x.GetStringWithoutUnits(), y.GetStringWithoutUnits(), f.name, he.Opposite().face.name);
                    sb.AppendFormat("Call this tenon '{0}'.", id);
                    prose = sb.ToString();

                    _result = wood.Tenon(cs, he, new xy(x, y), new xyz(xsize, ysize, depth), id);

                    string _s, _f, _e;
                    ut.ParsePath(Get_String("path"), out _s, out _f, out _e);

                    Face newendface = _result.FindFace(_s, _f);
                    if (newendface != null)
                    {
                        facesToBeLabeled.Add(newendface);

                        HalfEdge heother = newendface.FindEdge(_e);
                        if (heother != null)
                        {
                            facesToBeLabeled.Add(heother.Opposite().face);
                        }

                        HalfEdge hea = newendface.FindEdge(string.Format("{0}_left", id));
                        if (hea == null)
                        {
                            hea = newendface.FindEdge(string.Format("{0}_right", id));
                        }
                        if (hea != null)
                        {
                            this.annotations_PP.Add(new Annotation_PointToPoint(hea.from, hea.to, newendface.UnitNormal(), 2));
                        }

                        hea = newendface.FindEdge(string.Format("{0}_front", id));
                        if (hea == null)
                        {
                            hea = newendface.FindEdge(string.Format("{0}_back", id));
                        }
                        if (hea != null)
                        {
                            this.annotations_PP.Add(new Annotation_PointToPoint(hea.from, hea.to, newendface.UnitNormal(), 2));
                        }
                    }

                    // TODO more annotations here for the dimensions of the shoulders?

                    break;
                }

                case Action.MORTISE:
                {
                    Inches x     = Get_Eval("x");
                    Inches y     = Get_Eval("y");
                    Inches xsize = Get_Eval("xsize");
                    Inches ysize = Get_Eval("ysize");
                    Inches depth = Get_Eval("depth");
                    string id    = Get_String("id");
                    Inches dx    = Get_Eval("dx");
                    Inches dy    = Get_Eval("dy");
                    int    count = Get_Eval_Integer("count");

                    CompoundSolid cs;
                    Solid         sol;
                    Face          f;
                    HalfEdge      he;
                    Lookup(Get_String("path"), out cs, out sol, out f, out he);

                    if (depth > Limits.MAX_MORTISE_DEPTH)
                    {
                        Warnings.Add(string.Format("Mortise depth is absurd"));
                    }

                    StringBuilder sb = new StringBuilder();
                    if (count == 1)
                    {
                        sb.AppendFormat("Cut a mortise\r\n{0} by {1}\r\n{2} deep\r\n", xsize.GetProse(), ysize.GetProse(), depth.GetProse());
                        sb.AppendFormat("in the '{0}' face of the board named '{1}'\r\n", f.name, sol.name);
                        sb.AppendFormat("at {0}, {1} inches from\r\nthe edge between faces '{2}' and '{3}'.\r\n", x.GetStringWithoutUnits(), y.GetStringWithoutUnits(), f.name, he.Opposite().face.name);
                        //sb.AppendFormat("Call this mortise '{0}'.", id);
                    }
                    else
                    {
                        sb.AppendFormat("Cut {3} mortises\r\n{0} by {1}\r\n{2} deep\r\n", xsize.GetProse(), ysize.GetProse(), depth.GetProse(), count);
                        sb.AppendFormat("in the '{0}' face of the board named '{1}'\r\n", f.name, sol.name);
                        sb.AppendFormat("starting at {0}, {1} inches from\r\nthe edge between faces '{2}' and '{3}'\r\n", x.GetStringWithoutUnits(), y.GetStringWithoutUnits(), f.name, he.Opposite().face.name);
                        // TODO what if dx and dy are both non-zero?
                        if (dx > 0)
                        {
                            sb.AppendFormat("{0} apart", dx.GetProse());
                        }
                        else
                        {
                            sb.AppendFormat("{0} apart", dy.GetProse());
                        }
                        //sb.AppendFormat("Call this mortise '{0}'.", id);
                    }
                    prose   = sb.ToString();
                    _result = wood.Mortise(cs, he, new xy(x, y), new xyz(xsize, ysize, depth), count, dx, dy, id);

                    string _s, _f, _e;
                    ut.ParsePath(Get_String("path"), out _s, out _f, out _e);
                    Face newf = _result.FindFace(_s, _f);
                    if (newf != null)
                    {
                        facesToBeLabeled.Add(newf);
                        HalfEdge heother = newf.FindEdge(_e);
                        if (heother != null)
                        {
                            facesToBeLabeled.Add(heother.Opposite().face);
                        }
                    }

                    if (count == 1)
                    {
                        // label the dimensions of the mortise.  first across the front or back
                        HalfEdge hea = _result.FindEdge(sol.name, string.Format("{0}_front", id), f.name);
                        if (hea == null)
                        {
                            hea = _result.FindEdge(sol.name, string.Format("{0}_back", id), f.name);
                        }
                        if (hea != null)
                        {
                            this.annotations_PP.Add(new Annotation_PointToPoint(hea.from, hea.to, f.UnitNormal(), 2));
                        }

                        // now along the left or right
                        hea = _result.FindEdge(sol.name, string.Format("{0}_left", id), f.name);
                        if (hea == null)
                        {
                            hea = _result.FindEdge(sol.name, string.Format("{0}_right", id), f.name);
                        }
                        if (hea != null)
                        {
                            this.annotations_PP.Add(new Annotation_PointToPoint(hea.from, hea.to, f.UnitNormal(), 2));
                        }

                        // now label the location of the mortise
                        if (newf != null)
                        {
                            hea = newf.FindEdge(string.Format("{0}_front", id));

                            if (hea != null)
                            {
                                xyz p1 = hea.from;
                                xyz p2 = newf.Measure(hea, p1);
                                if (p2 != null)
                                {
                                    this.annotations_PP.Add(new Annotation_PointToPoint(p1, p2, newf.UnitNormal(), 2));
                                }
                            }

                            hea = newf.FindEdge(string.Format("{0}_right", id));
                            if (hea != null)
                            {
                                xyz p1 = hea.from;
                                xyz p2 = newf.Measure(hea, p1);
                                if (p2 != null)
                                {
                                    this.annotations_PP.Add(new Annotation_PointToPoint(p1, p2, newf.UnitNormal(), 2));
                                }
                            }
                        }
                    }

                    break;
                }

                case Action.DADO:
                {
                    Inches dist  = Get_Eval("dist");
                    Inches width = Get_Eval("width");
                    Inches depth = Get_Eval("depth");
                    string path  = Get_String("path");
                    string id    = Get_String("id");

                    CompoundSolid cs;
                    Solid         sol;
                    Face          f;
                    HalfEdge      he;
                    Lookup(path, out cs, out sol, out f, out he);

                    StringBuilder sb = new StringBuilder();
                    sb.AppendFormat("Cut a dado\r\n{0} wide and {1} deep\r\n", width.GetProse(), depth.GetProse());
                    sb.AppendFormat("in the '{0}' face of the board named '{1}'\r\n", f.name, sol.name);
                    sb.AppendFormat("parallel to and {0} from the edge between faces '{1}' and '{2}'.\r\n", dist.GetProse(), f.name, he.Opposite().face.name);
                    sb.AppendFormat("Call this dado '{0}'.", id);
                    prose = sb.ToString();

                    _result = wood.Dado(cs, he, dist, width, depth, id);

                    facesToBeLabeled.Add(_result.FindFace(string.Format("{0}.{1}_1", sol.name, f.name)));
                    facesToBeLabeled.Add(_result.FindFace(string.Format("{0}.{1}_2", sol.name, f.name)));

                    break;
                }

                case Action.RIP:
                {
                    Inches dist  = Get_Eval("dist");
                    double taper = Get_Eval_Angle("taper");
                    double tilt  = Get_Eval_Angle("tilt");

                    CompoundSolid cs;
                    Solid         sol;
                    Face          f;
                    HalfEdge      he;
                    Lookup(Get_String("path"), out cs, out sol, out f, out he);

                    if (he.Opposite().face.GetQuality() == FaceQuality.EndGrain)          // TODO is this how we want this to work?
                    {
                        Warnings.Add("This is not really a rip.");
                    }

                    StringBuilder sb = new StringBuilder();
                    sb.AppendFormat("TODO");
                    prose = sb.ToString();

                    _result = wood.Crosscut_Or_Rip(cs, he, dist, taper, tilt);

                    facesToBeLabeled.Add(_result.FindFace(sol.name, f.name));
                    facesToBeLabeled.Add(_result.FindFace(sol.name, he.Opposite().face.name));

                    break;
                }

                case Action.CROSSCUT:
                {
                    Inches dist  = Get_Eval("dist");
                    double miter = Get_Eval_Angle("miter");
                    double tilt  = Get_Eval_Angle("tilt");

                    CompoundSolid cs;
                    Solid         sol;
                    Face          f;
                    HalfEdge      he;
                    Lookup(Get_String("path"), out cs, out sol, out f, out he);

                    if (he.Opposite().face.GetQuality() != FaceQuality.EndGrain)         // TODO is this how we want this to work?
                    {
                        Warnings.Add("This is not really a crosscut.");
                    }

                    StringBuilder sb = new StringBuilder();
                    sb.AppendFormat("TODO");
                    prose = sb.ToString();

                    _result = wood.Crosscut_Or_Rip(cs, he, dist, miter, tilt);

                    facesToBeLabeled.Add(_result.FindFace(sol.name, f.name));
                    facesToBeLabeled.Add(_result.FindFace(sol.name, he.Opposite().face.name));

                    break;
                }

                case Action.CHAMFER:
                {
                    Inches inset = Get_Eval("inset");
                    string id    = Get_String("id");

                    CompoundSolid cs;
                    Solid         sol;
                    Face          f;
                    HalfEdge      he;
                    Lookup(Get_String("path"), out cs, out sol, out f, out he);

                    StringBuilder sb = new StringBuilder();
                    sb.AppendFormat("Chamfer\r\nthe edge between the faces '{0}' and '{1}'\r\non the board '{2}'\r\n", f.name, he.Opposite().face.name, sol.name);
                    sb.AppendFormat("at a depth of {0}.", inset.GetProse());
                    prose = sb.ToString();

                    _result = wood.DoChamfer(cs, he, inset, id);

                    facesToBeLabeled.Add(_result.FindFace(sol.name, f.name));
                    facesToBeLabeled.Add(_result.FindFace(sol.name, he.Opposite().face.name));

                    xyz p1 = he.Center();

                    Face     chamface = _result.FindFace(sol.name, string.Format("{0}_2", id));
                    HalfEdge he1      = chamface.FindEdge(f.name);

                    this.annotations_PP.Add(new Annotation_PointToPoint(p1, he1.Center(), he1.Opposite().face.UnitNormal(), 2));

                    he1 = chamface.FindEdge(he.Opposite().face.name);
                    this.annotations_PP.Add(new Annotation_PointToPoint(p1, he1.Center(), he1.Opposite().face.UnitNormal(), 2));

                    break;
                }

                case Action.RABBET:
                {
                    Inches inset = Get_Eval("inset");
                    Inches depth = Get_Eval("depth");
                    string id    = Get_String("id");

                    CompoundSolid cs;
                    Solid         sol;
                    Face          f;
                    HalfEdge      he;
                    Lookup(Get_String("path"), out cs, out sol, out f, out he);

                    StringBuilder sb = new StringBuilder();
                    sb.AppendFormat("TODO");
                    prose = sb.ToString();

                    _result = wood.DoRabbet(cs, he, inset, depth, id);

                    facesToBeLabeled.Add(_result.FindFace(sol.name, f.name));
                    facesToBeLabeled.Add(_result.FindFace(sol.name, he.Opposite().face.name));

                    break;
                }

                case Action.ROUNDOVER:
                {
                    Inches radius = Get_Eval("radius");
                    string id     = Get_String("id");

                    CompoundSolid cs;
                    Solid         sol;
                    Face          f;
                    HalfEdge      he;
                    Lookup(Get_String("path"), out cs, out sol, out f, out he);

                    StringBuilder sb = new StringBuilder();
                    sb.AppendFormat("TODO");
                    prose = sb.ToString();

                    _result = wood.DoRoundover(cs, he, radius, id);

                    facesToBeLabeled.Add(_result.FindFace(sol.name, f.name));
                    facesToBeLabeled.Add(_result.FindFace(sol.name, he.Opposite().face.name));

                    break;
                }

                case Action.NEW_BOARD:
                {
                    Inches        width     = Get_Eval("width");
                    Inches        length    = Get_Eval("length");
                    Inches        thickness = Get_Eval("thickness");
                    string        newname   = Get_String("newname");
                    string        material  = Get_String("material");
                    BoardMaterial bm        = BoardMaterial.Find(material);

                    StringBuilder sb = new StringBuilder();
                    sb.AppendFormat("Cut a new board made of {0}\r\n", bm.GetProse());
                    sb.AppendFormat("{0} wide\r\n{1} long\r\n{2} thick\r\n", width.GetProse(), length.GetProse(), thickness.GetProse());
                    sb.AppendFormat("Call this board '{0}'.", newname);
                    prose = sb.ToString();

                    _result = wood.CreateBoard(bm, newname, width, length, thickness).ToCompoundSolid();

                    Face     ftop = _result.Subs[0].FindFace("top");
                    HalfEdge he   = ftop.FindEdge("end1");
                    this.annotations_PP.Add(new Annotation_PointToPoint(he.from, he.to, ftop.UnitNormal(), 2));

                    he = ftop.FindEdge("left");
                    this.annotations_PP.Add(new Annotation_PointToPoint(he.from, he.to, ftop.UnitNormal(), 2));

                    Face fend1 = _result.Subs[0].FindFace("end1");
                    he = fend1.FindEdge("left");
                    this.annotations_PP.Add(new Annotation_PointToPoint(he.from, he.to, fend1.UnitNormal(), 2));

                    this.facesToBeLabeled.AddRange(_result.Subs[0].Faces);

                    break;
                }

                case Action.JOIN:
                {
                    Inches        offset1 = Get_Eval("offset1");
                    Inches        offset2 = Get_Eval("offset2");
                    string        path1   = Get_String("path1");
                    string        path2   = Get_String("path2");
                    EdgeAlignment align   = Get_EdgeAlignment("align");

                    CompoundSolid s1;
                    CompoundSolid s2;
                    Solid         sol1;
                    Solid         sol2;
                    Face          f1;
                    Face          f2;
                    HalfEdge      he1;
                    HalfEdge      he2;

                    Lookup(path1, out s1);
                    Lookup(path2, out s2);

                    CompoundSolid snew = s1.ShallowClone();             // s1 doesn't get modified by the join, so we don't need full clone
                    CompoundSolid sadd = s2.Clone();                    // s2 gets rotated and moved, so this step needs its own copy of every subsolid

                    snew.Lookup(path1, out sol1, out f1, out he1);
                    sadd.Lookup(path2, out sol2, out f2, out he2);

                    StringBuilder sb = new StringBuilder();
                    sb.AppendFormat("Join the board named '{0}'\r\nto the board named '{1}'\r\nas follows:\r\n",
                                    sol2.name,
                                    sol1.name);
                    sb.AppendFormat("On '{0}' find the face '{1}'\r\nand the edge shared between that face and '{2}'.\r\n",
                                    sol2.name, f2.name, he2.Opposite().face.name);
                    sb.AppendFormat("On '{0}' find the face '{1}'\r\nand the edge shared between that face and '{2}'.\r\n",
                                    sol1.name, f1.name, he1.Opposite().face.name);
                    sb.AppendFormat("Join these two faces together by matching up the two edges described above");
                    // TODO align
                    if (offset1 > 0)
                    {
                        sb.AppendFormat("at an offset of {0} along the edges", offset1.GetProse());
                    }
                    if (offset2 > 0)
                    {
                        sb.AppendFormat("at an offset of {0} perpendicular to the edges", offset2.GetProse());
                    }
                    prose = sb.ToString();

                    orient.Edges(sadd, f1, f2, he1, he2, align, offset1, offset2);
                    snew.AddSub(sadd);

#if DEBUG
                    snew.AssertNoNameClashes();
#endif

                    if (!snew.IsValidWithNoSubOverlaps())
                    {
                        Errors.Add("Invalid join:  Two boards cannot occupy the same space.");
                    }

                    _result = snew;

                    facesToBeLabeled.Add(_result.FindFace(sol1.name, f1.name));
                    facesToBeLabeled.Add(_result.FindFace(sol1.name, he1.Opposite().face.name));

                    facesToBeLabeled.Add(_result.FindFace(sol2.name, f2.name));
                    facesToBeLabeled.Add(_result.FindFace(sol2.name, he2.Opposite().face.name));

                    break;
                }

                case Action.JOIN_MT:
                {
                    string path1 = Get_String("mortisepath");
                    string path2 = Get_String("tenonpath");

                    CompoundSolid s1;
                    CompoundSolid s2;
                    Solid         sol1;
                    Solid         sol2;
                    Face          f1;
                    Face          f2;
                    HalfEdge      he1;
                    HalfEdge      he2;

                    Lookup(path1, out s1);
                    Lookup(path2, out s2);

                    CompoundSolid snew = s1.ShallowClone();             // s1 doesn't get modified by the join, so we don't need full clone
                    CompoundSolid sadd = s2.Clone();                    // s2 gets rotated and moved, so this step needs its own copy of every subsolid

                    snew.Lookup(path1, out sol1, out f1, out he1);
                    sadd.Lookup(path2, out sol2, out f2, out he2);

                    StringBuilder sb = new StringBuilder();
                    sb.AppendFormat("Assemble a mortise/tenon joint\r\njoining the board named '{0}' to the board named '{1}' as follows:\r\n",
                                    sol2.name,
                                    sol1.name);
                    sb.AppendFormat(" On '{0}' find the face '{1}' and the edge shared between that face and '{2}'.",
                                    sol2.name, f2.name, he2.Opposite().face.name);
                    sb.AppendFormat(" On '{0}' find the face '{1}' and the edge shared between that face and '{2}'.",
                                    sol1.name, f1.name, he1.Opposite().face.name);
                    sb.AppendFormat(" Join these two faces together by matching up the two edges described above.");
                    prose = sb.ToString();

                    orient.Edges(sadd, f1, f2, he1, he2, EdgeAlignment.Center, 0, 0);
                    snew.AddSub(sadd);

                    // TODO verify that the gluejoint has at least 3 pairs of faces (but what about face pairs not-local to this joint?)
#if DEBUG
                    snew.AssertNoNameClashes();
#endif

                    if (!snew.IsValidWithNoSubOverlaps())
                    {
                        Errors.Add("Invalid join:  Two boards cannot occupy the same space.");
                    }

                    _result = snew;

                    facesToBeLabeled.Add(_result.FindFace(sol1.name, f1.name));
                    facesToBeLabeled.Add(_result.FindFace(sol1.name, he1.Opposite().face.name));

                    facesToBeLabeled.Add(_result.FindFace(sol2.name, f2.name));
                    facesToBeLabeled.Add(_result.FindFace(sol2.name, he2.Opposite().face.name));

                    break;
                }

                case Action.DOVETAIL_JOIN:
                {
                    string id = Get_String("id");
                    if (!plan.Dovetails.ContainsKey(id))
                    {
                        Errors.Add(string.Format("Dovetail not found: {0}", id));
                    }
                    else
                    {
                        Dovetail dt = plan.Dovetails[id];

                        CompoundSolid cs1;
                        CompoundSolid cs2;

                        Lookup(dt.path1, out cs1);
                        Lookup(dt.path2, out cs2);

                        CompoundSolid snew = cs1.Clone();
                        CompoundSolid sadd = cs2.Clone();

                        StringBuilder sb = new StringBuilder();
                        sb.AppendFormat("Assemble the dovetail joint called '{0}'\r\n",
                                        id);
                        prose = sb.ToString();

                        dt.Join(snew, sadd);

                        if (!snew.IsValidWithNoSubOverlaps())
                        {
                            Errors.Add("Invalid join:  Two boards cannot occupy the same space.");
                        }

                        _result = snew;

                        string _s1, _f1, _e1;
                        string _s2, _f2, _e2;
                        ut.ParsePath(dt.path1, out _s1, out _f1, out _e1);
                        ut.ParsePath(dt.path2, out _s2, out _f2, out _e2);

                        facesToBeLabeled.Add(_result.FindFace(_s1, _e1));
                        facesToBeLabeled.Add(_result.FindFace(_s2, _e2));
                    }
                    break;
                }

                case Action.DOVETAIL_PINS:
                {
                    string id = Get_String("id");
                    if (!plan.Dovetails.ContainsKey(id))
                    {
                        Errors.Add(string.Format("Dovetail not found: {0}", id));
                    }
                    else
                    {
                        Dovetail      dt = plan.Dovetails[id];
                        CompoundSolid cs1;
                        CompoundSolid cs2;

                        Lookup(dt.path1, out cs1);
                        Lookup(dt.path2, out cs2);

                        string s_s1, s_f1, s_e1;
                        ut.ParsePath(dt.path1, out s_s1, out s_f1, out s_e1);

                        StringBuilder sb = new StringBuilder();
                        sb.AppendFormat("For the dovetail joint called '{0}',\r\nCut the pins in the board named '{1}'\r\n",
                                        id,
                                        s_s1);
                        sb.AppendFormat("in the face named '{0}'\r\n", s_f1);
                        sb.AppendFormat("with the face named '{0}' to be the outside of the joint.", s_e1);
                        prose = sb.ToString();

                        _result = dt.Pins(cs1);

                        facesToBeLabeled.Add(_result.FindFace(s_s1, s_e1));
                    }
                    break;
                }

                case Action.DOVETAIL_TAILS:
                {
                    string id        = Get_String("id");
                    string path1     = Get_String("path1");
                    string path2     = Get_String("path2");
                    int    numtails  = Get_Eval_Integer("numtails");
                    Inches tailwidth = Get_Eval("tailwidth");
                    // TODO angle/slope

                    CompoundSolid cs1;
                    CompoundSolid cs2;
                    Solid         s1;
                    Solid         s2;
                    Face          f1;
                    Face          f2;
                    HalfEdge      he1;
                    HalfEdge      he2;

                    Lookup(Get_String("path1"), out cs1, out s1, out f1, out he1);
                    Lookup(Get_String("path2"), out cs2, out s2, out f2, out he2);

                    if (he1.face.GetQuality() != FaceQuality.EndGrain)
                    {
                        Warnings.Add("The face/edge for the tails should be endgrain");
                    }
                    if (he2.face.GetQuality() != FaceQuality.EndGrain)
                    {
                        Warnings.Add("The face/edge for the pins should be endgrain");
                    }

                    StringBuilder sb = new StringBuilder();
                    sb.AppendFormat("Begin a dovetail joint called '{0}'.\r\nCut the tails in the board named '{1}'\r\n",
                                    id,
                                    s2.name);
                    sb.AppendFormat("in the face named '{0}'\r\n", f1.name);
                    sb.AppendFormat("with the face named '{0}' to be the outside of the joint.", he1.Opposite().face.name);
                    prose = sb.ToString();

                    Dovetail dt = new Dovetail(id, path1, path2, numtails, tailwidth, cs1, s1, f1, he1, cs2, s2, f2, he2);

                    CompoundSolid newcs2 = dt.Tails(cs2);

                    this.plan.Dovetails[id] = dt;

#if DEBUG
                    newcs2.AssertNoNameClashes();
#endif

                    if (!newcs2.IsValidWithNoSubOverlaps())
                    {
                        Errors.Add("Invalid join:  Two boards cannot occupy the same space.");
                    }

                    _result = newcs2;

                    facesToBeLabeled.Add(_result.FindFace(s2.name, he2.Opposite().face.name));

                    break;
                }
                }
                Debug.Assert(prose != null);
            }
            catch (Exception e)
            {
                this.Errors.Add(e.Message);
            }

            if (_result != null)
            {
                foreach (Annotation_FaceToFace a in annotations_FF)
                {
                    Solid    s1;
                    Face     f1;
                    HalfEdge he1;

                    Solid    s2;
                    Face     f2;
                    HalfEdge he2;

                    _result.FindPath(a.path1, out s1, out f1, out he1);
                    _result.FindPath(a.path2, out s2, out f2, out he2);

                    xyz p1 = he1.Center();

                    xyz n  = f2.myPlane.n;
                    xyz p0 = f2.myPlane.pts[0];

                    xyz ptfar = p1 - f1.UnitNormal() * 1000;

                    double u  = xyz.dotsub(n, p0, p1) / xyz.dotsub(n, ptfar, p1);
                    xyz    p2 = (ptfar - p1).multiply_in_place(u).add_in_place(p1);

                    this.annotations_PP.Add(new Annotation_PointToPoint(p1, p2, -he1.GetInwardNormal(), a.offset, a.size));
                }
            }
        }
Example #27
0
 public static Solid CreateCube(string solname, double d)
 {
     return(wood.CreateBoard(BoardMaterial.Find(BoardMaterial.SOLID_OAK_RED), solname, d, d, d));
 }
Example #28
0
        public CompoundSolid Tails(CompoundSolid cs2)
        {
            Solid    s1;
            Face     f1;
            HalfEdge he1;

            orig_cs1.Lookup(path1, out s1, out f1, out he1);

            Solid    s2;
            Face     f2;
            HalfEdge he2;

            cs2.Lookup(path2, out s2, out f2, out he2);

            // TODO search for the actual edge

            // TODO assert the two edges have the same length


            // The dimensions above are at the base of the tail.
            // we need the dimensions at the top of the tail, flush with s2

            // the edges specify the two edges on the outside of the joint.
            // the two edges will overlap each other when we're done.

            // cs1 is main.  cs2 will be added into it for the join.
            // cs2 is the tails.

            // length of the tails is distance from f2 to the base of
            // the tails, which is the thickness of s1.

            double s1_thickness_tail_length = f1.GetNextHalfEdge(he1).Length(); // TODO this assumes end of board is a simple rectangle with 4 edges
            double s2_thickness             = f2.GetNextHalfEdge(he2).Length(); // TODO this assumes end of board is a simple rectangle with 4 edges

            // TODO assert gapwidth_top > 0 and > some reasonable number

            /*
             * Position the boards for the join.
             * Create a cutter to cut the tails
             * Cut them in cs2
             * Cut.
             * Join (already in position)
             * */

            xyz u2  = he2.UnitVector();
            xyz in2 = he2.Opposite().GetInwardNormal();

            // one end
            cs2 = bool3d.Subtract(cs2, Solid.Sweep(id + "_dt_cutleft", BoardMaterial.Find(BoardMaterial.NONE),
                                                   (ut.MakePoly(
                                                        he2.from,
                                                        he2.from + in2 * s1_thickness_tail_length,
                                                        he2.from + in2 * s1_thickness_tail_length + u2 * gapwidth_bottom / 2,
                                                        he2.from + u2 * gapwidth_top / 2
                                                        )),
                                                   he2.GetInwardNormal() * s2_thickness));

            // other end
            cs2 = bool3d.Subtract(cs2, Solid.Sweep(id + "_dt_cutright", BoardMaterial.Find(BoardMaterial.NONE),
                                                   (ut.MakePoly(
                                                        he2.to,
                                                        he2.to - u2 * gapwidth_top / 2,
                                                        he2.to + in2 * s1_thickness_tail_length - u2 * gapwidth_bottom / 2,
                                                        he2.to + in2 * s1_thickness_tail_length
                                                        )),
                                                   he2.GetInwardNormal() * s2_thickness));

            xyz top_start = he2.from + u2 * gapwidth_top / 2;
            xyz bot_start = he2.from + in2 * s1_thickness_tail_length + u2 * gapwidth_bottom / 2;

            for (int i = 1; i <= (numtails - 1); i++)
            {
                cs2 = bool3d.Subtract(cs2, Solid.Sweep(string.Format("{0}_dt_cut{1}", id, i), BoardMaterial.Find(BoardMaterial.NONE),
                                                       (ut.MakePoly(
                                                            top_start + u2 * ((i * tailwidth_top) + ((i - 1) * gapwidth_top)),
                                                            bot_start + u2 * ((i * tailwidth_bottom) + ((i - 1) * gapwidth_bottom)),
                                                            bot_start + u2 * ((i * tailwidth_bottom) + ((i) * gapwidth_bottom)),
                                                            top_start + u2 * ((i * tailwidth_top) + (i * gapwidth_top))
                                                            )),
                                                       he2.GetInwardNormal() * s2_thickness));
            }

            return(cs2);
        }
Example #29
0
        private static Solid CreateCutter_Box(string name, xyz origin, xyz vx, xyz nrml, xyz size, string[] fnames)
        {
            Solid s = new Solid(name, BoardMaterial.Find(BoardMaterial.NONE));

            return(CreateCutter_Box(s, origin, vx, nrml, size, fnames));
        }
Example #30
0
        public void test_getallmaterials()
        {
            List <BoardMaterial> mats = BoardMaterial.GetAll();

            Assert.IsTrue(mats.Count > 0);
        }