Example #1
0
        internal override List <Target> GenerateTargets(UserSocket floating)
        {
            // copied from Lined.GenerateDefaultTargets and modified
            List <Target> targets = new List <Target>();

            // add all of the vertices
            // note that using m_intDefinedVertices rather than Vertices.Count omits the last closing vertex if closed
            for (int index = 0; index <= m_DefinedVertices - 1; index++)
            {
                targets.Add(new Target(this, Vertices[index], Target.Types.Vertex, floating, Target.Priorities.Vertex, shapeIndex: index));
            }
            // check the lines
            for (int index = 0; index <= Vertices.Count - 2; index++)
            {
                // it is relatively quick to check if the point is close enough to the bounding rectangle for the arc
                RectangleF bounds = new RectangleF(Vertices[index].X, Vertices[index].Y, 0, 0);
                Geometry.Extend(ref bounds, Vertices[index + 1]);
                Geometry.Extend(ref bounds, m_ControlPoints[index * 2]);
                Geometry.Extend(ref bounds, m_ControlPoints[index * 2 + 1]);
                if (Geometry.DirtyDistance(floating.Centre, bounds) <= Target.MaximumInterestDistance)
                {
                    float maximumError = MaximumTError(index) * 3;                     // doesn't need to be so precise, because the target point release be on the Bezier
                    // said the user probably can't tell if it is a little bit short or long
                    Target create = GenerateLineTargetOnOneBezier(floating, GetSingleCurve(index), targets, maximumError, index);
                    if (create != null)
                    {
                        targets.Add(create);
                    }
                }
            }
            return(targets);
        }
Example #2
0
        internal override List <UserSocket> GetPointsWhichSnapWhenMoving()
        {
            if (!AutoTargets)
            {
                return(null);
            }
            List <UserSocket> list = (from pt in Vertices select UserSocket.CreateForPoint(pt)).ToList();

            list.Add(UserSocket.CreateForPoint(Middle()));
            return(list);
        }
Example #3
0
        public override void CopyFrom(Datum other, CopyDepth depth, Mapping mapID)
        {
            base.CopyFrom(other, depth, mapID);
            UserSocket socket = (UserSocket)other;

            m_Centre       = socket.m_Centre;
            m_Exit         = socket.m_Exit;
            Options        = socket.Options;
            Classification = socket.Classification;
            m_Bounds       = RectangleF.Empty;
        }
Example #4
0
        // base does Centre and Middle

        internal override List <Target> GenerateTargets(UserSocket floating)
        {
            if (!AutoTargets)
            {
                return(null);
            }
            List <Target> targets = new List <Target>();

            Lined.AddLineTargets(this, targets, floating, m_Bounds.GetPoints(), true);
            targets.Add(new Target(this, Centre, Target.Types.Centre, floating));
            return(targets);
        }
Example #5
0
        internal override List <UserSocket> GetPointsWhichSnapWhenMoving()
        {
            if (!AutoTargets)
            {
                return(null);
            }
            List <UserSocket> list = new List <UserSocket>();

            foreach (PointF pt in m_Bounds.GetPoints())
            {
                list.Add(UserSocket.CreateForPoint(pt));
            }
            list.Add(UserSocket.CreateForPoint(Middle()));
            return(list);
        }
Example #6
0
        public float RotationRequired(UserSocket other)
        {
            // rotation required of this socket to make it fit other socket. 0 means they match or one or both don't care about angle
            if (m_Exit.IsEmpty)
            {
                return(0);
            }
            if (other.ExitVector.IsEmpty)
            {
                return(0);
            }
            float angle = other.ExitVector.VectorAngle() - m_Exit.VectorAngle() - Geometry.ANGLE180;

            // angle180 on end, because they are expected to be OPPOSITE
            return(Geometry.NormaliseAnglePlusMinus180(angle));
        }
Example #7
0
 public bool GenderCompatible(UserSocket other)
 {
     if ((Options & OptionsEnum._Gender) == OptionsEnum._Gender)
     {
         return(true);                // this shape doesn't care
     }
     if ((other.Options & OptionsEnum._Gender) == OptionsEnum._Gender)
     {
         return(true);                // other shape doesn't care
     }
     if ((Options & OptionsEnum._Gender) == (other.Options & OptionsEnum._Gender))
     {
         return(false);                // genders same- fails
     }
     return(true);
 }
Example #8
0
        public bool AngleCompatibile(UserSocket other)
        {
            // vectors must be opposite (apart from rounding error), if both defined
            if (m_Exit.IsEmpty)
            {
                return(true);
            }
            if (other.ExitVector.IsEmpty)
            {
                return(true);
            }
            float angle = Geometry.AbsoluteAngularDifference(m_Exit.VectorAngle(), other.ExitVector.VectorAngle());

            if (angle > Geometry.ANGLE180 - Geometry.NEGLIGIBLEANGLESMALL)
            {
                return(true);
            }
            return(false);
        }
Example #9
0
 // a more convenient constructor for shapes when generating targets:
 // might also want to store the source socket eventually
 public Target(Shape shape, PointF position, Types type, UserSocket source, Priorities priority = Priorities.Standard, float intersectionCertainty = Geometry.PI / 2, int shapeIndex = -1)
 {
     // ObjSource if the moving item for which targets have been requested
     // -1 is used as the default shape index to make it obvious when it was not defined (0 is usually valid)
     Shape    = shape;
     Position = position;
     Priority = priority;
     Type     = type;
     Debug.Assert(priority == Priorities.Intersection || intersectionCertainty == Geometry.ANGLE90);             // certainty has no effect unless it is an intersection
     if (type == Types.Intersection)
     {
         Uncertainty = Geometry.ANGLE90 - intersectionCertainty;
     }
     if (source != null)
     {
         Distance = Geometry.DistanceBetween(source.Centre, position);                 // otherwise Distance left as 0.  Not used for real snapping targets, but can be used for some dummy ones
     }
     ShapeIndex = shapeIndex;
     if (type == Types.GrabSpot && !(this is ForGrabSpot))
     {
         throw new ArgumentException(nameof(type));
     }
 }
Example #10
0
        public const float MAXIMUMSNAPROTATION = Geometry.ANGLE45 / 2;         // most to autorotate a moving shape

        internal override List <Target> GenerateTargets(UserSocket floating)
        {
            List <Target> list = new List <Target>();

            EnsureSocketList();
            foreach (UserSocket socket in m_Sockets)
            {
                if ((socket.Options & UserSocket.OptionsEnum.ShapeSnap) > 0)
                {
                    // if they aren't compatible we still generate the shape, but mark it as failed
                    Target newTarget = new Target(this, socket.Centre, Target.Types.Vertex, floating, Target.Priorities.Vertex);
                    if (!floating.ClassCompatible(socket) || !floating.GenderCompatible(socket))
                    {
                        newTarget.Mismatch = true;
                    }
                    else
                    {
                        float angle = floating.RotationRequired(socket);
                        if (Math.Abs(angle) > MAXIMUMSNAPROTATION)
                        {
                            newTarget = null;                             // angle so far out it is not a match at all
                        }
                        else if (angle != 0)
                        {
                            // can autorotate
                            newTarget.RotationRequired = angle;
                        }
                    }
                    if (newTarget != null)
                    {
                        list.Add(newTarget);
                    }
                }
            }
            return(list);
        }
Example #11
0
 internal override List <Target> GenerateTargets(UserSocket floating)
 {
     return(base.GenerateTargetsDefault(floating, false));
 }
Example #12
0
 internal override List <Target> GenerateTargets(UserSocket floating)
 {
     return(MaskShape.GenerateTargets(floating));
 }
Example #13
0
 internal override List <Target> GenerateTargets(UserSocket floating) => Element.GenerateTargets(floating);
Example #14
0
 internal override List <Target> GenerateTargets(UserSocket floating) => base.GenerateTargetsDefault(floating, Closed());
Example #15
0
 public bool ClassCompatible(UserSocket other)
 {
     return(string.IsNullOrEmpty(Classification) || string.IsNullOrEmpty(other.Classification) || Classification == other.Classification);
 }
Example #16
0
 internal override List <Target> GenerateTargets(UserSocket floating)
 {
     return(new List <Target> {
         new Target(this, m_Centre, Target.Types.Centre, floating)
     });
 }