Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / 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; // 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
- Atom10FormatterFactory.cs
- KeyPullup.cs
- DataGridViewAccessibleObject.cs
- ProfileServiceManager.cs
- InstanceOwner.cs
- MsmqInputChannel.cs
- BindingNavigator.cs
- DefaultObjectSerializer.cs
- PipeStream.cs
- ExclusiveCanonicalizationTransform.cs
- XPathNodePointer.cs
- Location.cs
- CodeEventReferenceExpression.cs
- Regex.cs
- StringAttributeCollection.cs
- CultureInfoConverter.cs
- serverconfig.cs
- DESCryptoServiceProvider.cs
- GroupDescription.cs
- HasCopySemanticsAttribute.cs
- PagesSection.cs
- bidPrivateBase.cs
- SqlDataSource.cs
- RangeContentEnumerator.cs
- HostedNamedPipeTransportManager.cs
- PropertiesTab.cs
- HttpWebResponse.cs
- DoubleAnimation.cs
- BridgeDataReader.cs
- FullTextState.cs
- PropertyDescriptorCollection.cs
- ActivityCodeDomSerializer.cs
- ProxyRpc.cs
- Menu.cs
- IOException.cs
- DataGridViewCheckBoxCell.cs
- Config.cs
- ListMarkerSourceInfo.cs
- OperationResponse.cs
- FontCollection.cs
- PopupEventArgs.cs
- RootBuilder.cs
- ScaleTransform3D.cs
- SynchronizationFilter.cs
- LayoutEvent.cs
- TextElementCollectionHelper.cs
- CollectionTraceRecord.cs
- CodeCastExpression.cs
- UpDownBase.cs
- DeclarativeCatalogPart.cs
- MulticastDelegate.cs
- PropertyCondition.cs
- SqlRowUpdatedEvent.cs
- Models.cs
- RequestValidator.cs
- SafeFindHandle.cs
- OleDbReferenceCollection.cs
- IisTraceWebEventProvider.cs
- XpsFilter.cs
- ContentValidator.cs
- WrappedReader.cs
- HandlerBase.cs
- UserPreferenceChangingEventArgs.cs
- QueryContinueDragEventArgs.cs
- RegexGroup.cs
- PerformanceCounterNameAttribute.cs
- StylusEditingBehavior.cs
- ResourceContainer.cs
- Location.cs
- ObjectParameter.cs
- PopupEventArgs.cs
- EncryptedType.cs
- DialogResultConverter.cs
- SecurityRuntime.cs
- RelationHandler.cs
- HttpListenerException.cs
- PrimitiveDataContract.cs
- DataServiceConfiguration.cs
- AppSettingsSection.cs
- NamedElement.cs
- Types.cs
- TargetException.cs
- SequenceFullException.cs
- EntityDataSourceContainerNameConverter.cs
- ControlsConfig.cs
- OutputCache.cs
- SmtpReplyReader.cs
- HttpListenerRequest.cs
- TypeUsageBuilder.cs
- Configuration.cs
- Label.cs
- QilFunction.cs
- WebContentFormatHelper.cs
- SupportsPreviewControlAttribute.cs
- StreamGeometry.cs
- HttpProfileBase.cs
- ConfigurationValidatorAttribute.cs
- ProfileParameter.cs
- ZeroOpNode.cs
- ReadOnlyCollectionBase.cs