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(List points)
{
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
- ParameterCollectionEditor.cs
- RegisterResponseInfo.cs
- CompositeControl.cs
- HealthMonitoringSectionHelper.cs
- SiteMapPath.cs
- hresults.cs
- GrabHandleGlyph.cs
- TaskFactory.cs
- SelectionRangeConverter.cs
- XmlQualifiedName.cs
- OdbcTransaction.cs
- SqlMetaData.cs
- PnrpPermission.cs
- CreateUserWizard.cs
- DataGridAddNewRow.cs
- UnsafeNativeMethods.cs
- DataBindingExpressionBuilder.cs
- ImageAutomationPeer.cs
- ListControlBoundActionList.cs
- ToolStripItemGlyph.cs
- ModelUtilities.cs
- Update.cs
- BeginStoryboard.cs
- ControlPropertyNameConverter.cs
- InternalCache.cs
- SafeRightsManagementQueryHandle.cs
- InstanceStore.cs
- FrameworkContentElement.cs
- ResizeBehavior.cs
- InvalidPipelineStoreException.cs
- ConnectionManagementElementCollection.cs
- DependencyPropertyHelper.cs
- RtfNavigator.cs
- webproxy.cs
- XmlSchemaDatatype.cs
- ScriptDescriptor.cs
- SmiEventSink.cs
- DataGridViewRowsRemovedEventArgs.cs
- ImageField.cs
- SqlClientPermission.cs
- NavigationHelper.cs
- PropertyOrder.cs
- HttpFileCollection.cs
- WCFBuildProvider.cs
- RealizationContext.cs
- ItemCheckEvent.cs
- ObjectContextServiceProvider.cs
- StringComparer.cs
- ImageAnimator.cs
- DropDownButton.cs
- SimplePropertyEntry.cs
- ToolStripDropDownItem.cs
- MethodAccessException.cs
- TextEndOfLine.cs
- CqlParser.cs
- LocalizedNameDescriptionPair.cs
- ConstrainedDataObject.cs
- AttachedPropertyMethodSelector.cs
- AttributeUsageAttribute.cs
- GestureRecognizer.cs
- ScrollBarRenderer.cs
- SqlCacheDependencyDatabase.cs
- KnownBoxes.cs
- Stylesheet.cs
- ThreadExceptionDialog.cs
- TypeSystemHelpers.cs
- MemberDescriptor.cs
- StylusPointPropertyUnit.cs
- ExecutionEngineException.cs
- PageBuildProvider.cs
- ZoomPercentageConverter.cs
- XmlChildNodes.cs
- InlineCollection.cs
- ZipIOExtraFieldZip64Element.cs
- MdImport.cs
- WebFaultClientMessageInspector.cs
- DataGridView.cs
- WeakReadOnlyCollection.cs
- LastQueryOperator.cs
- EmptyElement.cs
- IsolatedStorageFile.cs
- PeerCollaborationPermission.cs
- LocalizabilityAttribute.cs
- WebControlAdapter.cs
- TraceSource.cs
- FilterElement.cs
- CacheSection.cs
- SqlCommandSet.cs
- LoadGrammarCompletedEventArgs.cs
- TextParaLineResult.cs
- ThreadNeutralSemaphore.cs
- XmlAttributeCollection.cs
- DetailsViewPagerRow.cs
- InheritanceContextChangedEventManager.cs
- ImageMap.cs
- TheQuery.cs
- log.cs
- TypeUsage.cs
- RequestCacheManager.cs
- ItemMap.cs