Beispiel #1
0
		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");
			}
		}
Beispiel #2
0
		public static CsgObject CreateNegativeBevel(double innerRadius, double outerRadius, double height, Alignment alignment = Alignment.z, double extraDimension = defaultExtraRadialDimension, string name = "")
		{
			double width = outerRadius - innerRadius;
			List<Vector2> points = new List<Vector2>();

			int numCurvePoints = 6;
			for (int curvePoint = 0; curvePoint <= numCurvePoints; curvePoint++)
			{
				double x = width - Math.Cos((MathHelper.Tau / 4 * curvePoint / numCurvePoints)) * width;
				double y = height - Math.Sin((MathHelper.Tau / 4 * curvePoint / numCurvePoints)) * height;
				points.Add(new Vector2(x, y));
			}
			points.Add(new Vector2(width, 0));
			points.Add(new Vector2(width, height));

			CsgObject bevel = new RotateExtrude(points.ToArray(), innerRadius, alignment, name);

			points.Clear();
			points.Add(new Vector2(0, -extraDimension));
			points.Add(new Vector2(width + extraDimension, -extraDimension));
			points.Add(new Vector2(width + extraDimension, height + extraDimension));
			points.Add(new Vector2(0, height + extraDimension));

			CsgObject cut = new RotateExtrude(points.ToArray(), innerRadius, alignment, name);
			cut = new Align(cut, Face.Bottom, bevel, Face.Bottom, 0, 0, .1);
			//return cut;
			bevel = cut - bevel;

			return bevel;
		}
Beispiel #3
0
		public static CsgObject CreateFillet(CsgObject objectA, Face faceA, CsgObject objectB, Face faceB, double radius, double extraDimension = defaultExtraDimension)
		{
			int centralAxis = 0; // we start defaulted to x
			switch ((Edge)(faceA | faceB))
			{
				case Edge.LeftTop:
				case Edge.LeftBottom:
				case Edge.RightTop:
				case Edge.RightBottom:
					centralAxis = 1; // y axis
					break;

				case Edge.LeftFront:
				case Edge.LeftBack:
				case Edge.RightFront:
				case Edge.RightBack:
					centralAxis = 2; // z axis
					break;
			}

			AxisAlignedBoundingBox boundsA = objectA.GetAxisAlignedBoundingBox();
			AxisAlignedBoundingBox boundsB = objectB.GetAxisAlignedBoundingBox();

			double maxMin = Math.Max(boundsA.minXYZ[centralAxis], boundsB.minXYZ[centralAxis]);
			double minMax = Math.Min(boundsA.maxXYZ[centralAxis], boundsB.maxXYZ[centralAxis]);
			if (maxMin >= minMax)
			{
				throw new ArgumentException("Your two objects must overlap to have a fillet be created.");
			}

			Vector3 size = new Vector3(radius, radius, radius);
			size[centralAxis] = minMax - maxMin;
			Round newFilletRound = new Round(size);

			Face faceToGetBevelFor = CsgObject.GetOposite(faceA) | CsgObject.GetOposite(faceB);
			newFilletRound.RoundEdge((Edge)faceToGetBevelFor, radius, extraDimension);

			CsgObject newFillet = new SetCenter(newFilletRound, objectA.GetCenter());
			newFillet = new Align(newFillet, CsgObject.GetOposite(faceA), objectA, faceA);
			newFillet = new Align(newFillet, CsgObject.GetOposite(faceB), objectB, faceB);

			return newFillet;
		}
Beispiel #4
0
		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);
			}
		}
Beispiel #5
0
		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);
		}
Beispiel #6
0
		public void BevelAll(double radius)
		{
			Round roundToApply = new Round(Size);
			roundToApply.RoundAll(radius);
			CsgObject offsetRoundToApply = new Align(roundToApply, Face.Left | Face.Front | Face.Bottom, root, Face.Left | Face.Front | Face.Bottom);
			root -= offsetRoundToApply;
		}
Beispiel #7
0
		public void BevelEdge(Edge edgeToBevel, double radius)
		{
			Round roundToApply = new Round(Size);
			roundToApply.RoundEdge(edgeToBevel, radius);
			CsgObject offsetRoundToApply = new Align(roundToApply, Face.Left | Face.Front | Face.Bottom, root, Face.Left | Face.Front | Face.Bottom);
			root -= offsetRoundToApply;
		}
Beispiel #8
0
		/// <summary>
		/// Bevel a give edge.  The edge is chosen by saying which 2 faces are to be used,
		/// and or-ing them together
		/// </summary>
		/// <param name="facesThatShareEdge">The two faces or-ed together with |</param>
		/// <param name="radius">The radius of the bevel</param>
		public void BevelEdge(Face facesThatShareEdge, double radius)
		{
			Round roundToApply = new Round(Size);
			roundToApply.RoundEdge((Edge)facesThatShareEdge, radius);
			CsgObject offsetRoundToApply = new Align(roundToApply, Face.Left | Face.Front | Face.Bottom, root, Face.Left | Face.Front | Face.Bottom);
			root -= offsetRoundToApply;
		}