public void MirrorTests() { { Box leftBox = new Box(10, 20, 30, "leftBox", createCentered: false); CsgObject rightBox = new Box(11, 21, 31, "rightBox", createCentered: false); rightBox = new Align(rightBox, Face.Left, leftBox, Face.Right); CsgObject union = new Union(leftBox, rightBox); Assert.IsTrue(union.XSize == 21, "Correct XSize"); AxisAlignedBoundingBox unionBounds = union.GetAxisAlignedBoundingBox(); Assert.IsTrue(unionBounds.minXYZ == new Vector3(), "MinXYZ at 0"); Assert.IsTrue(union.GetAxisAlignedBoundingBox().maxXYZ == new Vector3(21, 21, 31), "MaxXYZ correct"); } { Box leftBox = new Box(10, 20, 30, "leftBox", createCentered: false); CsgObject rightBox = leftBox.NewMirrorAccrossX(name: "rightBox"); rightBox = new Align(rightBox, Face.Left, leftBox, Face.Right); CsgObject union = new Union(leftBox, rightBox); Assert.IsTrue(union.XSize == 20, "Correct XSize"); AxisAlignedBoundingBox unionBounds = union.GetAxisAlignedBoundingBox(); Assert.IsTrue(unionBounds.minXYZ == new Vector3(), "MinXYZ at 0"); Assert.IsTrue(union.GetAxisAlignedBoundingBox().maxXYZ == new Vector3(20, 20, 30), "MaxXYZ correct"); } { Box frontBox = new Box(10, 20, 30, createCentered: false); CsgObject backBox = frontBox.NewMirrorAccrossY(); backBox = new Align(backBox, Face.Front, frontBox, Face.Back); CsgObject union = new Union(frontBox, backBox); Assert.IsTrue(union.YSize == 40, "Correct YSize"); AxisAlignedBoundingBox unionBounds = union.GetAxisAlignedBoundingBox(); Assert.IsTrue(unionBounds.minXYZ == new Vector3(), "MinXYZ at 0"); Assert.IsTrue(union.GetAxisAlignedBoundingBox().maxXYZ == new Vector3(10, 40, 30), "MaxXYZ correct"); } }
public void SubtractionMakesClosedSolid() { double XOffset = -.4; MatterHackers.Csg.CsgObject boxCombine = new MatterHackers.Csg.Solids.Box(10, 10, 10); boxCombine -= new MatterHackers.Csg.Transform.Translate(new MatterHackers.Csg.Solids.Box(10, 10, 10), XOffset, -3, 2); Mesh result = RenderOpenGl.CsgToMesh.Convert(boxCombine); Assert.IsTrue(result.IsManifold()); }
public string GetScadOutputRecursive(Box.BoxPrimitive objectToProcess, int level = 0) { string info = AddRenderInfoIfReqired(objectToProcess); if (objectToProcess.CreateCentered) { info += "cube([" + objectToProcess.Size.x.ToString() + ", " + objectToProcess.Size.y.ToString() + ", " + objectToProcess.Size.z.ToString() + "], center=true);" + AddNameAsComment(objectToProcess); } else { info += "cube([" + objectToProcess.Size.x.ToString() + ", " + objectToProcess.Size.y.ToString() + ", " + objectToProcess.Size.z.ToString() + "]);" + AddNameAsComment(objectToProcess); } return ApplyIndent(info, level); }
public Round(Vector3 size, string name = "") : base(name) { this.size = size; root = new Box(size, name); }
public void RoundPoint(Face threeFacesThatSharePoint, double radius, double extraDimension = defaultExtraDimension) { if (roundedPoints.ContainsKey(threeFacesThatSharePoint)) { return; } double radiusBoxSize = radius + extraDimension; switch (threeFacesThatSharePoint) { case Face.Left | Face.Front | Face.Bottom: { RoundEdge(Edge.LeftFront, radius, extraDimension); RoundEdge(Edge.LeftBottom, radius, extraDimension); RoundEdge(Edge.FrontBottom, radius, extraDimension); CsgObject pointRound = new Box(radiusBoxSize, radiusBoxSize, radiusBoxSize, "box"); CsgObject pointCut = new Sphere(radius, "sphere"); pointCut = new Align(pointCut, threeFacesThatSharePoint, pointRound, threeFacesThatSharePoint, extraDimension, extraDimension, extraDimension); pointRound -= pointCut; pointRound = new Align(pointRound, threeFacesThatSharePoint, GetEdgeOffset(threeFacesThatSharePoint), -extraDimension, -extraDimension, -extraDimension); root += pointRound; } break; case Face.Left | Face.Front | Face.Top: { RoundEdge(Edge.LeftFront, radius, extraDimension); RoundEdge(Edge.LeftTop, radius, extraDimension); RoundEdge(Edge.FrontTop, radius, extraDimension); CsgObject pointRound = new Box(radiusBoxSize, radiusBoxSize, radiusBoxSize, "box"); CsgObject pointCut = new Sphere(radius, "sphere"); pointCut = new Align(pointCut, threeFacesThatSharePoint, pointRound, threeFacesThatSharePoint, extraDimension, extraDimension, -extraDimension); pointRound -= pointCut; pointRound = new Align(pointRound, threeFacesThatSharePoint, GetEdgeOffset(threeFacesThatSharePoint), -extraDimension, -extraDimension, extraDimension); root += pointRound; } break; case Face.Left | Face.Back | Face.Bottom: { RoundEdge(Edge.LeftBack, radius, extraDimension); RoundEdge(Edge.LeftBottom, radius, extraDimension); RoundEdge(Edge.BackBottom, radius, extraDimension); CsgObject pointRound = new Box(radiusBoxSize, radiusBoxSize, radiusBoxSize, "box"); CsgObject pointCut = new Sphere(radius, "sphere"); pointCut = new Align(pointCut, threeFacesThatSharePoint, pointRound, threeFacesThatSharePoint, extraDimension, -extraDimension, extraDimension); pointRound -= pointCut; pointRound = new Align(pointRound, threeFacesThatSharePoint, GetEdgeOffset(threeFacesThatSharePoint), -extraDimension, extraDimension, -extraDimension); root += pointRound; } break; case Face.Left | Face.Back | Face.Top: { RoundEdge(Edge.LeftBack, radius, extraDimension); RoundEdge(Edge.LeftTop, radius, extraDimension); RoundEdge(Edge.BackTop, radius, extraDimension); CsgObject pointRound = new Box(radiusBoxSize, radiusBoxSize, radiusBoxSize, "box"); CsgObject pointCut = new Sphere(radius, "sphere"); pointCut = new Align(pointCut, threeFacesThatSharePoint, pointRound, threeFacesThatSharePoint, extraDimension, -extraDimension, -extraDimension); pointRound -= pointCut; pointRound = new Align(pointRound, threeFacesThatSharePoint, GetEdgeOffset(threeFacesThatSharePoint), -extraDimension, extraDimension, extraDimension); root += pointRound; } break; case Face.Right | Face.Front | Face.Bottom: { RoundEdge(Edge.RightFront, radius, extraDimension); RoundEdge(Edge.RightBottom, radius, extraDimension); RoundEdge(Edge.FrontBottom, radius, extraDimension); CsgObject pointRound = new Box(radiusBoxSize, radiusBoxSize, radiusBoxSize, "box"); CsgObject pointCut = new Sphere(radius, "sphere"); pointCut = new Align(pointCut, threeFacesThatSharePoint, pointRound, threeFacesThatSharePoint, -extraDimension, extraDimension, extraDimension); pointRound -= pointCut; pointRound = new Align(pointRound, threeFacesThatSharePoint, GetEdgeOffset(threeFacesThatSharePoint), extraDimension, -extraDimension, -extraDimension); root += pointRound; } break; case Face.Right | Face.Front | Face.Top: { RoundEdge(Edge.RightFront, radius, extraDimension); RoundEdge(Edge.RightTop, radius, extraDimension); RoundEdge(Edge.FrontTop, radius, extraDimension); CsgObject pointRound = new Box(radiusBoxSize, radiusBoxSize, radiusBoxSize, "box"); CsgObject pointCut = new Sphere(radius, "sphere"); pointCut = new Align(pointCut, threeFacesThatSharePoint, pointRound, threeFacesThatSharePoint, -extraDimension, extraDimension, -extraDimension); pointRound -= pointCut; pointRound = new Align(pointRound, threeFacesThatSharePoint, GetEdgeOffset(threeFacesThatSharePoint), extraDimension, -extraDimension, extraDimension); root += pointRound; } break; case Face.Right | Face.Back | Face.Bottom: { RoundEdge(Edge.RightBack, radius, extraDimension); RoundEdge(Edge.RightBottom, radius, extraDimension); RoundEdge(Edge.BackBottom, radius, extraDimension); CsgObject pointRound = new Box(radiusBoxSize, radiusBoxSize, radiusBoxSize, "box"); CsgObject pointCut = new Sphere(radius, "sphere"); pointCut = new Align(pointCut, threeFacesThatSharePoint, pointRound, threeFacesThatSharePoint, -extraDimension, -extraDimension, extraDimension); pointRound -= pointCut; pointRound = new Align(pointRound, threeFacesThatSharePoint, GetEdgeOffset(threeFacesThatSharePoint), extraDimension, extraDimension, -extraDimension); root += pointRound; } break; case Face.Right | Face.Back | Face.Top: { RoundEdge(Edge.RightBack, radius, extraDimension); RoundEdge(Edge.RightTop, radius, extraDimension); RoundEdge(Edge.BackTop, radius, extraDimension); CsgObject pointRound = new Box(radiusBoxSize, radiusBoxSize, radiusBoxSize, "box"); CsgObject pointCut = new Sphere(radius, "sphere"); pointCut = new Align(pointCut, threeFacesThatSharePoint, pointRound, threeFacesThatSharePoint, -extraDimension, -extraDimension, -extraDimension); pointRound -= pointCut; pointRound = new Align(pointRound, threeFacesThatSharePoint, GetEdgeOffset(threeFacesThatSharePoint), extraDimension, extraDimension, extraDimension); root += pointRound; } break; default: throw new NotImplementedException("Don't know how to round " + threeFacesThatSharePoint.ToString()); } if (!roundedPoints.ContainsKey(threeFacesThatSharePoint)) { roundedPoints.Add(threeFacesThatSharePoint, radius); } }
public void RoundEdge(Edge edgeToRound, double radius, double extraDimension = defaultExtraDimension) { if (roundedEdges.ContainsKey(edgeToRound)) { return; } CsgObject newRound = null; double radiusBoxSize = radius + extraDimension; switch (edgeToRound) { case Edge.LeftFront: { double zSize = size.z + 2 * extraDimension; newRound = new Box(radiusBoxSize, radiusBoxSize, zSize); CsgObject frontTopCut = new Cylinder(radius, zSize + extraDimension * 2, Alignment.z); frontTopCut = new Align(frontTopCut, Face.Left | Face.Front, newRound, Face.Left | Face.Front, extraDimension, extraDimension, 0); newRound -= frontTopCut; newRound = new Align(newRound, Face.Left | Face.Front, GetEdgeOffset(Face.Left | Face.Front), -extraDimension, -extraDimension, 0); } break; case Edge.LeftBack: { double zSize = size.z + 2 * extraDimension; newRound = new Box(radiusBoxSize, radiusBoxSize, zSize); CsgObject BackTopCut = new Cylinder(radius, zSize + extraDimension * 2, Alignment.z); BackTopCut = new Align(BackTopCut, Face.Left | Face.Back, newRound, Face.Left | Face.Back, extraDimension, -extraDimension, 0); newRound -= BackTopCut; newRound = new Align(newRound, Face.Left | Face.Back, GetEdgeOffset(Face.Left | Face.Back), -extraDimension, extraDimension, 0); } break; case Edge.LeftTop: { double ySize = size.y + 2 * extraDimension; newRound = new Box(radiusBoxSize, ySize, radiusBoxSize); CsgObject frontTopCut = new Cylinder(radius, ySize + extraDimension * 2, Alignment.y); frontTopCut = new Align(frontTopCut, Face.Left | Face.Top, newRound, Face.Left | Face.Top, extraDimension, 0, -extraDimension); newRound -= frontTopCut; newRound = new Align(newRound, Face.Left | Face.Top, GetEdgeOffset(Face.Left | Face.Top), -extraDimension, 0, extraDimension); } break; case Edge.LeftBottom: { double ySize = size.y + 2 * extraDimension; newRound = new Box(radiusBoxSize, ySize, radiusBoxSize); CsgObject frontTopCut = new Cylinder(radius, ySize + extraDimension * 2, Alignment.y); frontTopCut = new Align(frontTopCut, Face.Left | Face.Bottom, newRound, Face.Left | Face.Bottom, extraDimension, 0, extraDimension); newRound -= frontTopCut; newRound = new Align(newRound, Face.Left | Face.Bottom, GetEdgeOffset(Face.Left | Face.Bottom), -extraDimension, 0, -extraDimension); } break; case Edge.RightFront: { double zSize = size.z + 2 * extraDimension; newRound = new Box(radiusBoxSize, radiusBoxSize, zSize); CsgObject frontTopCut = new Cylinder(radius, zSize + extraDimension * 2, Alignment.z); frontTopCut = new Align(frontTopCut, Face.Right | Face.Front, newRound, Face.Right | Face.Front, -extraDimension, extraDimension, 0); newRound -= frontTopCut; newRound = new Align(newRound, Face.Right | Face.Front, GetEdgeOffset(Face.Right | Face.Front), extraDimension, -extraDimension, 0); } break; case Edge.RightTop: { double ySize = size.y + 2 * extraDimension; newRound = new Box(radiusBoxSize, ySize, radiusBoxSize); CsgObject frontTopCut = new Cylinder(radius, ySize + extraDimension * 2, Alignment.y); frontTopCut = new Align(frontTopCut, Face.Right | Face.Top, newRound, Face.Right | Face.Top, -extraDimension, 0, -extraDimension); newRound -= frontTopCut; newRound = new Align(newRound, Face.Right | Face.Top, GetEdgeOffset(Face.Right | Face.Top), extraDimension, 0, extraDimension); } break; case Edge.RightBottom: { double ySize = size.y + 2 * extraDimension; newRound = new Box(radiusBoxSize, ySize, radiusBoxSize); CsgObject frontBottomCut = new Cylinder(radius, ySize + extraDimension * 2, Alignment.y); frontBottomCut = new Align(frontBottomCut, Face.Right | Face.Bottom, newRound, Face.Right | Face.Bottom, -extraDimension, 0, extraDimension); newRound -= frontBottomCut; newRound = new Align(newRound, Face.Right | Face.Bottom, GetEdgeOffset(Face.Right | Face.Bottom), extraDimension, 0, -extraDimension); } break; case Edge.RightBack: { double zSize = size.z + 2 * extraDimension; newRound = new Box(radiusBoxSize, radiusBoxSize, zSize); CsgObject BackTopCut = new Cylinder(radius, zSize + extraDimension * 2, Alignment.z); BackTopCut = new Align(BackTopCut, Face.Right | Face.Back, newRound, Face.Right | Face.Back, -extraDimension, -extraDimension, 0); newRound -= BackTopCut; newRound = new Align(newRound, Face.Right | Face.Back, GetEdgeOffset(Face.Right | Face.Back), extraDimension, extraDimension, 0); } break; case Edge.FrontTop: { double xSize = size.x + 2 * extraDimension; newRound = new Box(xSize, radiusBoxSize, radiusBoxSize); CsgObject frontTopCut = new Cylinder(radius, xSize + extraDimension * 2, Alignment.x); frontTopCut = new Align(frontTopCut, Face.Front | Face.Top, newRound, Face.Front | Face.Top, 0, extraDimension, -extraDimension); newRound -= frontTopCut; newRound = new Align(newRound, Face.Front | Face.Top, GetEdgeOffset(Face.Front | Face.Top), 0, -extraDimension, extraDimension); } break; case Edge.FrontBottom: { double xSize = size.x + 2 * extraDimension; newRound = new Box(xSize, radiusBoxSize, radiusBoxSize); CsgObject frontTopCut = new Cylinder(radius, xSize + extraDimension * 2, Alignment.x); frontTopCut = new Align(frontTopCut, Face.Front | Face.Bottom, newRound, Face.Front | Face.Bottom, 0, extraDimension, extraDimension); newRound -= frontTopCut; newRound = new Align(newRound, Face.Front | Face.Bottom, GetEdgeOffset(Face.Front | Face.Bottom), 0, -extraDimension, -extraDimension); } break; case Edge.BackBottom: { double xSize = size.x + 2 * extraDimension; newRound = new Box(xSize, radiusBoxSize, radiusBoxSize); CsgObject backBottomCut = new Cylinder(radius, xSize + extraDimension * 2, Alignment.x); backBottomCut = new Align(backBottomCut, Face.Back | Face.Bottom, newRound, Face.Back | Face.Bottom, 0, -extraDimension, extraDimension); newRound -= backBottomCut; newRound = new Align(newRound, Face.Back | Face.Bottom, GetEdgeOffset(Face.Back | Face.Bottom), 0, extraDimension, -extraDimension); } break; case Edge.BackTop: { double xSize = size.x + 2 * extraDimension; newRound = new Box(xSize, radiusBoxSize, radiusBoxSize); CsgObject backTopCut = new Cylinder(radius, xSize + extraDimension * 2, Alignment.x); backTopCut = new Align(backTopCut, Face.Back | Face.Top, newRound, Face.Back | Face.Top, 0, -extraDimension, -extraDimension); newRound -= backTopCut; newRound = new Align(newRound, Face.Back | Face.Top, GetEdgeOffset(Face.Back | Face.Top), 0, extraDimension, extraDimension); } break; default: throw new NotImplementedException("Don't know how to round " + edgeToRound.ToString()); } if (root is Box) { root = newRound; } else { root += newRound; } roundedEdges.Add(edgeToRound, radius); CheckCornersAndRoundIfNeeded(extraDimension); }
public CsgObject DoCopyAndFlatten(Box.BoxPrimitive objectToProcess) { return new Box.BoxPrimitive(objectToProcess); }
/// <summary> /// Cun along the diagonal of a give edge to the opposite edge. The edge is chosen by saying /// which 2 faces are to be kept solid, and or-ing them together. /// </summary> /// <param name="facesThatShareEdge">The two faces to maintain after the cut, or-ed together with '|'.</param> public void CutAlongDiagonal(Face facesToKeepWhole) { switch (facesToKeepWhole) { case (Face.Left | Face.Back): { Vector3 size = root.Size; CsgObject boxToCutOut = new Box(Math.Sqrt(2), 1, 1.1, createCentered: false); boxToCutOut = new Rotate(boxToCutOut, new Vector3(0, 0, MathHelper.Tau / 8)); boxToCutOut = new Translate(boxToCutOut, x: Math.Sqrt(2) / 2, y: -Math.Sqrt(2) / 2, z: -.05); boxToCutOut = new Scale(boxToCutOut, size, name: "boxToCutOut"); root = new Difference(root, boxToCutOut); } break; case (Face.Left | Face.Front): { Vector3 size = root.Size; CsgObject boxToCutOut = new Box(Math.Sqrt(2), 1, 1.1, createCentered: false); boxToCutOut = new Rotate(boxToCutOut, new Vector3(0, 0, -MathHelper.Tau / 8)); boxToCutOut = new Translate(boxToCutOut, y: 1, z: -.05); boxToCutOut = new Scale(boxToCutOut, size, name: "boxToCutOutLeftFront"); root = new Difference(root, boxToCutOut); } break; case (Face.Left | Face.Bottom): { Vector3 size = root.Size; CsgObject boxToCutOut = new Box(Math.Sqrt(2), 1.1, 1, createCentered: false); boxToCutOut = new Rotate(boxToCutOut, new Vector3(0, MathHelper.Tau / 8, 0)); boxToCutOut = new Translate(boxToCutOut, y: -.05, z: 1); boxToCutOut = new Scale(boxToCutOut, size, name: "boxToCutOut"); root = new Difference(root, boxToCutOut); } break; case (Face.Right | Face.Front): { Vector3 size = root.Size; CsgObject boxToCutOut = new Box(Math.Sqrt(2), 1, 1.1, createCentered: false, name: "boxtToCutOut"); boxToCutOut = new Rotate(boxToCutOut, new Vector3(0, 0, MathHelper.Tau / 8)); boxToCutOut = new Translate(boxToCutOut, z: -.05); boxToCutOut = new Scale(boxToCutOut, size, name: "boxToCutOutRightFront"); root = new Difference(root, boxToCutOut); } break; case (Face.Right | Face.Bottom): { Vector3 size = root.Size; CsgObject boxToCutOut = new Box(Math.Sqrt(2), 1.1, 1, createCentered: false, name: "boxToCutOut"); boxToCutOut = new Rotate(boxToCutOut, new Vector3(0, -MathHelper.Tau / 8, 0)); boxToCutOut = new Translate(boxToCutOut, 0, -.05, 0); //boxToCutOut = new Translate(boxToCutOut, Math.Sqrt(2) / 2, 0, -Math.Sqrt(2) / 2); boxToCutOut = new Scale(boxToCutOut, size, name: "boxToCutOut"); root = new Difference(root, boxToCutOut); } break; case (Face.Right | Face.Top): { Vector3 size = root.Size; CsgObject boxToCutOut = new Box(Math.Sqrt(2), 1.1, 1, createCentered: false, name: "boxToCutOut"); boxToCutOut = new Rotate(boxToCutOut, new Vector3(0, MathHelper.Tau / 8, 0)); boxToCutOut = new Translate(boxToCutOut, -Math.Sqrt(2) / 2, 0, 1 - Math.Sqrt(2) / 2); boxToCutOut = new Scale(boxToCutOut, size, name: "botToCutOut"); root = new Difference(root, boxToCutOut); } break; case (Face.Front | Face.Top): { Vector3 size = root.Size; CsgObject boxToCutOut = new Box(1.1, Math.Sqrt(2), 1, createCentered: false, name: "boxToCutOut"); boxToCutOut = new Rotate(boxToCutOut, new Vector3(MathHelper.Tau / 8, 0, 0)); boxToCutOut = new Translate(boxToCutOut, -.05, Math.Sqrt(2) / 2, -Math.Sqrt(2) / 2); boxToCutOut = new Scale(boxToCutOut, size); root = new Difference(root, boxToCutOut); } break; case (Face.Front | Face.Bottom): { Vector3 size = root.Size; CsgObject boxToCutOut = new Box(1.1, Math.Sqrt(2), 1, createCentered: false, name: "boxToCutOut"); boxToCutOut = new Rotate(boxToCutOut, new Vector3(-MathHelper.Tau / 8, 0, 0)); boxToCutOut = new Translate(boxToCutOut, -.05, 0, 1); boxToCutOut = new Scale(boxToCutOut, size, name: "boxtToCutOutFrontBottom"); root = new Difference(root, boxToCutOut); } break; case (Face.Bottom | Face.Back): { Vector3 size = root.Size; CsgObject boxToCutOut = new Box(1.1, Math.Sqrt(2), 1, createCentered: false); boxToCutOut = new Rotate(boxToCutOut, new Vector3(MathHelper.Tau / 8, 0, 0)); boxToCutOut = new Translate(boxToCutOut, x: -.05); boxToCutOut = new Scale(boxToCutOut, size, name: "boxToCutOut"); root = new Difference(root, boxToCutOut); } break; case (Face.Back | Face.Top): { Vector3 size = root.Size; CsgObject boxToCutOut = new Box(1.1, Math.Sqrt(2), 1, createCentered: false, name: "boxToCutOut"); boxToCutOut = new Rotate(boxToCutOut, new Vector3(-MathHelper.Tau / 8, 0, 0)); boxToCutOut = new Translate(boxToCutOut, x: -.05, y: -Math.Sqrt(2) / 2, z: .28); // TODO: do the right math. .28 is hacky boxToCutOut = new Scale(boxToCutOut, size, name: "boxToCutOut"); root = new Difference(root, boxToCutOut); } break; default: throw new NotImplementedException("Just write it for this case."); } }
public IRayTraceable GetIRayTraceableRecursive(Box.BoxPrimitive objectToProcess) { return new BoxShape(Vector3.Zero, objectToProcess.Size, DefaultMaterial); }
public void RenderToGlRecursive(Box.BoxPrimitive objectToProcess) { if (objectToProcess.CreateCentered) { //objectToProcess.Size; } else { } RGBA_Floats partColor = new RGBA_Floats(.8, .8, 1); RenderMeshToGl.Render(CreateBox(objectToProcess.GetAxisAlignedBoundingBox()), partColor); }