public static void Test_GetWestNorthVectors_02() { const double maxDev = 1E-6; for (int i = -1; i <= 1; i += 2) { var v = new VectorD3D(0, 0, i); var westNorth = PolylineMath3D.GetWestNorthVectors(new LineD3D(PointD3D.Empty, (PointD3D)v)); var west = westNorth.Item1; var north = westNorth.Item2; Assert.AreEqual(west.Length, 1, maxDev); // is west normalized Assert.AreEqual(north.Length, 1, maxDev); // is north normalized Assert.AreEqual(VectorD3D.DotProduct(west, v), 0, maxDev); // is west perpendicular to forward Assert.AreEqual(VectorD3D.DotProduct(north, v), 0, maxDev); // is north perpendicular to forward Assert.AreEqual(VectorD3D.DotProduct(west, north), 0, maxDev); // is west perpendicular to north var matrix = Altaxo.Geometry.Matrix4x3.NewFromBasisVectorsAndLocation(west, north, v, PointD3D.Empty); Assert.AreEqual(matrix.Determinant, 1, maxDev); var westExpected = new VectorD3D(-1, 0, 0); var northExpected = new VectorD3D(0, -i, 0); Assert.AreEqual(westExpected.X, west.X, maxDev); Assert.AreEqual(westExpected.Y, west.Y, maxDev); Assert.AreEqual(westExpected.Z, west.Z, maxDev); Assert.AreEqual(northExpected.X, north.X, maxDev); Assert.AreEqual(northExpected.Y, north.Y, maxDev); Assert.AreEqual(northExpected.Z, north.Z, maxDev); } }
public static void Test_GetWestNorthVectors_01() { const double maxDev = 1E-6; for (int iTheta = -89; iTheta < 90; ++iTheta) { double theta = Math.PI * iTheta / 180.0; for (int iPhi = 0; iPhi < 360; ++iPhi) { double phi = Math.PI * iPhi / 180.0; var v = new VectorD3D(Math.Cos(phi) * Math.Cos(theta), Math.Sin(phi) * Math.Cos(theta), Math.Sin(theta)); Assert.AreEqual(v.Length, 1, maxDev); // is forward normalized var rawNorth = PolylineMath3D.GetRawNorthVectorAtStart(v); Assert.AreEqual(rawNorth.X, 0); Assert.AreEqual(rawNorth.Y, 0); Assert.AreEqual(rawNorth.Z, 1); var westNorth = PolylineMath3D.GetWestNorthVectors(new LineD3D(PointD3D.Empty, (PointD3D)v)); var west = westNorth.Item1; var north = westNorth.Item2; Assert.AreEqual(west.Length, 1, maxDev); // is west normalized Assert.AreEqual(north.Length, 1, maxDev); // is north normalized Assert.AreEqual(VectorD3D.DotProduct(west, v), 0, maxDev); // is west perpendicular to forward Assert.AreEqual(VectorD3D.DotProduct(north, v), 0, maxDev); // is north perpendicular to forward Assert.AreEqual(VectorD3D.DotProduct(west, north), 0, maxDev); // is west perpendicular to north var matrix = Altaxo.Geometry.Matrix4x3.NewFromBasisVectorsAndLocation(west, north, v, PointD3D.Empty); Assert.AreEqual(matrix.Determinant, 1, maxDev); var westExpected = new VectorD3D(-Math.Sin(phi), Math.Cos(phi), 0); var northExpected = new VectorD3D(-Math.Cos(phi) * Math.Sin(theta), -Math.Sin(phi) * Math.Sin(theta), Math.Cos(theta)); Assert.AreEqual(westExpected.X, west.X, maxDev); Assert.AreEqual(westExpected.Y, west.Y, maxDev); Assert.AreEqual(westExpected.Z, west.Z, maxDev); Assert.AreEqual(northExpected.X, north.X, maxDev); Assert.AreEqual(northExpected.Y, north.Y, maxDev); Assert.AreEqual(northExpected.Z, north.Z, maxDev); } } }
public override IGripManipulationHandle[] GetGrips(int gripLevel) { if (gripLevel <= 1) { var ls = (LineShape)_hitobject; var pts = new PointD3D[] { PointD3D.Empty, (PointD3D)ls.Size }; for (int i = 0; i < pts.Length; i++) { var pt = ls._transformation.Transform(pts[i]); pt = Transformation.Transform(pt); pts[i] = pt; } var grips = new IGripManipulationHandle[gripLevel == 0 ? 1 : 3]; // Translation grips var bounds = ls.Bounds; var wn = PolylineMath3D.GetWestNorthVectors(bounds.Size); var transformation = Matrix4x3.NewFromBasisVectorsAndLocation(wn.Item1, wn.Item2, bounds.Size.Normalized, PointD3D.Empty); transformation.AppendTransform(ls._transformation); transformation.AppendTransform(Transformation); double t1 = 0.55 * ls._linePen.Thickness1; double t2 = 0.55 * ls._linePen.Thickness2; var rect = new RectangleD3D(-t1, -t2, 0, 2 * t1, 2 * t2, bounds.Size.Length); var objectOutline = new RectangularObjectOutline(rect, transformation); grips[0] = new MovementGripHandle(this, objectOutline, null); // PathNode grips if (gripLevel == 1) { grips[2] = grips[0]; // put the movement grip to the background, the two NodeGrips need more priority var gripRadius = Math.Max(t1, t2); grips[0] = new PathNodeGripHandle(this, new VectorD3D(0, 0, 0), pts[0], gripRadius); grips[1] = new PathNodeGripHandle(this, new VectorD3D(1, 1, 1), pts[1], gripRadius); } return(grips); } else { return(base.GetGrips(gripLevel)); } }
public bool IsHit(LineD3D line, double thickness1, double thickness2) { if (!(line.Length > 0)) { return(false); } var eastnorth = PolylineMath3D.GetWestNorthVectors(line); var e = eastnorth.Item1; // east vector var n = eastnorth.Item2; // north vector double thickness1By2 = thickness1 / 2; double thickness2By2 = thickness2 / 2; var pts = new PointD3D[8]; pts[0] = _hitTransformation.Transform(line.P0 - thickness1By2 * e - thickness2By2 * n); pts[1] = _hitTransformation.Transform(line.P1 - thickness1By2 * e - thickness2By2 * n); pts[2] = _hitTransformation.Transform(line.P0 + thickness1By2 * e - thickness2By2 * n); pts[3] = _hitTransformation.Transform(line.P1 + thickness1By2 * e - thickness2By2 * n); pts[4] = _hitTransformation.Transform(line.P0 - thickness1By2 * e + thickness2By2 * n); pts[5] = _hitTransformation.Transform(line.P1 - thickness1By2 * e + thickness2By2 * n); pts[6] = _hitTransformation.Transform(line.P0 + thickness1By2 * e + thickness2By2 * n); pts[7] = _hitTransformation.Transform(line.P1 + thickness1By2 * e + thickness2By2 * n); double z; foreach (var ti in RectangleD3D.GetTriangleIndices()) { if (HitTestWithAlreadyTransformedPoints(pts[ti.Item1], pts[ti.Item2], pts[ti.Item3], out z) && z >= 0) { return(true); } } z = double.NaN; return(false); }
public void AddGeometry( Action <PointD3D, VectorD3D> AddPositionAndNormal, Action <int, int, int, bool> AddIndices, ref int vertexIndexOffset, PenX3D pen, LineD3D line ) { var westnorth = PolylineMath3D.GetWestNorthVectors(line); var westVector = westnorth.Item1; var northVector = westnorth.Item2; if (pen.DashPattern is DashPatterns.Solid) { // draw without a dash pattern - we consider the whole line as one dash segment, but instead of dash caps, with line caps _dashSegment.Initialize(pen.CrossSection, pen.Thickness1, pen.Thickness2, pen.LineStartCap, pen.LineEndCap, westVector, northVector, line); _dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, line, null, null); } else { // draw with a dash pattern _dashSegment.Initialize(pen, westVector, northVector, line); double dashOffset = 0; PointD3D lineStart = line.P0; PointD3D lineEnd = line.P1; var lineVector = line.LineVector; double lineLength = lineVector.Length; var lineVectorNormalized = lineVector / lineLength; // calculate the real start and end of the line, taking the line start and end cap length into account if (null != pen.LineStartCap) { var v = pen.LineStartCap.GetAbsoluteBaseInset(pen.Thickness1, pen.Thickness2); if (v < 0) { dashOffset = -v; lineStart += -v * lineVectorNormalized; lineLength += v; } } if (null != pen.LineEndCap) { var v = pen.LineEndCap.GetAbsoluteBaseInset(pen.Thickness1, pen.Thickness2); if (v < 0) { lineEnd += v * lineVectorNormalized; lineLength += v; } } // now draw the individual dash segments bool wasLineStartCapDrawn = false; bool wasLineEndCapDrawn = false; if (lineLength > 0) { foreach (var seg in Math3D.DissectStraightLineWithDashPattern(new LineD3D(lineStart, lineEnd), pen.DashPattern, pen.DashPattern.DashOffset, Math.Max(pen.Thickness1, pen.Thickness2), dashOffset)) { if (seg.P0 == lineStart) // this is the start of the line, thus we must use the lineStartCap instead of the dashStartCap { _dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, seg, pen.LineStartCap, null); wasLineStartCapDrawn = true; } else if (seg.P1 == lineEnd) // this is the end of the line, thus we must use the lineEndCap instead of the dashEndCap { _dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, seg, null, pen.LineEndCap); wasLineEndCapDrawn = true; } else // this is a normal dashSegment, thus we can use dashStartCap and dashEndCap { _dashSegment.AddGeometry(AddPositionAndNormal, AddIndices, ref vertexIndexOffset, seg, null, null); } } } object temporaryStorageSpace = null; // if the start cap was not drawn before, it must be drawn now if (!wasLineStartCapDrawn && null != pen.LineStartCap) { pen.LineStartCap.AddGeometry( AddPositionAndNormal, AddIndices, ref vertexIndexOffset, true, lineStart, westVector, northVector, lineVectorNormalized, pen.CrossSection, null, null, ref temporaryStorageSpace); } // if the end cap was not drawn before, it must be drawn now if (!wasLineEndCapDrawn && null != pen.LineEndCap) { pen.LineEndCap.AddGeometry( AddPositionAndNormal, AddIndices, ref vertexIndexOffset, false, lineEnd, westVector, northVector, lineVectorNormalized, pen.CrossSection, null, null, ref temporaryStorageSpace); } } }
protected override IGripManipulationHandle[] GetGrips(IHitTestObject hitTest, GripKind gripKind) { var list = new List <IGripManipulationHandle>(); /* * * const double gripNominalSize = 10; // 10 Points nominal size on the screen * if ((GripKind.Resize & gripKind) != 0) * { * double gripSize = gripNominalSize / pageScale; // 10 Points, but we have to consider the current pageScale * for (int i = 1; i < _gripRelPositions.Length; i++) * { * PointD2D outVec, pos; * if (1 == i % 2) * GetCornerOutVector(_gripRelPositions[i], hitTest, out outVec, out pos); * else * GetMiddleRayOutVector(_gripRelPositions[i], hitTest, out outVec, out pos); * * outVec *= (gripSize / outVec.VectorLength); * PointD2D altVec = outVec.Get90DegreeRotated(); * PointD2D ptStart = pos; * list.Add(new ResizeGripHandle(hitTest, _gripRelPositions[i], new MatrixD2D(outVec.X, outVec.Y, altVec.X, altVec.Y, ptStart.X, ptStart.Y))); * } * } */ /* * if ((GripKind.Rotate & gripKind) != 0) * { * double gripSize = 10 / pageScale; * // Rotation grips * for (int i = 1; i < _gripRelPositions.Length; i += 2) * { * PointD2D outVec, pos; * GetCornerOutVector(_gripRelPositions[i], hitTest, out outVec, out pos); * * outVec *= (gripSize / outVec.VectorLength); * PointD2D altVec = outVec.Get90DegreeRotated(); * PointD2D ptStart = pos; * list.Add(new RotationGripHandle(hitTest, _gripRelPositions[i], new MatrixD2D(outVec.X, outVec.Y, altVec.X, altVec.Y, ptStart.X, ptStart.Y))); * } * } */ /* * if ((GripKind.Rescale & gripKind) != 0) * { * double gripSize = 10 / pageScale; // 10 Points, but we have to consider the current pageScale * for (int i = 1; i < _gripRelPositions.Length; i++) * { * PointD2D outVec, pos; * if (1 == i % 2) * GetCornerOutVector(_gripRelPositions[i], hitTest, out outVec, out pos); * else * GetMiddleRayOutVector(_gripRelPositions[i], hitTest, out outVec, out pos); * * outVec *= (gripSize / outVec.VectorLength); * PointD2D altVec = outVec.Get90DegreeRotated(); * PointD2D ptStart = pos; * list.Add(new RescaleGripHandle(hitTest, _gripRelPositions[i], new MatrixD2D(outVec.X, outVec.Y, altVec.X, altVec.Y, ptStart.X, ptStart.Y))); * } * } */ /* * if ((GripKind.Shear & gripKind) != 0) * { * double gripSize = 10 / pageScale; // 10 Points, but we have to consider the current pageScale * for (int i = 2; i < _gripRelPositions.Length; i += 2) * { * PointD2D outVec, pos; * GetEdgeOutVector(_gripRelPositions[i], hitTest, out outVec, out pos); * * outVec *= (gripSize / outVec.VectorLength); * PointD2D altVec = outVec.Get90DegreeRotated(); * PointD2D ptStart = pos; * list.Add(new ShearGripHandle(hitTest, _gripRelPositions[i], new MatrixD2D(outVec.X, outVec.Y, altVec.X, altVec.Y, ptStart.X, ptStart.Y))); * } * } */ if ((GripKind.Move & gripKind) != 0) { var bounds = Bounds; var wn = PolylineMath3D.GetWestNorthVectors(bounds.Size); var transformation = Matrix4x3.NewFromBasisVectorsAndLocation(wn.Item1, wn.Item2, bounds.Size.Normalized, PointD3D.Empty); transformation.AppendTransform(_transformation); transformation.AppendTransform(hitTest.Transformation); double t1 = 0.55 * _linePen.Thickness1; double t2 = 0.55 * _linePen.Thickness2; var rect = new RectangleD3D(-t1, -t2, 0, 2 * t1, 2 * t2, bounds.Size.Length); var objectOutline = new RectangularObjectOutline(rect, transformation); list.Add(new MovementGripHandle(hitTest, objectOutline, null)); } return(list.ToArray()); }