예제 #1
0
 /// <summary>
 /// Overrides <see cref="CADability.GeoObject.ISurfaceImpl.SameGeometry (BoundingRect, ISurface, BoundingRect, double, out ModOp2D)"/>
 /// </summary>
 /// <param name="thisBounds"></param>
 /// <param name="other"></param>
 /// <param name="otherBounds"></param>
 /// <param name="precision"></param>
 /// <param name="firstToSecond"></param>
 /// <returns></returns>
 public override bool SameGeometry(BoundingRect thisBounds, ISurface other, BoundingRect otherBounds, double precision, out ModOp2D firstToSecond)
 {
     firstToSecond = ModOp2D.Null;
     if (other is PlaneSurface)
     {
         PlaneSurface second = other as PlaneSurface;
         GeoPoint     p      = PointAt(thisBounds.GetCenter());
         if (Math.Abs(second.Plane.Distance(p)) > precision)
         {
             return(false);
         }
         p = second.PointAt(otherBounds.GetCenter());
         if (Math.Abs(Plane.Distance(p)) > precision)
         {
             return(false);
         }
         if (Precision.SameDirection(Normal, second.Normal, false))
         {
             GeoPoint2D[] src = new GeoPoint2D[] { GeoPoint2D.Origin, new GeoPoint2D(1, 0), new GeoPoint2D(0, 1) };
             GeoPoint2D[] dst = new GeoPoint2D[3];
             for (int i = 0; i < 3; ++i)
             {
                 dst[i] = second.PositionOf(PointAt(src[i]));
             }
             firstToSecond = ModOp2D.Fit(src, dst, true);
             return(true);
         }
         else
         {
             return(false);
         }
     }
     return(base.SameGeometry(thisBounds, other, otherBounds, precision, out firstToSecond));
 }
예제 #2
0
        /// <summary>
        /// Overrides <see cref="CADability.Actions.ConstructAction.OnSetAction ()"/>
        /// </summary>
        public override void OnSetAction()
        {
            base.TitleId = "CopyCircularObjects";

            BoundingRect result = originals.GetExtent(Frame.ActiveView.ProjectedModel.Projection, true, false);

            centerPoint = base.ActiveDrawingPlane.ToGlobal(result.GetCenter());
            //			rotationPoint =  base.ActiveDrawingPlane.ToGlobal(result.GetLowerLeft());
            rotationPoint = centerPoint;
            distX         = result.Width;
            if (copCount == 0)
            {
                copCount = 4;
                copAngle = Math.PI / 2.0;
            }

            GeoPointInput rotPoint = new GeoPointInput("CopyCircularObjects.RotationPoint");

            rotPoint.SetGeoPointEvent += new CADability.Actions.ConstructAction.GeoPointInput.SetGeoPointDelegate(SetRotPoint);
            rotPoint.GetGeoPointEvent += new CADability.Actions.ConstructAction.GeoPointInput.GetGeoPointDelegate(GetRotPoint);
            rotPoint.Optional          = true;
            rotPoint.DefinesHotSpot    = true;
            rotPoint.HotSpotSource     = "Hotspots.png:0";

            IntInput copiesCount = new IntInput("CopyCircularObjects.CopiesCount", copCount);

            copiesCount.SetMinMax(0, int.MaxValue, true);
            copiesCount.SetIntEvent += new CADability.Actions.ConstructAction.IntInput.SetIntDelegate(SetCopiesCount);
            //			copiesCount.CalculateIntEvent +=new CADability.Actions.ConstructAction.IntInput.CalculateIntDelegate(CalcCopiesCount);

            BooleanInput fullCircle = new BooleanInput("CopyCircularObjects.FullCircle", "CopyCircularObjects.FullCircle.Values");

            fullCircle.SetBooleanEvent += new CADability.Actions.ConstructAction.BooleanInput.SetBooleanDelegate(SetFullCircle);
            fullCircle.GetBooleanEvent += new CADability.Actions.ConstructAction.BooleanInput.GetBooleanDelegate(GetFullCircle);

            copiesAngle                      = new AngleInput("CopyCircularObjects.CopiesAngle", copAngle);
            copiesAngle.ReadOnly             = !partOfCircle;
            copiesAngle.Optional             = !partOfCircle;
            copiesAngle.SetAngleEvent       += new CADability.Actions.ConstructAction.AngleInput.SetAngleDelegate(SetCopAngle);
            copiesAngle.GetAngleEvent       += new CADability.Actions.ConstructAction.AngleInput.GetAngleDelegate(GetCopAngle);
            copiesAngle.CalculateAngleEvent += new CADability.Actions.ConstructAction.AngleInput.CalculateAngleDelegate(CalculateCopAngle);

            BooleanInput rotObject = new BooleanInput("CopyCircularObjects.ObjectsRotation", "CopyCircularObjects.ObjectsRotation.Values");

            rotObject.SetBooleanEvent += new CADability.Actions.ConstructAction.BooleanInput.SetBooleanDelegate(SetObjectsRotation);
            rotObject.GetBooleanEvent += new CADability.Actions.ConstructAction.BooleanInput.GetBooleanDelegate(GetObjectsRotation);

            base.SetInput(rotPoint, copiesCount, fullCircle, copiesAngle, rotObject);

            base.OnSetAction();
            showCirc();
        }
예제 #3
0
        /// <summary>
        /// Constructs a line passing through <paramref name="location"/> with the provided <paramref name="direction"/> clipped by the
        /// rectangle <paramref name="clippedBy"/>
        /// </summary>
        /// <param name="location">Point on the (extension of the) line </param>
        /// <param name="direction">Direction of the line</param>
        /// <param name="clippedBy">Clipping rectangle</param>
        public Line2D(GeoPoint2D location, GeoVector2D direction, BoundingRect clippedBy)
        {
            direction.Norm(); // ist ja ne Kopie
            // das geht aber eleganter, oder?
            GeoPoint2D c = Geometry.DropPL(clippedBy.GetCenter(), location, direction);
            double     l = clippedBy.Width + clippedBy.Height;

            startPoint = c + l * direction;
            endPoint   = c - l * direction;
            ClipRect clr = new ClipRect(ref clippedBy);

            clr.ClipLine(ref startPoint, ref endPoint);
        }
예제 #4
0
        /// <summary>
        /// Overrides <see cref="CADability.Actions.ConstructAction.OnSetAction ()"/>
        /// </summary>
        public override void OnSetAction()
        {
            base.TitleId = "CopyMatrixObjects";

            BoundingRect result = originals.GetExtent(Frame.ActiveView.ProjectedModel.Projection, true, false);

            centerPoint = base.ActiveDrawingPlane.ToGlobal(result.GetCenter());
            distX       = result.Width;
            distY       = result.Height;
            // da oben static private, werden diese Variablen gemerkt. Beim ersten Mal vorbesetzen:
            if ((horRight == 0) & (horLeft == 0) & (verUp == 0) & (verDown == 0))
            {
                horRight = 3;
                verUp    = 2;
            }
            // da oben static private, wird diese Variable gemerkt. Beim ersten Mal vorbesetzen:
            if (dirV.IsNullVector())
            {
                dirV = new GeoVector(1.0, 0.0, 0.0);
            }

            IntInput horCountRight = new IntInput("CopyMatrixObjects.HorCountRight", horRight);

            horCountRight.SetMinMax(0, int.MaxValue, true);
            horCountRight.SetIntEvent += new CADability.Actions.ConstructAction.IntInput.SetIntDelegate(SetHorCountRight);
            //			horCountRight.CalculateIntEvent +=new CADability.Actions.ConstructAction.IntInput.CalculateIntDelegate(CalcHorCountRight);

            IntInput verCountUp = new IntInput("CopyMatrixObjects.VerCountUp", verUp);

            verCountUp.SetMinMax(0, int.MaxValue, true);
            verCountUp.SetIntEvent += new CADability.Actions.ConstructAction.IntInput.SetIntDelegate(SetVerCountUp);
            //			verCountUp.CalculateIntEvent +=new CADability.Actions.ConstructAction.IntInput.CalculateIntDelegate(CalcVerCountUp);

            horDist = new LengthInput("CopyMatrixObjects.HorDist", distX);
            horDist.SetDistanceFromLine(centerPoint, centerPoint + (dirV ^ base.ActiveDrawingPlane.Normal));
            horDist.SetLengthEvent += new CADability.Actions.ConstructAction.LengthInput.SetLengthDelegate(SetHorDist);

            verDist = new LengthInput("CopyMatrixObjects.VerDist", distY);
            verDist.SetDistanceFromLine(centerPoint, centerPoint + dirV);
            verDist.SetLengthEvent += new CADability.Actions.ConstructAction.LengthInput.SetLengthDelegate(SetVerDist);

            GeoVectorInput dir = new GeoVectorInput("CopyMatrixObjects.Direction", dirV);

            dir.Optional = true;
            dir.SetVectorFromPoint(centerPoint);
            dir.SetGeoVectorEvent += new CADability.Actions.ConstructAction.GeoVectorInput.SetGeoVectorDelegate(SetDir);
            dir.IsAngle            = true;

            IntInput horCountLeft = new IntInput("CopyMatrixObjects.HorCountLeft", horLeft);

            horCountLeft.SetMinMax(0, int.MaxValue, true);
            horCountLeft.Optional     = true;
            horCountLeft.SetIntEvent += new CADability.Actions.ConstructAction.IntInput.SetIntDelegate(SetHorCountLeft);
            //			horCountLeft.CalculateIntEvent +=new CADability.Actions.ConstructAction.IntInput.CalculateIntDelegate(CalcHorCountLeft);

            IntInput verCountDown = new IntInput("CopyMatrixObjects.VerCountDown", verDown);

            verCountDown.SetMinMax(0, int.MaxValue, true);
            verCountDown.Optional     = true;
            verCountDown.SetIntEvent += new CADability.Actions.ConstructAction.IntInput.SetIntDelegate(SetVerCountDown);
            //			verCountDown.CalculateIntEvent +=new CADability.Actions.ConstructAction.IntInput.CalculateIntDelegate(CalcVerCountDown);


            base.SetInput(horCountRight, verCountUp, horDist, verDist, dir, horCountLeft, verCountDown);

            base.OnSetAction();
            showMatrix();
        }
예제 #5
0
        public static Ellipse2D FromPoints(IEnumerable <GeoPoint2D> points)
        {
            GeoPoint2D[] pnts = null;
            if (points is GeoPoint2D[] a)
            {
                pnts = a;
            }
            else if (points is List <GeoPoint2D> l)
            {
                pnts = l.ToArray();
            }
            else
            {
                List <GeoPoint2D> lp = new List <GeoPoint2D>();
                foreach (GeoPoint2D point2D in points)
                {
                    lp.Add(point2D);
                }
                pnts = lp.ToArray();
            }
            Vector <double> observedX = new DenseVector(pnts.Length + 1); // there is no need to set values
            Vector <double> observedY = new DenseVector(pnts.Length + 1); // this is the data we want to achieve, namely 1.0, points on the unit circle distance to origin

            for (int i = 0; i < observedY.Count; i++)
            {
                observedY[i] = 1;
            }
            observedY[pnts.Length] = 0; // the scalar product of minor and major axis
            LevenbergMarquardtMinimizer lm  = new LevenbergMarquardtMinimizer(gradientTolerance: 1e-12, maximumIterations: 20);
            IObjectiveModel             iom = ObjectiveFunction.NonlinearModel(
                new Func <Vector <double>, Vector <double>, Vector <double> >(delegate(Vector <double> vd, Vector <double> ox) // function
            {
                // parameters: the homogeneous matrix that projects the ellipse to the unit circle
                ModOp2D m       = new ModOp2D(vd[0], vd[1], vd[2], vd[3], vd[4], vd[5]);
                DenseVector res = new DenseVector(pnts.Length + 1);
                for (int i = 0; i < pnts.Length; i++)
                {
                    GeoPoint2D pp = m * pnts[i];
                    res[i]        = pp.x * pp.x + pp.y * pp.y;
                }
                res[pnts.Length] = m[0, 0] * m[0, 1] + m[1, 0] * m[1, 1];     // the axis should be perpendicular
#if DEBUG
                double err = 0.0;
                for (int i = 0; i < pnts.Length; i++)
                {
                    err += (res[i] - 1) * (res[i] - 1);
                }
                err += res[pnts.Length] * res[pnts.Length];
#endif
                return(res);
            }),
                new Func <Vector <double>, Vector <double>, Matrix <double> >(delegate(Vector <double> vd, Vector <double> ox) // derivatives
            {
                // parameters: the homogeneous matrix that projects the ellipse to the unit circle
                ModOp2D m = new ModOp2D(vd[0], vd[1], vd[2], vd[3], vd[4], vd[5]);
                var prime = new DenseMatrix(pnts.Length + 1, 6);
                for (int i = 0; i < pnts.Length; i++)
                {
                    GeoPoint2D pp = m * pnts[i];
                    prime[i, 0]   = 2 * pnts[i].x * pp.x;
                    prime[i, 1]   = 2 * pnts[i].y * pp.x;
                    prime[i, 2]   = 2 * pp.x;
                    prime[i, 3]   = 2 * pnts[i].x * pp.y;
                    prime[i, 4]   = 2 * pnts[i].y * pp.y;
                    prime[i, 5]   = 2 * pp.y;
                }
                prime[pnts.Length, 0] = m[0, 1];
                prime[pnts.Length, 1] = m[0, 0];
                prime[pnts.Length, 2] = 0;
                prime[pnts.Length, 3] = m[1, 1];
                prime[pnts.Length, 4] = m[1, 0];
                prime[pnts.Length, 5] = 0;
                return(prime);
            }), observedX, observedY);

            BoundingRect ext = new BoundingRect(pnts);
            NonlinearMinimizationResult mres = lm.FindMinimum(iom, new DenseVector(new double[] { 2.0 / ext.Width, 0, -ext.GetCenter().x, 0, 2.0 / ext.Height, -ext.GetCenter().y }));

            if (mres.ReasonForExit == ExitCondition.Converged || mres.ReasonForExit == ExitCondition.RelativeGradient)
            {
                Vector <double> vd = mres.MinimizingPoint;
                ModOp2D         m  = new ModOp2D(vd[0], vd[1], vd[2], vd[3], vd[4], vd[5]);
                m = m.GetInverse();
                return(new Ellipse2D(m * GeoPoint2D.Origin, m * GeoVector2D.XAxis, m * GeoVector2D.YAxis));
            }
            else
            {
                return(null);
            }
        }
예제 #6
0
        public override ICurve2D GetProjectedCurve(ICurve curve, double precision)
        {
            ICurve2D dbg = base.GetProjectedCurve(curve, precision);

            if (curve is Ellipse elli)
            {   // a circle on the surface is projected to an ellipse in the uv plane
                GeoPoint2D[] positions = new GeoPoint2D[5];
                for (int i = 0; i < 5; i++)
                {
                    positions[i] = PositionOf(elli.PointAtParam(i * Math.PI * 2.0 / 6.0));
                }
                Ellipse2D elli2d = Ellipse2D.FromFivePoints(positions, true);
                double    prec   = precision;
                if (prec == 0)
                {
                    prec = Precision.eps;
                }
                if (elli2d == null)
                {
                    BoundingRect ext = new BoundingRect(positions);
                    GaussNewtonMinimizer.Ellipse2DFit(new ToIArray <GeoPoint2D>(positions), ext.GetCenter(), ext.Size / 2.0, ext.Size / 3.0, 0.0, prec, out elli2d);
                }
                else
                {
                    GaussNewtonMinimizer.Ellipse2DFit(new ToIArray <GeoPoint2D>(positions), elli2d.center, elli2d.majrad, elli2d.minrad, elli2d.majorAxis.Angle, prec, out elli2d);
                }
                //GeoPoint2D center = PositionOf(elli.Center);
                //GeoPoint2D maj = PositionOf(elli.Center + elli.MajorAxis);
                //GeoPoint2D min = PositionOf(elli.Center + elli.MinorAxis);
                //Geometry.PrincipalAxis(maj - center, min - center, out GeoVector2D majorAxis, out GeoVector2D minorAxis);
                //Ellipse2D elli2d = new Ellipse2D(center, maj - center, min - center);
                if (elli2d == null)
                {
                    return(base.GetProjectedCurve(curve, precision));
                }
                if (elli.IsArc)
                {
                    double       sp        = elli2d.PositionOf(PositionOf(elli.StartPoint));
                    double       ep        = elli2d.PositionOf(PositionOf(elli.EndPoint));
                    EllipseArc2D elliarc2d = elli2d.Trim(sp, ep) as EllipseArc2D;
                    // there must be a more sophisticated way to calculate the orientation and which part to use, but the following works:
                    double pm = elliarc2d.PositionOf(PositionOf(elli.PointAt(0.5)));
                    if (pm < 0 || pm > 1)
                    {
                        elliarc2d = elliarc2d.GetComplement();
                    }
                    pm = elliarc2d.PositionOf(PositionOf(elli.PointAt(0.1)));
                    if (pm > 0.5)
                    {
                        elliarc2d.Reverse();
                    }
                    return(elliarc2d);
                }
                else
                {   // get the correct orientation
                    double pos = elli2d.PositionOf(PositionOf(elli.PointAt(0.1)));
                    if (pos > 0.5)
                    {
                        elli2d.Reverse();
                    }
                    return(elli2d);
                }
            }
            return(base.GetProjectedCurve(curve, precision));
        }