public override void SetPosition(IObject3D selectedItem) { AxisAlignedBoundingBox selectedBounds = selectedItem.GetAxisAlignedBoundingBox(); Vector3 topPosition = GetTopPosition(selectedItem); Vector3 bottomPosition = new Vector3(topPosition.X, topPosition.Y, selectedBounds.MinXYZ.Z); double distBetweenPixelsWorldSpace = InteractionContext.World.GetWorldUnitsPerScreenPixelAtPosition(topPosition); Vector3 boxCenter = topPosition; boxCenter.Z += (10 + upArrowSize / 2) * distBetweenPixelsWorldSpace; Matrix4X4 centerMatrix = Matrix4X4.CreateTranslation(boxCenter); centerMatrix = Matrix4X4.CreateScale(distBetweenPixelsWorldSpace) * centerMatrix; TotalTransform = centerMatrix; lines.Clear(); // left lines // the lines on the bed var bedPosition = new Vector3(topPosition.X, topPosition.Y, 0); lines.Add(InteractionContext.World.GetScreenPosition(bedPosition + new Vector3(distToStart * distBetweenPixelsWorldSpace, 0, 0))); lines.Add(new Vector2(lines[0].X + lineLength, lines[0].Y)); lines.Add(InteractionContext.World.GetScreenPosition(bottomPosition + new Vector3(distToStart * distBetweenPixelsWorldSpace, 0, 0))); lines.Add(new Vector2(lines[2].X + lineLength, lines[2].Y)); }
private void SetWordHeight(List <MeshGroup> meshesList, List <ScaleRotateTranslate> meshTransforms) { if (meshesList.Count > 0) { for (int meshIndex = 0; meshIndex < meshesList.Count - 1; meshIndex++) { Vector3 startPosition = Vector3.Transform(Vector3.Zero, meshTransforms[meshIndex].translation); // take out the last scale double oldHeight = 1.0 / lastHeightValue; double newHeight = heightScrollBar.Value; // move the part to keep it in the same relative position ScaleRotateTranslate scale = meshTransforms[meshIndex]; scale.scale *= Matrix4X4.CreateScale(new Vector3(1, 1, oldHeight)); scale.scale *= Matrix4X4.CreateScale(new Vector3(1, 1, newHeight)); // if it's not the base int baseIndex = meshesList.Count - 1; AxisAlignedBoundingBox baseBounds = meshesList[baseIndex].GetAxisAlignedBoundingBox(meshTransforms[baseIndex].TotalTransform); scale.translation *= Matrix4X4.CreateTranslation(new Vector3(0, 0, baseBounds.ZSize - startPosition.z)); meshTransforms[meshIndex] = scale; } lastHeightValue = heightScrollBar.Value; } }
public override void SetPosition() { AxisAlignedBoundingBox selectedBounds = MeshViewerToDrawWith.GetBoundsForSelection(); Vector3 boundsCenter = selectedBounds.Center; Vector3 centerTop = new Vector3(boundsCenter.x, boundsCenter.y, selectedBounds.maxXYZ.z); Vector2 centerTopScreenPosition = MeshViewerToDrawWith.TrackballTumbleWidget.GetScreenPosition(centerTop); double distBetweenPixelsWorldSpace = MeshViewerToDrawWith.TrackballTumbleWidget.GetWorldUnitsPerScreenPixelAtPosition(centerTop); Matrix4X4 arrowTransform = Matrix4X4.CreateTranslation(new Vector3(centerTop.x, centerTop.y, centerTop.z + 20 * distBetweenPixelsWorldSpace)); arrowTransform = Matrix4X4.CreateScale(distBetweenPixelsWorldSpace) * arrowTransform; TotalTransform = arrowTransform; if (MouseOver || MouseDownOnControl) { heightDisplay.Visible = true; } else if (!view3DWidget.DisplayAllValueData) { heightDisplay.Visible = false; } }
private void Rebuild(UndoBuffer undoBuffer) { this.DebugDepth("Rebuild"); this.Children.Modify(list => { IObject3D lastChild = list.First(); list.Clear(); list.Add(lastChild); var offset = Offset; for (int i = 1; i < Count; i++) { var rotateRadians = MathHelper.DegreesToRadians(Rotate); if (ScaleOffset) { offset *= Scale; } var next = lastChild.Clone(); offset = Vector3.Transform(offset, Matrix4X4.CreateRotationZ(rotateRadians)); next.Matrix *= Matrix4X4.CreateTranslation(offset); if (RotatePart) { next.Matrix = next.ApplyAtBoundsCenter(Matrix4X4.CreateRotationZ(rotateRadians)); } next.Matrix = next.ApplyAtBoundsCenter(Matrix4X4.CreateScale(Scale)); list.Add(next); lastChild = next; } }); }
public void Stripes_With_An_Object_Transformation() { var pattern = new StripePattern(Color.White, Color.Black); var sphere = new Sphere(Matrix4X4.CreateScale(2, 2, 2)); pattern.ColorAt(new Point(1.5, 0, 0), sphere).ShouldBe(Color.White); }
public void SubtractIcosahedronsWorks() { Vector3 centering = new Vector3(100, 100, 20); Mesh meshA = PlatonicSolids.CreateIcosahedron(35); meshA.Translate(centering); Mesh meshB = PlatonicSolids.CreateIcosahedron(35); Vector3 finalTransform = new Vector3(105.240172225344, 92.9716306394062, 18.4619570261172); Vector3 rotCurrent = new Vector3(4.56890223673623, -2.67874102322035, 1.02768848238523); Vector3 scaleCurrent = new Vector3(1.07853517569753, 0.964980885267323, 1.09290934544604); Matrix4X4 transformB = Matrix4X4.CreateScale(scaleCurrent) * Matrix4X4.CreateRotation(rotCurrent) * Matrix4X4.CreateTranslation(finalTransform); meshB.Transform(transformB); Mesh result = CsgOperations.Subtract(meshA, meshB); AxisAlignedBoundingBox a_aabb = meshA.GetAxisAlignedBoundingBox(); AxisAlignedBoundingBox b_aabb = meshB.GetAxisAlignedBoundingBox(); AxisAlignedBoundingBox intersect_aabb = result.GetAxisAlignedBoundingBox(); Assert.IsTrue(a_aabb.XSize == 40 && a_aabb.YSize == 40 && a_aabb.ZSize == 40); Assert.IsTrue(intersect_aabb.XSize == 40 && intersect_aabb.YSize == 40 && intersect_aabb.ZSize == 40); // Todo: turn this on //Assert.IsTrue(result.IsManifold()); }
private void SetWordSize(List <MeshGroup> meshesList, List <Matrix4X4> meshTransforms) { if (meshesList.Count > 0) { for (int meshIndex = 0; meshIndex < meshesList.Count; meshIndex++) { Vector3 startPositionRelCenter = Vector3.Transform(Vector3.Zero, meshTransforms[meshIndex]); // take out the last scale double oldSize = 1.0 / lastSizeValue; Vector3 unscaledStartPositionRelCenter = startPositionRelCenter * oldSize; double newSize = sizeScrollBar.Value; Vector3 endPositionRelCenter = unscaledStartPositionRelCenter * newSize; Vector3 deltaPosition = endPositionRelCenter - startPositionRelCenter; // move the part to keep it in the same relative position meshTransforms[meshIndex] *= Matrix4X4.CreateScale(new Vector3(oldSize, oldSize, oldSize)); meshTransforms[meshIndex] *= Matrix4X4.CreateScale(new Vector3(newSize, newSize, newSize)); meshTransforms[meshIndex] *= Matrix4X4.CreateTranslation(deltaPosition); } lastSizeValue = sizeScrollBar.Value; } CenterTextOnScreen(meshesList, meshTransforms); }
public void View_Transform_Looking_In_Positive_Z_Position() { Matrix4X4.CreateViewTransform(new Point(0, 0, 0), new Point(0, 0, 1), new Vector(0, 1, 0)) .ShouldBe(Matrix4X4.CreateScale(-1, 1, -1)); }
public override void SetPosition(IObject3D selectedItem, MeshSelectInfo selectInfo) { AxisAlignedBoundingBox selectedBounds = selectedItem.GetAxisAlignedBoundingBox(); Vector3 topPosition = GetTopPosition(selectedItem); var bottomPosition = new Vector3(topPosition.X, topPosition.Y, selectedBounds.MinXYZ.Z); double distBetweenPixelsWorldSpace = Object3DControlContext.World.GetWorldUnitsPerScreenPixelAtPosition(topPosition); Vector3 arrowCenter = topPosition; arrowCenter.Z += arrowSize / 2 * distBetweenPixelsWorldSpace; var centerMatrix = Matrix4X4.CreateTranslation(arrowCenter); centerMatrix = Matrix4X4.CreateScale(distBetweenPixelsWorldSpace) * centerMatrix; TotalTransform = centerMatrix; lines.Clear(); // left lines lines.Add(Object3DControlContext.World.GetScreenPosition(topPosition + new Vector3(DistToStart * distBetweenPixelsWorldSpace, 0, 0))); lines.Add(new Vector2(lines[0].X + LineLength, lines[0].Y)); lines.Add(Object3DControlContext.World.GetScreenPosition(bottomPosition + new Vector3(DistToStart * distBetweenPixelsWorldSpace, 0, 0))); lines.Add(new Vector2(lines[2].X + LineLength, lines[2].Y)); }
public static List <Segment> GetUnorderdSegments(Mesh mesh, Plane plane, int outputScale = 1000) { var rotation = new Quaternion(plane.Normal, Vector3.UnitZ); var flattenedMatrix = Matrix4X4.CreateRotation(rotation); flattenedMatrix *= Matrix4X4.CreateTranslation(0, 0, -plane.DistanceFromOrigin); // collect all the segments this plane intersects and record them in unordered segments in z 0 space var meshTo0Plane = flattenedMatrix * Matrix4X4.CreateScale(outputScale); var unorderedSegments = new List <Segment>(); foreach (var face in mesh.Faces) { if (face.GetCutLine(mesh.Vertices, plane, out Vector3 start, out Vector3 end)) { var startAtZ0 = Vector3Ex.Transform(start, meshTo0Plane); var endAtZ0 = Vector3Ex.Transform(end, meshTo0Plane); unorderedSegments.Add( new Segment( new IntPoint(startAtZ0.X, startAtZ0.Y), new IntPoint(endAtZ0.X, endAtZ0.Y))); } } return(unorderedSegments); }
private void UpdateBoundsItem() { if (Children.Count == 2) { var transformAabb = ItemWithTransform.GetAxisAlignedBoundingBox(); var fitAabb = FitBounds.GetAxisAlignedBoundingBox(); var fitSize = fitAabb.Size; if (boundsSize.X != 0 && boundsSize.Y != 0 && boundsSize.Z != 0 && (fitSize != boundsSize || fitAabb.Center != transformAabb.Center)) { FitBounds.Matrix *= Matrix4X4.CreateScale( boundsSize.X / fitSize.X, boundsSize.Y / fitSize.Y, boundsSize.Z / fitSize.Z); FitBounds.Matrix *= Matrix4X4.CreateTranslation( transformAabb.Center - FitBounds.GetAxisAlignedBoundingBox().Center); } if (AlternateCentering) { var test = GetCenteringTransformVisualCenter(UntransformedChildren, Diameter / 2); } else { var test = GetCenteringTransformExpandedToRadius(UntransformedChildren, Diameter / 2); } } }
public override Task Rebuild() { this.DebugDepth("Rebuild"); var rebuildLock = this.RebuildLock(); return(ApplicationController.Instance.Tasks.Execute( "Mirror".Localize(), null, (reporter, cancellationToken) => { SourceContainer.Visible = true; RemoveAllButSource(); var oldMatrix = this.Matrix; this.Matrix = Matrix4X4.Identity; var mirrorMatrix = Matrix4X4.Identity; switch (MirrorOn) { case MirrorAxis.X_Axis: mirrorMatrix = this.ApplyAtBoundsCenter(Matrix4X4.CreateScale(-1, 1, 1)); break; case MirrorAxis.Y_Axis: mirrorMatrix = this.ApplyAtBoundsCenter(Matrix4X4.CreateScale(1, -1, 1)); break; case MirrorAxis.Z_Axis: mirrorMatrix = this.ApplyAtBoundsCenter(Matrix4X4.CreateScale(1, 1, -1)); break; } foreach (var sourceItem in SourceContainer.VisibleMeshes()) { var originalMesh = sourceItem.Mesh; var transformedMesh = originalMesh.Copy(CancellationToken.None); var sourceToThisMatrix = sourceItem.WorldMatrix(this); // move it to us then mirror then move it back transformedMesh.Transform(sourceToThisMatrix * mirrorMatrix * sourceToThisMatrix.Inverted); transformedMesh.ReverseFaces(); var newMesh = new Object3D() { Mesh = transformedMesh }; newMesh.CopyWorldProperties(sourceItem, this, Object3DPropertyFlags.All, false); this.Children.Add(newMesh); } this.Matrix = oldMatrix; SourceContainer.Visible = false; rebuildLock.Dispose(); Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Children)); return Task.CompletedTask; })); }
private void SetWordSize(List <MeshGroup> meshesList, List <ScaleRotateTranslate> meshTransforms) { Vector3 bedCenter = new Vector3(MeshViewerWidget.BedCenter); if (meshesList.Count > 0) { for (int meshIndex = 0; meshIndex < meshesList.Count; meshIndex++) { Vector3 startPositionRelCenter = Vector3.Transform(Vector3.Zero, meshTransforms[meshIndex].translation) - bedCenter; // take out the last scale double oldSize = 1.0 / lastSizeValue; Vector3 unscaledStartPositionRelCenter = startPositionRelCenter * oldSize; double newSize = sizeScrollBar.Value; Vector3 endPositionRelCenter = unscaledStartPositionRelCenter * newSize; Vector3 deltaPosition = endPositionRelCenter - startPositionRelCenter; // move the part to keep it in the same relative position ScaleRotateTranslate scale = meshTransforms[meshIndex]; scale.scale *= Matrix4X4.CreateScale(new Vector3(oldSize, oldSize, oldSize)); scale.scale *= Matrix4X4.CreateScale(new Vector3(newSize, newSize, newSize)); scale.translation *= Matrix4X4.CreateTranslation(deltaPosition); meshTransforms[meshIndex] = scale; } lastSizeValue = sizeScrollBar.Value; } }
private Matrix4X4 GetCenteringTransformExpandedToRadius(IEnumerable <IObject3D> items, double radius) { IEnumerable <Vector2> GetTranslatedXY() { foreach (var item in items) { foreach (var mesh in item.VisibleMeshes()) { var worldMatrix = mesh.WorldMatrix(this); foreach (var vertex in mesh.Mesh.Vertices) { yield return(new Vector2(vertex.Transform(worldMatrix))); } } } } var circle = SmallestEnclosingCircle.MakeCircle(GetTranslatedXY()); // move the circle center to the origin var centering = Matrix4X4.CreateTranslation(-circle.Center.X, -circle.Center.Y, 0); // scale to the fit size in x y double scale = radius / circle.Radius; var scalling = Matrix4X4.CreateScale(scale, scale, 1); return(centering * scalling); }
private void CreateBase(List <MeshGroup> meshesList, List <Matrix4X4> meshTransforms, List <PlatingMeshGroupData> platingDataList) { if (meshesList.Count > 0) { AxisAlignedBoundingBox bounds = meshesList[0].GetAxisAlignedBoundingBox(meshTransforms[0]); for (int i = 1; i < meshesList.Count; i++) { bounds = AxisAlignedBoundingBox.Union(bounds, meshesList[i].GetAxisAlignedBoundingBox(meshTransforms[i])); } double roundingScale = 20; RectangleDouble baseRect = new RectangleDouble(bounds.minXYZ.x, bounds.minXYZ.y, bounds.maxXYZ.x, bounds.maxXYZ.y); baseRect.Inflate(2); baseRect *= roundingScale; RoundedRect baseRoundedRect = new RoundedRect(baseRect, 1 * roundingScale); Mesh baseMeshResult = VertexSourceToMesh.Extrude(baseRoundedRect, unscaledBaseHeight / 2 * roundingScale * sizeScrollBar.Value * heightScrollBar.Value); baseMeshResult.Transform(Matrix4X4.CreateScale(1 / roundingScale)); meshesList.Add(new MeshGroup(baseMeshResult)); platingDataList.Add(new PlatingMeshGroupData()); meshTransforms.Add(Matrix4X4.CreateTranslation(0, 0, 0)); PlatingHelper.CreateITraceableForMeshGroup(platingDataList, meshesList, meshesList.Count - 1, null); } }
private Matrix4X4 GetRotationTransform(IObject3D selectedItem, out double radius) { Matrix4X4 rotationCenterTransform; AxisAlignedBoundingBox currentSelectedBounds = selectedItem.GetAxisAlignedBoundingBox(Matrix4X4.Identity); Vector3 controlCenter = GetControlCenter(selectedItem); Vector3 rotationCenter = GetRotationCenter(selectedItem, currentSelectedBounds); if (mouseDownInfo != null) { rotationCenter = mouseDownInfo.SelectedObjectRotationCenter; controlCenter = mouseDownInfo.ControlCenter; } double distBetweenPixelsWorldSpace = InteractionContext.World.GetWorldUnitsPerScreenPixelAtPosition(rotationCenter); double lengthFromCenterToControl = (rotationCenter - controlCenter).Length; radius = lengthFromCenterToControl * (1 / distBetweenPixelsWorldSpace); rotationTransformScale = distBetweenPixelsWorldSpace; rotationCenterTransform = Matrix4X4.CreateScale(distBetweenPixelsWorldSpace) * Matrix4X4.CreateTranslation(rotationCenter); var center = Vector3Ex.Transform(Vector3.Zero, rotationCenterTransform); switch (RotationAxis) { case 0: { rotationCenterTransform = Matrix4X4.CreateTranslation(-center) * Matrix4X4.CreateRotation(new Vector3(0, -MathHelper.Tau / 4, 0)) * Matrix4X4.CreateRotation(new Vector3(-MathHelper.Tau / 4, 0, 0)) * rotationCenterTransform; var center2 = Vector3Ex.Transform(Vector3.Zero, rotationCenterTransform); rotationCenterTransform *= Matrix4X4.CreateTranslation(center - center2); } break; case 1: { rotationCenterTransform = Matrix4X4.CreateTranslation(-center) * Matrix4X4.CreateRotation(new Vector3(MathHelper.Tau / 4, 0, 0)) * Matrix4X4.CreateRotation(new Vector3(0, MathHelper.Tau / 4, 0)) * rotationCenterTransform; var center2 = Vector3Ex.Transform(Vector3.Zero, rotationCenterTransform); rotationCenterTransform *= Matrix4X4.CreateTranslation(center - center2); } break; case 2: break; } return(rotationCenterTransform); }
public override void DrawGlContent(DrawGlContentEventArgs e) { bool shouldDrawScaleControls = true; var selectedItem = RootSelection; if (InteractionContext.SelectedInteractionVolume != null && InteractionContext.SelectedInteractionVolume as ScaleTopControl == null) { shouldDrawScaleControls = false; } if (selectedItem != null) { if (shouldDrawScaleControls) { // don't draw if any other control is dragging if (MouseOver) { GLHelper.Render(topScaleMesh, Color.Red, TotalTransform, RenderTypes.Shaded); } else { GLHelper.Render(topScaleMesh, Color.Black, TotalTransform, RenderTypes.Shaded); } } if (e != null) { // evaluate the position of the up line to draw Vector3 topPosition = GetTopPosition(selectedItem); var bottomPosition = topPosition; var originalSelectedBounds = selectedItem.GetAxisAlignedBoundingBox(Matrix4X4.Identity); bottomPosition.Z = originalSelectedBounds.MinXYZ.Z; // render with z-buffer full black double distBetweenPixelsWorldSpace = InteractionContext.World.GetWorldUnitsPerScreenPixelAtPosition(topPosition); Vector3 delta = topPosition - bottomPosition; Vector3 centerPosition = (topPosition + bottomPosition) / 2; Matrix4X4 rotateTransform = Matrix4X4.CreateRotation(new Quaternion(delta, Vector3.UnitX)); Matrix4X4 scaleTransform = Matrix4X4.CreateScale((topPosition - bottomPosition).Length, distBetweenPixelsWorldSpace, distBetweenPixelsWorldSpace); Matrix4X4 lineTransform = scaleTransform * rotateTransform * Matrix4X4.CreateTranslation(centerPosition); Frustum clippingFrustum = GLHelper.GetClippingFrustum(InteractionContext.World); if (e.ZBuffered) { InteractionContext.World.Render3DLine(clippingFrustum, bottomPosition, topPosition, Color.Black); } else { // render on top of everything very lightly InteractionContext.World.Render3DLine(clippingFrustum, bottomPosition, topPosition, new Color(Color.Black, 20), false); } } } base.DrawGlContent(e); }
//Mouse drag, calculate rotation public void OnMouseMove(Vector2 mousePosition) { switch (currentTrackingType) { case MouseDownType.Rotation: activeRotationQuaternion = Quaternion.Identity; //Map the point to the sphere MapToSphere(mousePosition, out rotationCurrent); //Return the quaternion equivalent to the rotation //Compute the vector perpendicular to the begin and end vectors Vector3 Perp = Vector3.Cross(rotationStart, rotationCurrent); //Compute the length of the perpendicular vector if (Perp.Length > Epsilon) { //if its non-zero //We're ok, so return the perpendicular vector as the transform after all activeRotationQuaternion.X = Perp.x; activeRotationQuaternion.Y = Perp.y; activeRotationQuaternion.Z = Perp.z; //In the quaternion values, w is cosine (theta / 2), where theta is the rotation angle activeRotationQuaternion.W = Vector3.Dot(rotationStart, rotationCurrent); } break; case MouseDownType.Translation: { Vector2 mouseDelta = mousePosition - lastTranslationMousePosition; Vector2 scalledDelta = mouseDelta / screenCenter.x * 4.75; Vector3 offset = new Vector3(scalledDelta.x, scalledDelta.y, 0); offset = Vector3.TransformPosition(offset, Matrix4X4.Invert(CurrentRotation)); offset = Vector3.TransformPosition(offset, localToScreenTransform); currentTranslationMatrix = currentTranslationMatrix * Matrix4X4.CreateTranslation(offset); lastTranslationMousePosition = mousePosition; } break; case MouseDownType.Scale: { Vector2 mouseDelta = mousePosition - lastScaleMousePosition; double zoomDelta = 1; if (mouseDelta.y < 0) { zoomDelta = 1 - (-1 * mouseDelta.y / 100); } else if (mouseDelta.y > 0) { zoomDelta = 1 + (1 * mouseDelta.y / 100); } currentTranslationMatrix *= Matrix4X4.CreateScale(zoomDelta); lastScaleMousePosition = mousePosition; } break; default: throw new NotImplementedException(); } }
public void Can_Multiply_Vector_By_Scaling_Matrix() { var scaling = Matrix4X4.CreateScale(2, 3, 4); var vector = new Vector(-4, 6, 8); (scaling * vector).ShouldBe(new Vector(-8, 18, 32)); (scaling.Invert().inverse *vector).ShouldBe(new Vector(-2, 2, 2)); }
public void Can_Multiply_Point_By_Scaling_Matrix() { var scaling = Matrix4X4.CreateScale(2, 3, 4); var negativeScale = Matrix4X4.CreateScale(-1, 1, 1); var point = new Point(-4, 6, 8); (scaling * point).ShouldBe(new Point(-8, 18, 32)); (negativeScale * point).ShouldBe(new Point(4, 6, 8)); }
public void Stripe_With_Pattern_Transformation() { var pattern = new StripePattern(Color.White, Color.Black) { TransformMatrix = Matrix4X4.CreateScale(2, 2, 2), }; pattern.ColorAt(new Point(1.5, 0, 0), new Sphere()).ShouldBe(Color.White); }
private Matrix4X4 GetCenteringTransformVisualCenter(IEnumerable <IObject3D> items, double goalRadius) { IEnumerable <(Vector2, Vector2, Vector2)> GetPolygons() { foreach (var item in items) { foreach (var meshItem in item.VisibleMeshes()) { var worldMatrix = meshItem.WorldMatrix(this); var faces = meshItem.Mesh.Faces; var vertices = meshItem.Mesh.Vertices; foreach (var face in faces) { if (face.normal.TransformNormal(worldMatrix).Z > 0) { yield return( new Vector2(vertices[face.v0].Transform(worldMatrix)), new Vector2(vertices[face.v1].Transform(worldMatrix)), new Vector2(vertices[face.v2].Transform(worldMatrix)) ); } } } } } var outsidePolygons = new List <List <IntPoint> >(); var projection = new Polygons(); // remove all holes from the polygons so we only center the major outlines var polygons = OrthographicZProjection.GetClipperPolygons(GetPolygons()); foreach (var polygon in polygons) { if (polygon.GetWindingDirection() == 1) { outsidePolygons.Add(polygon); } } IVertexSource outsideSource = outsidePolygons.CreateVertexStorage(); Vector2 center = outsideSource.GetWeightedCenter(); outsideSource = new VertexSourceApplyTransform(outsideSource, Affine.NewTranslation(-center)); double radius = MaxXyDistFromCenter(outsideSource); double scale = goalRadius / radius; var scalling = Matrix4X4.CreateScale(scale, scale, 1); var centering = Matrix4X4.CreateTranslation(-center.X, -center.Y, 0); return(centering * scalling); }
public override async Task Rebuild() { var rebuildLock = this.RebuildLock(); SourceContainer.Visible = true; await ApplicationController.Instance.Tasks.Execute( "Advanced Array".Localize(), null, (reporter, cancellationToken) => { this.DebugDepth("Rebuild"); var sourceContainer = SourceContainer; this.Children.Modify(list => { list.Clear(); list.Add(sourceContainer); var lastChild = sourceContainer.Children.First(); list.Add(lastChild.Clone()); var offset = Offset; var count = Count.Value(this); var rotate = Rotate.Value(this); var scale = Scale.Value(this); for (int i = 1; i < count; i++) { var rotateRadians = MathHelper.DegreesToRadians(rotate); if (ScaleOffset) { offset *= scale; } var next = lastChild.Clone(); offset = Vector3Ex.Transform(offset, Matrix4X4.CreateRotationZ(rotateRadians)); next.Matrix *= Matrix4X4.CreateTranslation(offset); if (RotatePart) { next.Matrix = next.ApplyAtBoundsCenter(Matrix4X4.CreateRotationZ(rotateRadians)); } next.Matrix = next.ApplyAtBoundsCenter(Matrix4X4.CreateScale(scale)); list.Add(next); lastChild = next; } }); ProcessIndexExpressions(); SourceContainer.Visible = false; UiThread.RunOnIdle(() => { rebuildLock.Dispose(); Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Children)); }); return Task.CompletedTask; }); }
public override Task Rebuild() { this.DebugDepth("Rebuild"); tabScale = 3; // by default we don't want tab with to be greater than 10 mm if (TabWidth > 10) { tabScale = 1; } else if (TabWidth > 5) { tabScale = 2; } using (RebuildLock()) { using (new CenterAndHeightMaintainer(this)) { this.Children.Modify((list) => { list.Clear(); }); var calibrateX = GetTab(true); this.Children.Add(calibrateX); var calibrateY = GetTab(false); this.Children.Add(calibrateY); // add in the corner connector this.Children.Add(new Object3D() { Mesh = PlatonicSolids.CreateCube(), Matrix = Matrix4X4.CreateTranslation(-1 / 2.0, 1 / 2.0, 1 / 2.0) * Matrix4X4.CreateScale(TabDepth, TabDepth, BaseHeight), Color = Color.LightBlue }); if (WipeTowerSize > 0) { // add in the wipe tower this.Children.Add(new Object3D() { Mesh = new CylinderObject3D(1, 1, 50).Mesh, Matrix = Matrix4X4.CreateTranslation(1 / 2.0, 1 / 2.0, 1 / 2.0) * Matrix4X4.CreateScale(WipeTowerSize, WipeTowerSize, BaseHeight + Layers * ChangingHeight) * Matrix4X4.CreateTranslation(TabDepth * 1, TabDepth * 2, 0), OutputType = PrintOutputTypes.WipeTower }); } } } Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Mesh)); return(Task.CompletedTask); }
public override void SetPosition(IObject3D selectedItem, MeshSelectInfo selectInfo) { var(hitPos, _) = GetHitPosition(selectedItem); double distBetweenPixelsWorldSpace = Object3DControlContext.World.GetWorldUnitsPerScreenPixelAtPosition(hitPos); var centerMatrix = Matrix4X4.CreateTranslation(hitPos); centerMatrix = Matrix4X4.CreateScale(distBetweenPixelsWorldSpace) * centerMatrix; TotalTransform = centerMatrix; }
public void Scaled_Sphere_Intersection() { var ray = new Ray(new Point(0, 0, -5), new Vector(0, 0, 1)); var sphere = new Sphere(Matrix4X4.CreateScale(2, 2, 2)); var intersections = sphere.GetIntersections(ray); intersections.Count.ShouldBe(2); intersections.ShouldContain(new Intersection(3, sphere)); intersections.ShouldContain(new Intersection(7, sphere)); }
public void Can_Create_Matrix_From_Scaling() { Matrix4X4.CreateScale(5, -3, 2) .ShouldBe(new Matrix4X4 { M11 = 5, M12 = 0, M13 = 0, M14 = 0, M21 = 0, M22 = -3, M23 = 0, M24 = 0, M31 = 0, M32 = 0, M33 = 2, M34 = 0, M41 = 0, M42 = 0, M43 = 0, M44 = 1, }); }
public void Stripe_With_Pattern_And_Object_Transform() { var pattern = new StripePattern(Color.White, Color.Black) { TransformMatrix = Matrix4X4.CreateTranslation(0.5, 0, 0), }; var sphere = new Sphere(Matrix4X4.CreateScale(2, 2, 2)); pattern.ColorAt(new Point(2.5, 0, 0), sphere).ShouldBe(Color.White); }
private Matrix4X4 ShapeMatrix() { var worldPosition = getPosition(); double distBetweenPixelsWorldSpace = context.World.GetWorldUnitsPerScreenPixelAtPosition(worldPosition); var scale = Matrix4X4.CreateScale(distBetweenPixelsWorldSpace * blockSize); var offset = Matrix4X4.CreateTranslation(getPosition()); var cubeMatrix = scale * offset; return(cubeMatrix); }
/// <summary> /// Calculate the transform to move from the plane to a scaled polygon at plane z=1 offset = 0 /// </summary> /// <param name="plane">The plane to transform from</param> /// <param name="outputScale">The amout to scale up when transforming</param> /// <returns>The plane to accomplish the transform</returns> public static Matrix4X4 GetTransformTo0Plane(Plane plane, int outputScale = 1000) { var rotation = new Quaternion(plane.Normal, Vector3.UnitZ); var flattenedMatrix = Matrix4X4.CreateRotation(rotation); flattenedMatrix *= Matrix4X4.CreateTranslation(0, 0, -plane.DistanceFromOrigin); var transformTo0Plane = flattenedMatrix * Matrix4X4.CreateScale(outputScale); return(transformTo0Plane); }