Ejemplo n.º 1
0
 public LinkedPoint(double X, double Y, Sketch.Substroke par)
 {
     this.x      = X;
     this.y      = Y;
     this.parent = par;
     index       = null;
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Constructor. Create from Shape. Shallow copy of subshapes, deep copy of substrokes.
        /// </summary>
        /// <param name="shape">A Shape.</param>
        public Shape(Shape shape)
        {
            this.Name = shape.Name;
            List <Substroke> newSubstrokes = new List <Substroke>(shape._substrokes.Count);

            foreach (Substroke s in shape._substrokes)
            {
                Substroke newS = s.CloneConstruct();
                newS.ParentShape = this;
                newSubstrokes.Add(newS);
            }

            _substrokes = new List <Substroke>(shape._substrokes.Count);
            foreach (Substroke s in newSubstrokes)
            {
                AddSubstroke(s);
            }
            _xmlAttributes = shape._xmlAttributes.Clone();

            AlreadyGrouped = shape.AlreadyGrouped;
            AlreadyLabeled = shape.AlreadyLabeled;
            UserLabeled    = shape.UserLabeled;

            TemplateName    = shape.TemplateName;
            TemplateDrawing = shape.TemplateDrawing;
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Add a Substroke to this shape
        /// </summary>
        /// <param name="substroke">A Substroke</param>
        public void AddSubstroke(Substroke substroke)
        {
            if (!this.substrokes.Contains(substroke))
            {
                int low  = 0;
                int high = this.substrokes.Count - 1;
                int mid;
                while (low <= high)
                {
                    mid = (high - low) / 2 + low;
                    if ((ulong)substroke.XmlAttrs.Time < (ulong)((Substroke)this.substrokes[mid]).XmlAttrs.Time)
                    {
                        high = mid - 1;
                    }
                    else
                    {
                        low = mid + 1;
                    }
                }

                this.substrokes.Insert(low, substroke);

                if (substroke.ParentShapes != null && !substroke.ParentShapes.Contains(this))
                {
                    substroke.ParentShapes.Add(this);
                }

                UpdateSpatialAttributes(this);
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Constructor for Single Stroke Features. Calculates Single Stroke Features
        /// </summary>
        /// <param name="substroke">Stroke to find feature values for</param>
        /// <param name="featureList">Which features to use</param>
        public FeatureStroke(Sketch.Substroke substroke, Dictionary <string, bool> featureList) :
            this(substroke)
        {
            featuresToUse = featureList;

            CalculateSingleStrokeFeatures();
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Add the substroke into a new, labeled Shape.
        /// </summary>
        /// <param name="substroke">Substroke to be included in the label</param>
        /// <param name="label">Label's string</param>
        /// <param name="probability">Probability of a label's accuracy</param>
        /// <returns>The labeled shape added to the Sketch</returns>
        public Shape AddLabel(Substroke substroke, string label, double probability)
        {
            ArrayList tempArrayList = new ArrayList();

            tempArrayList.Add(substroke);

            return(AddLabel(tempArrayList, label, probability));
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Add the substroke into a new, labeled Shape.
        /// </summary>
        /// <param name="substroke">Substroke to be included in the label</param>
        /// <param name="label">Label's string</param>
        /// <returns>The labeled shape added to the Sketch</returns>
        public Shape AddLabel(Substroke substroke, string label)
        {
            ArrayList tempArrayList = new ArrayList();

            tempArrayList.Add(substroke);

            return(AddLabel(tempArrayList, label));
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Create a stroke from an InkStroke. Used when adding the stroke.
        /// </summary>
        /// <param name="stroke"></param>
        /// <param name="dtGuid"></param>
        /// <param name="SAMPLE_RATE"></param>
        public Stroke(System.Windows.Ink.Stroke stroke, Guid dtGuid, float SAMPLE_RATE)
            : this()
        {
            // Get the timestamp for the function using a const Guid
            ulong theTime;

            if (stroke.ContainsPropertyData(dtGuid))
            {
                // MIT file format
                ulong fileTime = (ulong)stroke.GetPropertyData(dtGuid);
                theTime = (fileTime - 116444736000000000) / 10000;
            }
            else
            {
                theTime = ((ulong)DateTime.Now.ToFileTime() - 116444736000000000) / 10000;
            }

            // Set time data for each point and add it to the list of substroke's points
            List <Point> pointsToAdd = new List <Point>();

            System.Windows.Input.StylusPointCollection stylusPoints = stroke.StylusPoints;
            int numPoints = stylusPoints.Count;

            for (int i = 0; i < numPoints; i++)
            {
                // We believe this to be the standard sample rate.  The multiplication by 1,000 is to convert from
                // seconds to milliseconds.
                //
                // Our time is in the form of milliseconds since Jan 1, 1970
                //
                // NOTE: The timestamp for the stroke is made WHEN THE PEN IS LIFTED
                System.Windows.Input.StylusPoint styPoint = stylusPoints[i];
                ulong adjustedTime = theTime - (ulong)((1 / SAMPLE_RATE * 1000) * (numPoints - i));
                Point toAdd        = new Point((float)styPoint.X, (float)styPoint.Y, (float)styPoint.PressureFactor, Convert.ToUInt64(adjustedTime), "point");
                // HACK: Add back in if debugging: if (!pointsToAdd.Contains(toAdd))
                pointsToAdd.Add(toAdd);
            }

            // Create the new substroke using its drawing attributes
            System.Windows.Ink.DrawingAttributes drawingAttributes = stroke.DrawingAttributes;
            Substroke substroke = new Substroke(pointsToAdd);

            substroke.Name      = "substroke";
            substroke.Color     = drawingAttributes.Color.GetHashCode();
            substroke.PenTip    = drawingAttributes.StylusTip.ToString();
            substroke.PenWidth  = (float)drawingAttributes.Width;
            substroke.PenHeight = (float)drawingAttributes.Height;
            substroke.Source    = "InkSketch.canvasStrokeToSketchStroke";
            substroke.Start     = pointsToAdd[0].Id;
            substroke.End       = pointsToAdd[pointsToAdd.Count - 1].Id;
            this.AddSubstroke(substroke);

            // Update the stroke's attributes
            this._xmlAttributes.Name   = "stroke";
            this._xmlAttributes.Time   = (ulong)theTime;
            this._xmlAttributes.Type   = "stroke";
            this._xmlAttributes.Source = "Converter";
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Adds the Substroke to the Stroke's Substroke ArrayList.
        /// Calling this repeatedly may be much slower than calling
        /// AddSubstrokes(list).
        /// </summary>
        /// <param name="substroke">Substroke to add</param>
        public void AddSubstroke(Substroke substroke)
        {
            if (substroke == null)
            {
                throw new ArgumentException("Cannot add a null substroke to a stroke!");
            }

            AddSubstrokes(new Substroke[] { substroke });
        }
Ejemplo n.º 9
0
        public LinkedPoint(Substroke par, int index)
        {
            Point p = par.PointsL[index];

            this.x      = p.X;
            this.y      = p.Y;
            this.parent = par;
            this.index  = index;
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Compare this Substroke to another based on time.
        /// Returns less than 0 if this time is less than the other's.
        /// Returns 0 if this time is equal to the other's.
        /// Returns greater than 0 if this time is greater than the other's.
        /// </summary>
        /// <param name="obj">The other Substroke to compare this one to</param>
        /// <returns>An integer indicating how the Substroke times compare</returns>
        int System.IComparable.CompareTo(Object obj)
        {
            Substroke other = (Substroke)obj;

            ulong thisTime  = (ulong)this.XmlAttrs.Time;
            ulong otherTime = (ulong)other.XmlAttrs.Time;

            return((int)(thisTime - otherTime));
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Splits a Substroke at the given index.
        /// </summary>
        /// <param name="index">Index where the Substroke should be split</param>
        public void SplitAt(int index)
        {
            // If there is nothing to split...
            if (index < 1 || index > this.points.Count - 2)
            {
                return;
            }

            Substroke lastHalf = new Substroke();

            // We invalidate these things
            this.XmlAttrs.Height = null;
            this.XmlAttrs.Width  = null;
            this.XmlAttrs.Area   = null;
            this.XmlAttrs.LeftX  = null;
            this.XmlAttrs.TopY   = null;
            this.XmlAttrs.X      = null;
            this.XmlAttrs.Y      = null;

            // Copy the rest of the attributes into the second half
            lastHalf.XmlAttrs    = this.XmlAttrs.Clone();
            lastHalf.XmlAttrs.Id = System.Guid.NewGuid();

            int length = points.Count;

            // Add points to the last Half
            lastHalf.AddPoints(points.GetRange(index, length - index));

            // Change the start of the last half
            lastHalf.XmlAttrs.Start = ((Point)lastHalf.points[0]).XmlAttrs.Id;

            // Remove all the points in the second half
            this.points.RemoveRange(index, length - index);
            //this.points.RemoveRange(index + 1, length - index - 1);	// Used if we want to include the middle, split point in both Substrokes

            // Add the end to the first half
            this.XmlAttrs.End = ((Point)this.points[index - 1]).XmlAttrs.Id;

            // The new first half time is equal to the last point's time in it
            this.XmlAttrs.Time = ((Point)this.points[index - 1]).XmlAttrs.Time;

            // Update the parent info
            lastHalf.ParentStroke = this.parentStroke;
            lastHalf.ParentStroke.AddSubstroke(lastHalf);

            lastHalf.ParentShapes = this.parentShapes;

            length = lastHalf.parentShapes.Count;
            for (int i = 0; i < length; ++i)
            {
                if (lastHalf.parentShapes[i] != null)
                {
                    ((Shape)lastHalf.parentShapes[i]).AddSubstroke(lastHalf);
                }
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Removes a Substroke from the Stroke.
        /// </summary>
        /// <param name="substroke">Substroke to remove</param>
        /// <returns>True iff the Substroke is removed</returns>
        public bool RemoveSubstroke(Substroke substroke)
        {
            if (this._substrokes.Contains(substroke))
            {
                RemoveSubstrokes(new Substroke[] { substroke });
                return(true);
            }

            return(false);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Split the substroke at the given index at the given indices
        /// </summary>
        /// <param name="substrokeIndex">The index of the substroke</param>
        /// <param name="pointIndices">The indices to split at</param>
        public void SplitSubstrokeAt(int substrokeIndex, int[] pointIndices)
        {
            // We need to step through backwards so we dont mess up the indices
            Array.Sort(pointIndices);
            Array.Reverse(pointIndices);

            Substroke first = (Substroke)this.substrokes[substrokeIndex];

            first.SplitAt(pointIndices);
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Returns the average pressure of the points in a stroke
        /// </summary>
        /// <param name="stroke">The stroke</param>
        /// <returns>the average pressure</returns>
        public ushort findAvgPressure(Sketch.Substroke stroke)
        {
            List <Point> points        = stroke.PointsL;
            ulong        totalPressure = 0;

            foreach (Point p in points)
            {
                totalPressure += p.Pressure;
            }
            return((ushort)(totalPressure / ((ulong)points.Count)));
        }
Ejemplo n.º 15
0
 /// <summary>
 /// Removes a single Substroke from the Stroke's Substroke ArrayList.
 /// </summary>
 /// <param name="substroke">The substroke to remove</param>
 /// <returns>True iff the substroke was successfully removed</returns>
 public bool RemoveSubstroke(Substroke substroke)
 {
     if (this.substrokes.Contains(substroke))
     {
         this.substrokes.Remove(substroke);
         return(true);
     }
     else
     {
         return(false);
     }
 }
Ejemplo n.º 16
0
        /// <summary>
        /// Removes a Substroke from the Sketch.  Removes parent stroke if
        /// this substroke is the only substroke in the stroke.
        /// </summary>
        /// <param name="stroke">Substroke to remove</param>
        /// <returns>True iff Substroke is removed</returns>
        public bool RemoveSubstroke(Substroke substroke)
        {
            Stroke parentStroke = substroke.ParentStroke;

            if (parentStroke.Substrokes.Length == 1)
            {
                return(RemoveStroke(parentStroke));
            }
            else
            {
                return(parentStroke.RemoveSubstroke(substroke));
            }
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Load a Stroke with a corresponding substroke.
        /// Precondition: Substroke is in the Sketch/FeatureSketch.
        /// Postcondition: The stroke's in our bookkeeping data structures.
        /// </summary>
        /// <param name="inkStroke">The Stroke to add</param>
        public void AddInkStrokeWithSubstroke(System.Windows.Ink.Stroke inkStroke, Sketch.Substroke substroke)
        {
            // Format the inkStroke
            inkStroke.AddPropertyData(dtGuid, (ulong)DateTime.Now.ToFileTime());
            String strokeId = System.Guid.NewGuid().ToString();

            inkStroke.AddPropertyData(idGuid, strokeId);

            // Add it to the data structures (InkCanvas last)
            ink2sketchStr.Add(strokeId, substroke.XmlAttrs.Id);
            sketchStr2ink.Add(substroke.XmlAttrs.Id, strokeId);
            substrokeIdMap.Add(substroke.XmlAttrs.Id, substroke);
            mInkCanvas.Strokes.Add(inkStroke);
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Transforms (e.g. moves or resizes) an Ink Stroke in the Sketch.
        /// Converts the given Ink Stroke into a Sketch stroke and then
        /// updates the Sketch to point to the new Ink Stroke instead of the old one.
        /// </summary>
        /// <param name="iStroke">The Ink Stroke to modify</param>
        public void TransformInkStroke(Microsoft.Ink.Stroke iStroke)
        {
            if (!ink2sketchStr.ContainsKey(iStroke.Id))
            {
                return;
            }

            if (!substrokeIdMap.ContainsKey(ink2sketchStr[iStroke.Id]))
            {
                return;
            }

            Sketch.Stroke newSStroke = mReadJnt.InkStroke2SketchStroke(iStroke);
            Substroke     oldSStroke = substrokeIdMap[ink2sketchStr[iStroke.Id]];

            // FIXME need to masquerade Substroke Ids.  Here
            // we abitrarily synchronize the Ids of the first
            // substroke in each stroke.  We do this because
            // ReadJnt will always return a stroke with one
            // substroke.  In some use cases (e.g. fragmenting),
            // matching Ids like this might cause problems.
            //
            // Eric Peterson: June 30, 2009: When loading an old
            // xml sketch, we need to preserve the time data for
            // each point.
            newSStroke.Substrokes[0].XmlAttrs.Id = oldSStroke.XmlAttrs.Id;
            for (int i = 0; i < oldSStroke.Points.Length; i++)
            {
                newSStroke.Substrokes[0].Points[i].Time = oldSStroke.Points[i].Time;
            }

            // Update mapping between strokes
            ink2sketchStr.Remove(iStroke.Id);
            ink2sketchStr.Add(iStroke.Id, newSStroke.Substrokes[0].XmlAttrs.Id);
            sketchStr2ink.Remove(oldSStroke.XmlAttrs.Id);
            sketchStr2ink.Add(newSStroke.Substrokes[0].XmlAttrs.Id, iStroke.Id);
            substrokeIdMap.Remove(newSStroke.Substrokes[0].XmlAttrs.Id);
            substrokeIdMap.Add(newSStroke.Substrokes[0].XmlAttrs.Id, newSStroke.Substrokes[0]);

            // Update pointers in Sketch
            Sketch.Substroke newSSubstroke = newSStroke.Substrokes[0];
            foreach (Sketch.Shape shape in oldSStroke.ParentShapes)
            {
                shape.AddSubstroke(newSSubstroke);
            }

            Sketch.RemoveSubstroke(oldSStroke);
            Sketch.AddStroke(newSStroke);
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Removes a Substroke from the Shape.
        /// </summary>
        /// <param name="substroke">Substroke to remove</param>
        /// <returns>True iff the Substroke is removed</returns>
        public bool RemoveSubstroke(Substroke substroke)
        {
            if (this.substrokes.Contains(substroke))
            {
                substroke.ParentShapes.Remove(this);
                this.substrokes.Remove(substroke);
                UpdateSpatialAttributes(this);

                return(true);
            }
            else
            {
                return(false);
            }
        }
Ejemplo n.º 20
0
            public override void Execute()
            {
                if (this.selection.Count > 0)
                {
                    Sketch.Substroke selected = this.mIdToSubstroke[this.selection[0].Id] as Sketch.Substroke;

                    if (selected != null)
                    {
                        FragmentDialogBox fdb = new FragmentDialogBox(new Sketch.Stroke[1] {
                            selected.ParentStroke
                        });
                        fdb.Show();
                    }
                }
            }
Ejemplo n.º 21
0
        /// <summary>
        /// Removes an ArrayList of Substrokes from the Shape.
        /// </summary>
        /// <param name="substrokes">Substrokes to remove</param>
        /// <returns>True iff all Substrokes are removed</returns>
        public bool RemoveSubstrokes(ArrayList substrokes)
        {
            bool completelyRemoved = true;

            for (int i = 0; i < substrokes.Count; ++i)
            {
                Substroke currSubstroke = (Substroke)substrokes[i];

                if (!RemoveSubstroke(currSubstroke))
                {
                    completelyRemoved = false;
                    Console.WriteLine("Substroke " + currSubstroke.XmlAttrs.Id + " not removed!");
                }
            }

            return(completelyRemoved);
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Called when a substroke is added to this shape, and before it is added
        /// to the list of substrokes. By default this does the following:
        ///    - updates the substroke's parent shape
        ///    - connects this shape to everything the substroke is connected to
        /// </summary>
        /// <param name="substroke">the substroke to acquire</param>
        protected virtual void AcquireSubstroke(Substroke substroke)
        {
            if (substroke.ParentShape != null && substroke.ParentShape != this)
            {
                throw new ArgumentException("Cannot add a substroke belonging to a different shape!");
            }
            substroke.ParentShape = this;

            foreach (EndPoint endpoint in substroke.Endpoints)
            {
                Shape connected = endpoint.ConnectedShape;
                if (connected != null)
                {
                    ConnectedShapes.Add(connected);
                    connected.ConnectedShapes.Add(this);
                }
            }
        }
Ejemplo n.º 23
0
        /// <summary>
        /// Refreshes the underlying data structures corresponding to the inkStroke after the
        /// inkStroke has been modified (moved or resized)
        /// </summary>
        /// <param name="inkStroke">The Ink Stroke to modify</param>
        public void UpdateInkStroke(System.Windows.Ink.Stroke inkStroke)
        {
            // Delete the old stroke but save its shape for the new Stroke
            Sketch.Shape oldShape = GetSketchSubstrokeByInk(inkStroke).ParentShape;
            DeleteStroke(inkStroke);

            // Add the new stroke to the Sketch and put it in the old Shape
            AddStroke(inkStroke);
            Sketch.Substroke newSubstroke = GetSketchSubstrokeByInk(inkStroke);
            if (oldShape != null)
            {
                oldShape.AddSubstroke(newSubstroke);
                if (!Sketch.ShapesL.Contains(oldShape))
                {
                    Sketch.AddShape(oldShape);
                }
            }
        }
Ejemplo n.º 24
0
        /// <summary>
        /// Find the shortests distance from a point in this shape to a
        /// given point.
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="exclude">If this is set, that substroke will not be considered
        /// when looking for close points</param>
        /// <returns>the shortest distance to a point in a substroke of this shape, or
        /// Double.MaxValue if there are no points in this substroke</returns>
        public double minDistanceTo(double x, double y, Substroke exclude = null)
        {
            double bestDistance = Double.MaxValue;

            foreach (Substroke substroke in _substrokes)
            {
                if (substroke == exclude)
                {
                    continue;
                }

                double distance = substroke.minDistanceTo(x, y);
                if (distance < bestDistance)
                {
                    bestDistance = distance;
                }
            }
            return(bestDistance);
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Returns the time it took to draw the substroke
        /// </summary>
        /// <param name="sub">The substroke</param>
        /// <returns>the total time it took to draw the substroke</returns>
        public ulong findSubStrokeTime(Sketch.Substroke sub)
        {
            double       minTime = Double.PositiveInfinity;
            double       maxTime = Double.NegativeInfinity;
            List <Point> points  = sub.PointsL;

            foreach (Point p in points)
            {
                if ((Double)(p.Time) < minTime)
                {
                    minTime = p.Time;
                }
                if ((Double)(p.Time) > maxTime)
                {
                    maxTime = (Double)(p.Time);
                }
            }
            return((ulong)(maxTime - minTime));
        }
        public string Recognize(Sketch.Substroke stroke)
        {
            List <double> features  = getFeatureValues(stroke.PointsL);
            string        best      = "NA";
            double        bestScore = double.MinValue;
            List <double> allScores = new List <double>();

            // Compute scores for each class
            for (int c = 0; c < _classNames.Count; c++)
            {
                double sum = 0.0;
                for (int i = 0; i < _weights_0.Count; i++)
                {
                    sum += _weights.GetElement(c, i) * features[i];
                }

                double score = this._weights_0[c] + sum;
                allScores.Add(score);
                if (score > bestScore)
                {
                    bestScore = score;
                    best      = _classNames[c];
                }
            }
            allScores.Remove(bestScore);

            // Get Probability - for rejection
            double sumP = 0.0;

            foreach (double s in allScores)
            {
                sumP += Math.Exp(s - bestScore);
            }
            double probability = 1 / sumP;

            if (probability < SCORE_THRESHOLD)
            {
                return("Unknown");
            }

            return(best);
        }
Ejemplo n.º 27
0
        /// <summary>
        /// Find the parent shape of a list of strokes
        /// </summary>
        /// <param name="strokeIds"></param>
        /// <returns></returns>
        private void LabelShape(ListSet <string> strokeIds, string name)
        {
            // Create list of all shapes
            List <Shape> shapes = new List <Shape>();

            foreach (string s in strokeIds)
            {
                Sketch.Substroke sub = sketchPanel.InkSketch.GetSketchSubstrokeByInkId(s);
                if (!shapes.Contains(sub.ParentShape))
                {
                    shapes.Add(sub.ParentShape);
                }
            }

            // Set the name to what the user specified
            foreach (Shape shape in shapes)
            {
                shape.Name = name;
            }
        }
Ejemplo n.º 28
0
        /// <summary>
        /// Finds the features of a Substroke
        /// </summary>
        /// <param name="substroke">Substroke to find features for</param>
        public FeatureStroke(Sketch.Substroke substroke)
        {
            Point[] points = substroke.Points;
            _substroke  = substroke;
            spatial     = new Spatial(points);
            arcLength   = new ArcLength(points);
            slope       = new Slope(points);
            speed       = new Speed(points);
            curvature   = new Curvature(points, ArcLength.Profile, Slope.TanProfile);
            fit         = new Fit(substroke);
            boundingBox = Compute.BoundingBox(substroke.Points);

            this.id = (System.Guid)substroke.Id;

            features      = new Dictionary <string, Feature>();
            featuresToUse = new Dictionary <string, bool>();
            addAllFeatures();

            if (UseThetas)
            {
                thetas = Compute.FindThetas(substroke.Points);
                //thetas = Compute.Normalize(thetas, Math.PI * 2.0);
            }
            else
            {
                thetas = new double[0];
            }

            if (UseArcLength)
            {
                features.Add("Arc Length", new InkLength(arcLength.TotalLength));
            }

            if (UseClosedPath)
            {
                features.Add("Part of a Closed Path", new PartOfClosedPath(false));
                features.Add("Inside a Closed Path", new InsideClosedPath(false));
            }
        }
Ejemplo n.º 29
0
        /// <summary>
        /// Finds a given shape's closest endpoint to the invoking shape.
        /// </summary>
        /// <param name="otherShape">The shape with endpoints</param>
        /// <returns>The closest endpoint in otherShape</returns>
        public EndPoint ClosestEndpointFrom(Shape otherShape)
        {
            double    distance         = Double.MaxValue;
            Substroke closestSubstroke = null;
            EndPoint  closestEndpoint  = null;

            foreach (Substroke stroke in otherShape.Substrokes)
            {
                foreach (EndPoint endpoint in stroke.Endpoints)
                {
                    double ptDist = Math.Sqrt(Math.Pow(endpoint.X - this.Centroid.X, 2) +
                                              Math.Pow(endpoint.Y - this.Centroid.Y, 2));
                    if (ptDist < distance)
                    {
                        distance         = ptDist;
                        closestSubstroke = stroke;
                        closestEndpoint  = endpoint;
                    }
                }
            }

            return(closestEndpoint);
        }
Ejemplo n.º 30
0
        /// <summary>
        /// Removes a Substroke from the Sketch.  Removes parent stroke if
        /// this substroke is the only substroke in the stroke.
        /// </summary>
        /// <param name="substroke">Substroke to remove</param>
        /// <returns>True iff Substroke is removed</returns>
        public bool RemoveSubstroke(Substroke substroke)
        {
            Stroke parentStroke = substroke.ParentStroke;

            // Remove this substrokes from parent shapes
            // and remove all parent shapes that contain
            // only this substroke
            object[] parentShapes = substroke.ParentShapes.ToArray();
            for (int i = 0; i < parentShapes.Length; ++i)
            {
                if (parentShapes[i] != null)
                {
                    Shape currentShape = (Shape)parentShapes[i];
                    if (currentShape.Substrokes.Length == 1)
                    {
                        RemoveShape(currentShape);
                    }
                    else
                    {
                        currentShape.RemoveSubstroke(substroke);
                    }
                }
            }

            // Remove the substroke from the parent stroke,
            // or, if the substroke is its parent stroke's only
            // child, remove the parent stroke.
            if (parentStroke.Substrokes.Length == 1)
            {
                return(RemoveStroke(parentStroke));
            }
            else
            {
                return(parentStroke.RemoveSubstroke(substroke));
            }
        }