Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Framework / MS / Internal / Ink / LassoHelper.cs / 1 / LassoHelper.cs
//------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------- using System; using System.Windows; using System.Windows.Media; using System.Windows.Ink; using System.Collections; using System.Collections.Generic; using System.Windows.Documents; namespace MS.Internal.Ink { #region LassoHelper ////// An internal helper class to draw lasso as a sequence of dots /// closed with a rubber line. LassoSelectionBehavior creates an object of /// this class to render a single lasso, so, for simplicity, /// LassoHelper objects are indended for one-time use only. /// internal class LassoHelper { #region Fields // Visuals, geometry builders and drawing stuff DrawingVisual _containerVisual = null; Brush _brush = null; Pen _pen = null; //Pen _linePen = null; // bool _isActivated = false; Point _firstLassoPoint; Point _lastLassoPoint; int _count = 0; // Entire lasso. Collected to hit test InkCanvas' subelements after stylus up. List_lasso = null; Rect _boundingBox; // NTRAID#T2-00000-2003/07/14-vsmirnov - some of these are probably not in [....] // with the spec (which is not available at this moment), and also might // need to be different for the high contrast mode. public const double MinDistanceSquared = 49.0; const double DotRadius = 2.5; const double DotCircumferenceThickness = 0.5; const double ConnectLineThickness = 0.75; const double ConnectLineOpacity = 0.75; static readonly Color DotColor = Colors.Orange; //FromArgb(1, 0.89f, 0.3607f, 0.1843f); static readonly Color DotCircumferenceColor = Colors.White; #endregion #region Public API /// /// Read-only access to the container visual for dynamic drawing a lasso /// public Visual Visual { get { EnsureVisual(); return _containerVisual; } } ///TBS public Point[] AddPoints(Listpoints) { if (null == points) throw new ArgumentNullException("points"); // Lazy initialization. EnsureReady(); List justAdded = new List (); int count = points.Count; for ( int i = 0; i < count ; i++ ) { Point point = points[i]; if (0 == _count) { AddLassoPoint(point); justAdded.Add(point); _lasso.Add(point); _boundingBox.Union(point); _firstLassoPoint = point; _lastLassoPoint = point; _count++; } else { Vector last2next = point - _lastLassoPoint; double distanceSquared = last2next.LengthSquared; // Avoid using Sqrt when the distance is equal to the step. if (DoubleUtil.AreClose(MinDistanceSquared, distanceSquared)) { AddLassoPoint(point); justAdded.Add(point); _lasso.Add(point); _boundingBox.Union(point); _lastLassoPoint = point; _count++; } else if (MinDistanceSquared < distanceSquared) { double step = Math.Sqrt(MinDistanceSquared / distanceSquared); Point last = _lastLassoPoint; for (double findex = step; findex < 1.0f; findex += step) { Point lassoPoint = last + (last2next * findex); AddLassoPoint(lassoPoint); justAdded.Add(lassoPoint); _lasso.Add(lassoPoint); _boundingBox.Union(lassoPoint); _lastLassoPoint = lassoPoint; _count++; } } } } // still working on perf here. // Draw a line between the last point and the first one. //if (_count > 1) //{ // DrawingContext dc = _containerVisual.RenderOpen(); // dc.DrawLine(_linePen, _firstLassoPoint, _lastLassoPoint); // dc.Close(); //} return justAdded.ToArray(); } ///// ///// Draws a single lasso dot with the center at the given point. ///// private void AddLassoPoint(Point lassoPoint) { DrawingVisual dv = new DrawingVisual(); DrawingContext dc = null; try { dc = dv.RenderOpen(); dc.DrawEllipse(_brush, _pen, lassoPoint, DotRadius, DotRadius); } finally { if (dc != null) { dc.Close(); } } // Add the new visual to the container. _containerVisual.Children.Add(dv); } #endregion #region ArePointsInLasso ///Copy-pasted Platform's Lasso.Contains(...) public bool ArePointsInLasso(Point[] points, int percentIntersect) { System.Diagnostics.Debug.Assert(null != points); System.Diagnostics.Debug.Assert((0 <= percentIntersect) && (100 >= percentIntersect)); // Find out how many of the points need to be inside the lasso to satisfy the percentIntersect. int marginCount = (points.Length * percentIntersect) / 100; if ((0 == marginCount) || (50 <= ((points.Length * percentIntersect) % 100))) { marginCount++; } // Check if any point on the stroke is within the lasso or not. // This is done by checking all segments on the left side of the point. // If the no of such segments is odd then the point is within the lasso otherwise not. int countPointsInLasso = 0; foreach (Point point in points) { if (true == Contains(point)) { countPointsInLasso++; if (countPointsInLasso == marginCount) break; } } return (countPointsInLasso == marginCount); } ///TBS private bool Contains(Point point) { if (false == _boundingBox.Contains(point)) { return false; } bool isHigher = false; int last = _lasso.Count; while (--last >= 0) { if (false == DoubleUtil.AreClose(_lasso[last].Y, point.Y)) { isHigher = point.Y < _lasso[last].Y; break; } } bool isInside = false, isOnClosingSegment = false; Point prevLassoPoint = _lasso[_lasso.Count - 1]; for (int i = 0; i < _lasso.Count; i++) { Point lassoPoint = _lasso[i]; if (DoubleUtil.AreClose(lassoPoint.Y, point.Y)) { if (DoubleUtil.AreClose(lassoPoint.X, point.X)) { isInside = true; break; } if ((0 != i) && DoubleUtil.AreClose(prevLassoPoint.Y, point.Y) && DoubleUtil.GreaterThanOrClose(point.X, Math.Min(prevLassoPoint.X, lassoPoint.X)) && DoubleUtil.LessThanOrClose(point.X, Math.Max(prevLassoPoint.X, lassoPoint.X))) { isInside = true; break; } } else if (isHigher != (point.Y < lassoPoint.Y)) { isHigher = !isHigher; if (DoubleUtil.GreaterThanOrClose(point.X, Math.Max(prevLassoPoint.X, lassoPoint.X))) { // there certainly is an intersection on the left isInside = !isInside; // The closing segment is the only exclusive one. Special case it. if ((0 == i) && DoubleUtil.AreClose(point.X, Math.Max(prevLassoPoint.X, lassoPoint.X))) { isOnClosingSegment = true; } } else if (DoubleUtil.GreaterThanOrClose(point.X, Math.Min(prevLassoPoint.X, lassoPoint.X))) { // The X of the point lies within the x ranges for the segment. // Calculate the x value of the point where the segment intersects with the line. Vector lassoSegment = lassoPoint - prevLassoPoint; double x = prevLassoPoint.X + (lassoSegment.X / lassoSegment.Y) * (point.Y - prevLassoPoint.Y); if (DoubleUtil.GreaterThanOrClose(point.X, x)) { isInside = !isInside; if ((0 == i) && DoubleUtil.AreClose(point.X, x)) { isOnClosingSegment = true; } } } } prevLassoPoint = lassoPoint; } return isInside ? !isOnClosingSegment : false; } #endregion #region Implementation helpers ///Creates the container visual when needed. private void EnsureVisual() { if (null == _containerVisual) { _containerVisual = new DrawingVisual(); } } ////// Creates and initializes objects required for drawing /// private void EnsureReady() { if (false == _isActivated) { _isActivated = true; EnsureVisual(); _brush = new SolidColorBrush(DotColor); _brush.Freeze(); //_linePen = new Pen(new SolidColorBrush(Colors.DarkGray), ConnectLineThickness); //_linePen.Brush.Opacity = ConnectLineOpacity; //_linePen.LineJoin = PenLineJoin.Round; _pen = new Pen(new SolidColorBrush(DotCircumferenceColor), DotCircumferenceThickness); _pen.LineJoin = PenLineJoin.Round; _pen.Freeze(); _lasso = new List(100); _boundingBox = Rect.Empty; _count = 0; } } #endregion } #endregion } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------- using System; using System.Windows; using System.Windows.Media; using System.Windows.Ink; using System.Collections; using System.Collections.Generic; using System.Windows.Documents; namespace MS.Internal.Ink { #region LassoHelper ////// An internal helper class to draw lasso as a sequence of dots /// closed with a rubber line. LassoSelectionBehavior creates an object of /// this class to render a single lasso, so, for simplicity, /// LassoHelper objects are indended for one-time use only. /// internal class LassoHelper { #region Fields // Visuals, geometry builders and drawing stuff DrawingVisual _containerVisual = null; Brush _brush = null; Pen _pen = null; //Pen _linePen = null; // bool _isActivated = false; Point _firstLassoPoint; Point _lastLassoPoint; int _count = 0; // Entire lasso. Collected to hit test InkCanvas' subelements after stylus up. List_lasso = null; Rect _boundingBox; // NTRAID#T2-00000-2003/07/14-vsmirnov - some of these are probably not in [....] // with the spec (which is not available at this moment), and also might // need to be different for the high contrast mode. public const double MinDistanceSquared = 49.0; const double DotRadius = 2.5; const double DotCircumferenceThickness = 0.5; const double ConnectLineThickness = 0.75; const double ConnectLineOpacity = 0.75; static readonly Color DotColor = Colors.Orange; //FromArgb(1, 0.89f, 0.3607f, 0.1843f); static readonly Color DotCircumferenceColor = Colors.White; #endregion #region Public API /// /// Read-only access to the container visual for dynamic drawing a lasso /// public Visual Visual { get { EnsureVisual(); return _containerVisual; } } ///TBS public Point[] AddPoints(Listpoints) { if (null == points) throw new ArgumentNullException("points"); // Lazy initialization. EnsureReady(); List justAdded = new List (); int count = points.Count; for ( int i = 0; i < count ; i++ ) { Point point = points[i]; if (0 == _count) { AddLassoPoint(point); justAdded.Add(point); _lasso.Add(point); _boundingBox.Union(point); _firstLassoPoint = point; _lastLassoPoint = point; _count++; } else { Vector last2next = point - _lastLassoPoint; double distanceSquared = last2next.LengthSquared; // Avoid using Sqrt when the distance is equal to the step. if (DoubleUtil.AreClose(MinDistanceSquared, distanceSquared)) { AddLassoPoint(point); justAdded.Add(point); _lasso.Add(point); _boundingBox.Union(point); _lastLassoPoint = point; _count++; } else if (MinDistanceSquared < distanceSquared) { double step = Math.Sqrt(MinDistanceSquared / distanceSquared); Point last = _lastLassoPoint; for (double findex = step; findex < 1.0f; findex += step) { Point lassoPoint = last + (last2next * findex); AddLassoPoint(lassoPoint); justAdded.Add(lassoPoint); _lasso.Add(lassoPoint); _boundingBox.Union(lassoPoint); _lastLassoPoint = lassoPoint; _count++; } } } } // still working on perf here. // Draw a line between the last point and the first one. //if (_count > 1) //{ // DrawingContext dc = _containerVisual.RenderOpen(); // dc.DrawLine(_linePen, _firstLassoPoint, _lastLassoPoint); // dc.Close(); //} return justAdded.ToArray(); } ///// ///// Draws a single lasso dot with the center at the given point. ///// private void AddLassoPoint(Point lassoPoint) { DrawingVisual dv = new DrawingVisual(); DrawingContext dc = null; try { dc = dv.RenderOpen(); dc.DrawEllipse(_brush, _pen, lassoPoint, DotRadius, DotRadius); } finally { if (dc != null) { dc.Close(); } } // Add the new visual to the container. _containerVisual.Children.Add(dv); } #endregion #region ArePointsInLasso ///Copy-pasted Platform's Lasso.Contains(...) public bool ArePointsInLasso(Point[] points, int percentIntersect) { System.Diagnostics.Debug.Assert(null != points); System.Diagnostics.Debug.Assert((0 <= percentIntersect) && (100 >= percentIntersect)); // Find out how many of the points need to be inside the lasso to satisfy the percentIntersect. int marginCount = (points.Length * percentIntersect) / 100; if ((0 == marginCount) || (50 <= ((points.Length * percentIntersect) % 100))) { marginCount++; } // Check if any point on the stroke is within the lasso or not. // This is done by checking all segments on the left side of the point. // If the no of such segments is odd then the point is within the lasso otherwise not. int countPointsInLasso = 0; foreach (Point point in points) { if (true == Contains(point)) { countPointsInLasso++; if (countPointsInLasso == marginCount) break; } } return (countPointsInLasso == marginCount); } ///TBS private bool Contains(Point point) { if (false == _boundingBox.Contains(point)) { return false; } bool isHigher = false; int last = _lasso.Count; while (--last >= 0) { if (false == DoubleUtil.AreClose(_lasso[last].Y, point.Y)) { isHigher = point.Y < _lasso[last].Y; break; } } bool isInside = false, isOnClosingSegment = false; Point prevLassoPoint = _lasso[_lasso.Count - 1]; for (int i = 0; i < _lasso.Count; i++) { Point lassoPoint = _lasso[i]; if (DoubleUtil.AreClose(lassoPoint.Y, point.Y)) { if (DoubleUtil.AreClose(lassoPoint.X, point.X)) { isInside = true; break; } if ((0 != i) && DoubleUtil.AreClose(prevLassoPoint.Y, point.Y) && DoubleUtil.GreaterThanOrClose(point.X, Math.Min(prevLassoPoint.X, lassoPoint.X)) && DoubleUtil.LessThanOrClose(point.X, Math.Max(prevLassoPoint.X, lassoPoint.X))) { isInside = true; break; } } else if (isHigher != (point.Y < lassoPoint.Y)) { isHigher = !isHigher; if (DoubleUtil.GreaterThanOrClose(point.X, Math.Max(prevLassoPoint.X, lassoPoint.X))) { // there certainly is an intersection on the left isInside = !isInside; // The closing segment is the only exclusive one. Special case it. if ((0 == i) && DoubleUtil.AreClose(point.X, Math.Max(prevLassoPoint.X, lassoPoint.X))) { isOnClosingSegment = true; } } else if (DoubleUtil.GreaterThanOrClose(point.X, Math.Min(prevLassoPoint.X, lassoPoint.X))) { // The X of the point lies within the x ranges for the segment. // Calculate the x value of the point where the segment intersects with the line. Vector lassoSegment = lassoPoint - prevLassoPoint; double x = prevLassoPoint.X + (lassoSegment.X / lassoSegment.Y) * (point.Y - prevLassoPoint.Y); if (DoubleUtil.GreaterThanOrClose(point.X, x)) { isInside = !isInside; if ((0 == i) && DoubleUtil.AreClose(point.X, x)) { isOnClosingSegment = true; } } } } prevLassoPoint = lassoPoint; } return isInside ? !isOnClosingSegment : false; } #endregion #region Implementation helpers ///Creates the container visual when needed. private void EnsureVisual() { if (null == _containerVisual) { _containerVisual = new DrawingVisual(); } } ////// Creates and initializes objects required for drawing /// private void EnsureReady() { if (false == _isActivated) { _isActivated = true; EnsureVisual(); _brush = new SolidColorBrush(DotColor); _brush.Freeze(); //_linePen = new Pen(new SolidColorBrush(Colors.DarkGray), ConnectLineThickness); //_linePen.Brush.Opacity = ConnectLineOpacity; //_linePen.LineJoin = PenLineJoin.Round; _pen = new Pen(new SolidColorBrush(DotCircumferenceColor), DotCircumferenceThickness); _pen.LineJoin = PenLineJoin.Round; _pen.Freeze(); _lasso = new List(100); _boundingBox = Rect.Empty; _count = 0; } } #endregion } #endregion } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- CodeArrayIndexerExpression.cs
- CustomServiceCredentials.cs
- TdsRecordBufferSetter.cs
- RemoveStoryboard.cs
- QueryExpr.cs
- ProbeMatchesMessage11.cs
- HtmlTernaryTree.cs
- ChannelManager.cs
- TextDecorationUnitValidation.cs
- ChangeConflicts.cs
- LexicalChunk.cs
- DBNull.cs
- DelegatedStream.cs
- IUnknownConstantAttribute.cs
- DataGridViewRowDividerDoubleClickEventArgs.cs
- TextFormatterContext.cs
- BindingGroup.cs
- WinEventTracker.cs
- XmlAttributeAttribute.cs
- DesignerCategoryAttribute.cs
- IsolatedStorageSecurityState.cs
- Publisher.cs
- XmlCountingReader.cs
- StringInfo.cs
- GlobalEventManager.cs
- QueryOptionExpression.cs
- ResourceSet.cs
- ILGenerator.cs
- DbgCompiler.cs
- FixedSOMElement.cs
- GridViewHeaderRowPresenterAutomationPeer.cs
- TdsValueSetter.cs
- WaveHeader.cs
- AssemblyAttributes.cs
- WinFormsSpinner.cs
- RelatedCurrencyManager.cs
- GridViewRow.cs
- PositiveTimeSpanValidator.cs
- ReachPageContentCollectionSerializer.cs
- DropShadowBitmapEffect.cs
- ReadOnlyHierarchicalDataSourceView.cs
- LongSumAggregationOperator.cs
- StringUtil.cs
- InternalTransaction.cs
- ChameleonKey.cs
- SlipBehavior.cs
- AppDomainManager.cs
- TraceContext.cs
- LabelLiteral.cs
- DataGridViewSelectedCellCollection.cs
- SectionInput.cs
- Zone.cs
- CommonRemoteMemoryBlock.cs
- HashJoinQueryOperatorEnumerator.cs
- EditorPart.cs
- ChangeBlockUndoRecord.cs
- XmlObjectSerializerWriteContextComplexJson.cs
- _ConnectStream.cs
- SHA512.cs
- ReflectEventDescriptor.cs
- Style.cs
- DetailsViewUpdateEventArgs.cs
- _SSPISessionCache.cs
- BindingExpression.cs
- ReadOnlyHierarchicalDataSourceView.cs
- XmlDataSource.cs
- SkipStoryboardToFill.cs
- ActivationProxy.cs
- FileDialogCustomPlaces.cs
- ApplicationSecurityInfo.cs
- SafeRegistryHandle.cs
- HtmlElement.cs
- SmtpClient.cs
- CommandConverter.cs
- DebugView.cs
- VisualStyleElement.cs
- SubMenuStyleCollection.cs
- UmAlQuraCalendar.cs
- PersistenceTypeAttribute.cs
- CacheMode.cs
- ExpressionConverter.cs
- AnimatedTypeHelpers.cs
- StrongNamePublicKeyBlob.cs
- Variable.cs
- HyperlinkAutomationPeer.cs
- DataGridViewAutoSizeColumnModeEventArgs.cs
- CheckBoxList.cs
- LocalBuilder.cs
- MessageSmuggler.cs
- StateItem.cs
- SrgsSemanticInterpretationTag.cs
- Rect3D.cs
- ComAdminInterfaces.cs
- Thumb.cs
- BitmapEffectInput.cs
- DataGridTextBox.cs
- SettingsContext.cs
- QueryModel.cs
- EmptyEnumerator.cs
- DependentList.cs