예제 #1
0
파일: TestMath3D.cs 프로젝트: olesar/Altaxo
        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);
            }
        }
예제 #2
0
파일: TestMath3D.cs 프로젝트: olesar/Altaxo
        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);
                }
            }
        }
예제 #3
0
            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));
                }
            }
예제 #4
0
        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);
        }
예제 #5
0
        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);
                }
            }
        }
예제 #6
0
        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());
        }