private static MeshGeometry3D CreateSGCGeometry( Vector3D axis, double length, Point3D bottomCenter, IEnumerable <CylinderComponent> components) { //MessageBox.Show("Snapped Factory"); var startPoint = bottomCenter; var endPoint = bottomCenter + axis * length; var pathQuery = from component in components select MathUtils3D.Lerp(startPoint, endPoint, component.Progress); var diametersQuery = from component in components select 2 * component.Radius; var builder = new MeshBuilder(); builder.AddTube( pathQuery.ToArray(), null, diametersQuery.ToArray(), thetaDiv: 20, isTubeClosed: false); var geometry = builder.ToMesh(freeze: true); return(geometry); }
protected Point3D ProjectViewDirectionOnPlane(Plane3D plane, Point3D point) { var sndPoint = point + uiState.SketchPlane.Normal; var t = plane.IntersectLine(point, sndPoint); return(MathUtils3D.Lerp(point, sndPoint, t)); }
protected override NewPrimitive ConvertCore(SnappedCylinder snapped) { return(new NewCylinder { Axis = snapped.AxisResult, Length = snapped.LengthResult, Diameter = 2 * snapped.RadiusResult, Center = MathUtils3D.Lerp(snapped.TopCenterResult, snapped.BottomCenterResult, 0.5), }); }
private double ContainedCenterOnContainerAxisProjection(CandidatePair pair) { var containedCenter = pair.Contained.CenterResult; var containerAxis = pair.Container.NormalResult; var containerCenter = pair.Container.CenterResult; // this is t such that the projected point is (containerCenter + t * containerAxis); var projectionParameter = MathUtils3D.ProjectOnLine(containedCenter, containerCenter, containerAxis).Item1; return(projectionParameter); }
protected override NewPrimitive ConvertCore(SnappedCone snapped) { var result = new NewCone(); result.Axis.Value = snapped.AxisResult; result.TopRadius.Value = snapped.TopRadiusResult; result.BottomRadius.Value = snapped.BottomRadiusResult; result.Length.Value = snapped.LengthResult; result.Center.Value = MathUtils3D.Lerp(snapped.TopCenterResult, snapped.BottomCenterResult, 0.5); return(result); }
protected override NewPrimitive ConvertCore(SnappedCone snapped) { return(new NewCone { Axis = snapped.AxisResult, TopRadius = snapped.TopRadiusResult, BottomRadius = snapped.BottomRadiusResult, Length = snapped.LengthResult, Center = MathUtils3D.Lerp(snapped.TopCenterResult, snapped.BottomCenterResult, 0.5), }); }
/// <summary> /// Constructs a new instance of the <see cref="PolarPointsGenerator"/> class. /// </summary> /// <param name="center">The central point around which this class will generate other points.</param> /// <param name="xBase">Basis vector that serves as the X axis</param> /// <param name="yBase">Basis vector that serves as the Y axis</param> /// <remarks><paramref name="xBase"/> and <paramref name="yBase"/> vectors must be orthogonal</remarks> public PolarPointsGenerator(Point3D center, Vector3D xBase, Vector3D yBase) { Contract.Requires(xBase.LengthSquared > 0); Contract.Requires(yBase.LengthSquared > 0); Contract.Requires(MathUtils3D.AreOrthogonal(xBase, yBase)); this.center = center; xBase.Normalize(); yBase.Normalize(); this.xBase = xBase; this.yBase = yBase; }
/// <summary> /// Generates an approximation of a circle given its center, a normal vector for the plane, and its radius. /// </summary> /// <param name="center">The circle's center</param> /// <param name="normal">Normal vector to the circle's plane</param> /// <param name="radius">Circle's radius.</param> /// <param name="count">Number of points that approximate the circle</param> /// <returns>An array of points that form the circle's approximation</returns> public static Point3D[] GenerateCircle(Point3D center, Vector3D normal, double radius, int count) { Contract.Requires(radius > 0); Contract.Requires(count >= 3); Contract.Ensures(Contract.Result <Point3D[]>() != null); Contract.Ensures(Contract.Result <Point3D[]>().Length == count); Contract.Ensures(Contract.ForAll( Contract.Result <Point3D[]>(), pnt => NumericUtils.AlmostEqual(radius * radius, (pnt - center).LengthSquared, 100))); var xAxis = MathUtils3D.NormalVector(normal).Normalized(); var yAxis = Vector3D.CrossProduct(normal, xAxis).Normalized(); return(GenerateCircle(center, xAxis, yAxis, radius, count)); }
protected override NewPrimitive ConvertCore(SnappedCylinder snapped) { var result = new NewCylinder(); result.Axis.Value = snapped.AxisResult; result.Length.Value = snapped.LengthResult; result.Diameter.Value = 2 * snapped.RadiusResult; result.Center.Value = MathUtils3D.Lerp(snapped.TopCenterResult, snapped.BottomCenterResult, 0.5); result.EditConstraints.Add(new AxisOnLineConstraint( snapped.BottomCenterResult, snapped.AxisResult, result.Center, result.Axis)); return(result); }
/// <summary> /// Gets the point on the sketch plane that is intersected by a given ray /// </summary> /// <param name="sketchPlane">The sketch plane</param> /// <param name="lineRange">The ray information</param> /// <returns>The point on the plane of <paramref name="sketchPlane"/> that intersects the ray given by <paramref name="lineRange"/>, or <c>null</c> /// if no such point exists.</returns> public static Point3D?PointFromRay(this SketchPlane sketchPlane, LineRange lineRange) { Contract.Requires(sketchPlane != null); var plane = Plane3D.FromPointAndNormal(sketchPlane.Center, sketchPlane.Normal); var t = plane.IntersectLine(lineRange.Point1, lineRange.Point2); if (double.IsNaN(t)) { return(null); } else { return(MathUtils3D.Lerp(lineRange.Point1, lineRange.Point2, t)); } }
protected override NewPrimitive ConvertCore(SnappedStraightGenCylinder snapped) { var result = new NewStraightGenCylinder(); result.Axis.Value = snapped.AxisResult; result.Length.Value = snapped.LengthResult; result.Center.Value = MathUtils3D.Lerp(snapped.TopCenterResult, snapped.BottomCenterResult, 0.5); result.Components = snapped.ComponentResults.CloneArray(); result.EditConstraints.Add(new AxisOnLineConstraint( snapped.BottomCenterResult, snapped.AxisResult, result.Center, result.Axis)); return(result); }
public void Drag(Point currPos, LineRange currRay) { var currDragPosition = PointOnSketchPlane(currRay); var dragVector3d = currDragPosition - lastDragPosition3d; var dragVector2d = currPos - lastDragPosition2d; if (dragVector3d != null) { var axisDragVector = MathUtils3D.ProjectVector(dragVector3d.Value, editable.ApproximateAxis); PerformDrag(dragVector2d, dragVector3d.Value, axisDragVector, currDragPosition); editable.NotifyDragged(); } if (currDragPosition != null) { lastDragPosition3d = currDragPosition; } lastDragPosition2d = currPos; }
public SketchPlane(string name, Point3D center, Vector3D xAxis, Vector3D yAxis, Vector3D normal, double width, double height) { Contract.Requires(!string.IsNullOrEmpty(name)); Contract.Requires(width > 0); Contract.Requires(height > 0); Contract.Requires(MathUtils3D.AreOrthogonal(xAxis, yAxis)); Contract.Requires(MathUtils3D.AreOrthogonal(xAxis, normal)); Contract.Requires(MathUtils3D.AreOrthogonal(yAxis, normal)); xAxis.Normalize(); yAxis.Normalize(); normal.Normalize(); Name = name; Center = center; XAxis = xAxis; YAxis = yAxis; Normal = normal; Width = width; Height = height; }
private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.Match(() => viewModel.SketchPlane)) { var sketchPlane = viewModel.SketchPlane; var normal = sketchPlane.Normal.Normalized(); var center = sketchPlane.Center; var position = sketchPlane.Center - 50 * normal; var lookAt = MathUtils3D.LookAt(position, normal, sketchPlane.YAxis.Normalized()); camera.ViewMatrix = lookAt; light.Direction = normal; var projMatrix = Matrix3D.Identity; projMatrix.M33 = 0.0001; projMatrix.OffsetZ = 0.2; camera.ProjectionMatrix = projMatrix; } }
/// <summary> /// Generates an approximation of a circle given its center, two orthonormal basis vectors for the plane, and its radius. /// </summary> /// <param name="center">The circle's center</param> /// <param name="u">First basis vector. This is the "X" axis.</param> /// <param name="v">Second basis vector. This is the "Y" axis.</param> /// <param name="radius">Circle's radius.</param> /// <param name="count">Number of points that approximate the circle</param> /// <returns>An array of points that form the circle's approximation</returns> public static Point3D[] GenerateCircle(Point3D center, Vector3D u, Vector3D v, double radius, int count) { Contract.Requires(MathUtils3D.AreOrthogonal(u, v)); Contract.Requires(NumericUtils.AlmostEqual(u.LengthSquared, 1, 10)); Contract.Requires(NumericUtils.AlmostEqual(v.LengthSquared, 1, 10)); Contract.Requires(radius > 0); Contract.Requires(count >= 3); Contract.Ensures(Contract.Result <Point3D[]>() != null); Contract.Ensures(Contract.Result <Point3D[]>().Length == count); // we cannot really ensure that (?) //Contract.Ensures(Contract.ForAll( // Contract.Result<Point3D[]>(), // pnt => NumericUtils.AlmostEqual((pnt - center).LengthSquared, radius * radius, 100))); var result = new Point3D[count]; for (int i = 0; i < count; ++i) { var fraction = i / (double)count; var angle = 2 * Math.PI * fraction; result[i] = center + radius * (Math.Cos(angle) * u + Math.Sin(angle) * v); } return(result); }
private static MeshGeometry3D CreateGeometry(NewSGCViewModel viewModel) { var startPoint = viewModel.Center - 0.5 * viewModel.Length * viewModel.Axis; var endPoint = viewModel.Center + 0.5 * viewModel.Length * viewModel.Axis; var components = viewModel.Components; var path = from component in components select MathUtils3D.Lerp(startPoint, endPoint, component.Progress); var diameters = from component in components select 2 * component.Radius; var builder = new MeshBuilder(); builder.AddTube( path.ToArray(), null, diameters.ToArray(), thetaDiv: CIRCLE_DIV, isTubeClosed: false); var geometry = builder.ToMesh(freeze: true); return(geometry); }
private void OnTestCase(object ignore) { // data from which the cylinder and its curve representations will be created var axis = RotationHelper.RotateVector(MathUtils3D.UnitY, MathUtils3D.UnitX, -20); var center = MathUtils3D.Origin; var radius = 0.2; var halfLength = 0.3; // basis vectors for the cylinder top/bottom planes var xBase = MathUtils3D.NormalVector(axis); var yBase = Vector3D.CrossProduct(xBase, axis); // generators for the top/bottom circles. var topGenerator = new PolarPointsGenerator(center + halfLength * axis, xBase, yBase); var bottomGenerator = new PolarPointsGenerator(center - halfLength * axis, xBase, yBase); // angles to use for circles generation. const int COUNT = 50; var angles = from i in Enumerable.Range(0, COUNT) select 2 * Math.PI * i / COUNT; // generate top/bottom circles in 3D var topCircle3d = from angle in angles select topGenerator.GetPoint(angle, radius); var bottomCircle3d = from angle in angles select bottomGenerator.GetPoint(angle, radius); // generate the left line from top to bottom var leftLine3d = from i in Enumerable.Range(0, COUNT) let top = topGenerator.GetPoint(0, radius) let bottom = bottomGenerator.GetPoint(0, radius) let fraction = i / (double)(COUNT - 1) select MathUtils3D.Lerp(top, bottom, fraction); // generate right line from top to bottom var rightLine3d = from i in Enumerable.Range(0, COUNT) let top = topGenerator.GetPoint(Math.PI, radius) let bottom = bottomGenerator.GetPoint(Math.PI, radius) let fraction = i / (double)(COUNT - 1) select MathUtils3D.Lerp(top, bottom, fraction); // project all lines to 2D var topCircle2d = Project(topCircle3d); var bottomCircle2d = Project(bottomCircle3d); var leftLine2d = Project(leftLine3d); var rightLine2d = Project(rightLine3d); // generate curve data var topCurve = new Polygon { CurveCategory = CurveCategories.Feature, Points = topCircle2d.ToArray() }; var bottomCurve = new Polygon { CurveCategory = CurveCategories.Feature, Points = bottomCircle2d.ToArray() }; var leftCurve = new Polyline { CurveCategory = CurveCategories.Silhouette, Points = leftLine2d.ToArray() }; var rightCurve = new Polyline { CurveCategory = CurveCategories.Silhouette, Points = rightLine2d.ToArray() }; // generate new primitive that exactly matches the curves var newcylinder = new NewCylinder(); newcylinder.Axis.Value = axis; newcylinder.Center.Value = center; newcylinder.Length.Value = halfLength * 2; newcylinder.Diameter.Value = radius * 2; // reset session data var sketchData = new SketchData { NewPrimitives = new NewPrimitive[] { newcylinder }, Curves = new PointsSequence[] { topCurve, bottomCurve, leftCurve, rightCurve }, SnappedPrimitives = new SnappedPrimitive[0], Annotations = new Annotation[0], }; sessionData.SketchData = sketchData; sessionData.Annotations.Clear(); sessionData.Annotations.AddRange(sketchData.Annotations); sessionData.NewPrimitives.Clear(); sessionData.NewPrimitives.AddRange(sketchData.NewPrimitives); sessionData.SketchObjects = sketchData.Curves.ToArray(); sessionData.SnappedPrimitives.Clear(); sessionData.SnappedPrimitives.AddRange(sessionData.SnappedPrimitives); }