/// <summary> /// Checks if a node is inside a certain box. Considers HitTestRadius. /// </summary> /// <returns>True if the box intersects the elliptical shape of the node. Also true if box lies completely inside node.</returns> protected override bool IsInBox(IInputModeContext context, RectD rectangle, INode node) { // early exit if not even the bounds are contained in the box if (!base.IsInBox(context, rectangle, node)) { return(false); } double eps = context.HitTestRadius; var outline = GetOutline(node); if (outline == null) { return(rectangle.Contains(node.Layout.ToRectD().TopLeft) && rectangle.Contains(node.Layout.ToRectD().BottomRight)); } if (outline.Intersects(rectangle, eps)) { return(true); } if (outline.PathContains(rectangle.TopLeft, eps) && outline.PathContains(rectangle.BottomRight, eps)) { return(true); } return(rectangle.Contains(node.Layout.ToRectD().TopLeft) && rectangle.Contains(node.Layout.ToRectD().BottomRight)); }
/// <summary> /// Finds the child node of the <see cref="QuadTreeNode{TValue}"/> that contains the /// specified key.</summary> /// <param name="key"> /// The key to locate. This argument must lie within <see cref="Bounds"/>.</param> /// <returns> /// The child of the <see cref="QuadTreeNode{TValue}"/> that contains <paramref /// name="key"/>, or a null reference if the child does not yet exist.</returns> /// <remarks> /// <b>FindChild</b> compares the specified <paramref name="key"/> to the <see /// cref="Center"/> point to determine the containing quadrant.</remarks> internal QuadTreeNode <TValue> FindChild(PointD key) { Debug.Assert(Bounds.Contains(key)); double relX = key.X - Center.X; double relY = key.Y - Center.Y; return(relX < 0 ? (relY < 0 ? _topLeft : _bottomLeft) : (relY < 0 ? _topRight : _bottomRight)); }
protected override bool IsHit(IInputModeContext context, PointD location, INode node) { const double cornerRadius = 7; var layout = node.Layout; // Our shape is a rounded rectangle. Hits can appear in either of the following rectangles ... var rect1 = new RectD(layout.X, layout.Y + cornerRadius, layout.Width, layout.Height - 2 * cornerRadius); var rect2 = new RectD(layout.X + cornerRadius, layout.Y, layout.Width - 2 * cornerRadius, layout.Height); if (rect1.Contains(location, context.HitTestRadius) || rect2.Contains(location, context.HitTestRadius)) { return(true); } // ... or in circle arcs around the corners var p1 = new PointD(layout.X + cornerRadius, layout.Y + cornerRadius); var p2 = new PointD(layout.X + layout.Width - cornerRadius, layout.Y + cornerRadius); var p3 = new PointD(layout.X + cornerRadius, layout.Y + layout.Height - cornerRadius); var p4 = new PointD(layout.X + layout.Width - cornerRadius, layout.Y + layout.Height - cornerRadius); if (location.DistanceTo(p1) < cornerRadius + context.HitTestRadius || location.DistanceTo(p2) < cornerRadius + context.HitTestRadius || location.DistanceTo(p3) < cornerRadius + context.HitTestRadius || location.DistanceTo(p4) < cornerRadius + context.HitTestRadius) { return(true); } return(false); }
private static void RandomPointsComparer(IPointDComparer comparer) { RectD bounds = new RectD(-100, -100, 200, 200); PointD[] points = GeoAlgorithms.RandomPoints(100, bounds, comparer, 2); for (int i = 0; i < points.Length; i++) { PointD p = points[i]; Assert.IsTrue(bounds.Contains(p)); if (i > 0) { Assert.AreEqual(+1, comparer.Compare(p, points[i - 1])); } if (i < points.Length - 1) { Assert.AreEqual(-1, comparer.Compare(p, points[i + 1])); } for (int j = 0; j < points.Length; j++) { if (i == j) { continue; } double distance = p.Subtract(points[j]).LengthSquared; Assert.GreaterOrEqual(distance, 4); } } }
/// <summary> /// Converts all <see cref="DelaunayEdges"/> to a planar <see cref="Subdivision"/>, using /// the specified clipping bounds.</summary> /// <param name="bounds"> /// A <see cref="RectD"/> that indicates the clipping bounds for all <see /// cref="DelaunayEdges"/>.</param> /// <param name="addRegions"> /// <c>true</c> to add all <see cref="VoronoiRegions"/> with the corresponding <see /// cref="GeneratorSites"/> to the <see cref="Subdivision.VertexRegions"/> collection of the /// new <see cref="Subdivision"/>; otherwise, <c>false</c>.</param> /// <returns> /// A new <see cref="Subdivision"/> whose <see cref="Subdivision.Edges"/> correspond to the /// <see cref="DelaunayEdges"/> of the <see cref="VoronoiResults"/>.</returns> /// <remarks><para> /// The specified <paramref name="bounds"/> determine the subset of <see /// cref="GeneratorSites"/> and <see cref="DelaunayEdges"/> that is stored in the new <see /// cref="Subdivision"/>, as described in <see cref="ClipDelaunayEdges"/>. /// </para><para> /// If <paramref name="addRegions"/> is <c>true</c>, the polygons added to the <see /// cref="Subdivision.VertexRegions"/> collection are also clipped the specified <paramref /// name="bounds"/>.</para></remarks> public Subdivision ToDelaunySubdivision(RectD bounds, bool addRegions = false) { LineD[] edges = ClipDelaunayEdges(bounds); Subdivision division = Subdivision.FromLines(edges); if (addRegions) { for (int i = 0; i < GeneratorSites.Length; i++) { PointD site = GeneratorSites[i]; if (!bounds.Contains(site)) { continue; } PointD[] region; if (bounds.Intersect(VoronoiRegions[i], out region)) { division.VertexRegions.Add(site, region); } } } return(division); }
public void RandomPoints() { RectD bounds = new RectD(-100, -100, 200, 200); PointD[] points = GeoAlgorithms.RandomPoints(100, bounds); foreach (PointD p in points) { Assert.IsTrue(bounds.Contains(p)); } }
/// <summary> /// Clips the edge list for the Delaunay triangulation to the specified bounds.</summary> /// <param name="bounds"> /// A <see cref="RectD"/> that indicates the clipping bounds for all <see /// cref="DelaunayEdges"/>.</param> /// <returns> /// An <see cref="Array"/> containing all <see cref="DelaunayEdges"/> which intersect the /// specified <paramref name="bounds"/>, as defined below.</returns> /// <remarks><para> /// <b>ClipDelaunayEdges</b> returns all <see cref="DelaunayEdges"/> whose corresponding /// <see cref="VoronoiEdges"/> element fulfils two conditions: /// </para><list type="bullet"><item> /// <see cref="VoronoiEdge.Site1"/> and <see cref="VoronoiEdge.Site2"/> both fall within the /// specified <paramref name="bounds"/>. /// </item><item> /// The line segment indicated by <see cref="VoronoiEdge.Vertex1"/> and <see /// cref="VoronoiEdge.Vertex2"/> intersects the specified <paramref name="bounds"/>. /// </item></list><para> /// In other words, <b>ClipDelaunayEdges</b> selects those <see cref="DelaunayEdges"/> that /// fall entirely within <paramref name="bounds"/>, and which connect two <see /// cref="VoronoiRegions"/> that share a common border within <paramref name="bounds"/>. /// </para></remarks> public LineD[] ClipDelaunayEdges(RectD bounds) { List <LineD> delaunayEdges = new List <LineD>(VoronoiEdges.Length); foreach (VoronoiEdge edge in VoronoiEdges) { PointD s1 = GeneratorSites[edge.Site1]; PointD s2 = GeneratorSites[edge.Site2]; if (bounds.Contains(s1) && bounds.Contains(s2)) { PointD v1 = VoronoiVertices[edge.Vertex1]; PointD v2 = VoronoiVertices[edge.Vertex2]; if (bounds.IntersectsWith(new LineD(v1, v2))) { delaunayEdges.Add(new LineD(s1, s2)); } } } return(delaunayEdges.ToArray()); }
public override void ChildrenHitTestCore(HitChain hitChain) { RectD bound = RenderVx.GetBounds(); if (bound.Contains(hitChain.TestPoint.x, hitChain.TestPoint.y)) { //check exact hit or the vxs part if (HitTestOnSubPart(RenderVx, hitChain.TextPointX, hitChain.TextPointY)) { hitChain.AddHitObject(this); } } base.ChildrenHitTestCore(hitChain); }
/// <summary> /// Gets the layer at the given location. /// </summary> /// <param name="location">The location.</param> /// <returns>A positive value if a specific layer is hit, a negative one to indicate that a new layer should /// be inserted before layer -(value + 1) - int.MaxValue if no layer has been hit.</returns> public int GetLayer(PointD location) { // global bounds var nbounds = new RectD(bounds.X, bounds.Y - LayerInsets, bounds.Width, bounds.Height + LayerInsets * 2); if (location.Y < bounds.Y) { // before the first layer return(-1); } if (location.Y > bounds.Bottom) { // after the last layer return(-((dividers.Count + 2) + 1)); } // nothing found, if (!nbounds.Contains(location)) { return(Int32.MaxValue); } // now search the layer double top = bounds.Top; int layerCount = 0; foreach (var divider in dividers) { var layerBounds = new RectD(bounds.X, top, bounds.Width, divider - top); if (layerBounds.Contains(location)) { return(GetLayerIndex(location, layerBounds, layerCount)); } layerCount++; top = divider; } { var layerBounds = new RectD(bounds.X, top, bounds.Width, bounds.Bottom - top); if (layerBounds.Contains(location)) { return(GetLayerIndex(location, layerBounds, layerCount)); } } // should not really happen... return(Int32.MaxValue); }
public override void OnRender() { var item = Target as ItemDataControl; RefreshResources(item); if (imageTex == null) { return; } var rect = new RectD(new Vector2d(-0.5f * imageTex.width, -imageTex.height), new Vector2d(imageTex.width, imageTex.height)); var adaptedRect = ComponentBasedEditor.Generic.ToRelative(rect.ToPoints()).ToRectD().ToRect(); GUI.DrawTexture(adaptedRect, rect.Contains(Event.current.mousePosition.ToVector2d()) && imageOverTex ? imageOverTex : imageTex, ScaleMode.ScaleToFit); }
protected override bool IsHit(IInputModeContext context, PointD location, INode node) { if (sns.Renderer.GetHitTestable(node, sns).IsHit(context, location)) { return(true); } var layout = node.Layout.ToRectD(); if (ShowTopMessage) { var cx = layout.GetCenter().X; var topBoxSize = BpmnConstants.MessageSize; var messageRect = new RectD(new PointD(cx - topBoxSize.Width / 2, layout.Y - MessageDistance - topBoxSize.Height), topBoxSize); if (messageRect.Contains(location, context.HitTestRadius)) { return(true); } if (Math.Abs(location.X - cx) < context.HitTestRadius && layout.Y - MessageDistance - context.HitTestRadius < location.Y && location.Y < layout.Y + context.HitTestRadius) { return(true); } } if (ShowBottomMessage) { var bottomBoxSize = BpmnConstants.MessageSize; var cx = layout.GetCenter().X; var messageRect = new RectD(new PointD(cx - bottomBoxSize.Width / 2, layout.GetMaxY() + MessageDistance), bottomBoxSize); if (messageRect.Contains(location, context.HitTestRadius)) { return(true); } if (Math.Abs(location.X - cx) < context.HitTestRadius && layout.GetMaxY() - context.HitTestRadius < location.Y && location.Y < layout.GetMaxY() + MessageDistance + context.HitTestRadius) { return(true); } } return(false); }
// the type of button which has been hit private HitInfo GetHitInfo(PointD location) { RectD layout = node.Layout.ToRectD(); var classInfo = node.Tag as ClassInfo; PointD buttonLocation = layout.TopRight + new PointD(-ImageSize - 5, 5); RectD buttonRect = new RectD(buttonLocation, new SizeD(ImageSize, ImageSize)); if (buttonRect.Contains(location)) { return(HitInfo.ToggleAllDetails); } double height = umlStyle.GetHeaderSize(classInfo).Height; if (IsButtonHit(location, height)) { return(HitInfo.ToggleFieldDetails); } if (classInfo != null) { height += umlStyle.GetSectionSize(classInfo.Fields, "Fields").Height; } if (IsButtonHit(location, height)) { return(HitInfo.TogglePropertyDetails); } if (classInfo != null) { height += umlStyle.GetSectionSize(classInfo.Properties, "Properties").Height; } if (IsButtonHit(location, height)) { return(HitInfo.ToggleMethodDetails); } return(HitInfo.None); }
/// <summary> /// Finds all key-and-value pairs within the specified key range that are stored in the <see /// cref="QuadTreeNode{TValue}"/> or its child nodes.</summary> /// <param name="range"> /// A <see cref="RectD"/> indicating the key range to search. This argument must intersect /// with <see cref="Bounds"/>, and it must be a square if <paramref name="useCircle"/> is /// <c>true</c>.</param> /// <param name="useCircle"> /// <c>true</c> to search only the circle inscribed within <paramref name="range"/>; /// <c>false</c> to search the entire <paramref name="range"/>.</param> /// <param name="output"> /// A <see cref="Dictionary{PointD, TValue}"/> to which any elements are added whose key /// lies within the specified <paramref name="range"/>.</param> internal void FindRange(ref RectD range, bool useCircle, Dictionary <PointD, TValue> output) { Debug.Assert(Bounds.IntersectsWith(range)); if (_data != null) { if (useCircle) { double radius = range.Width / 2; double x = range.X + radius, y = range.Y + radius; foreach (var pair in _data) { if (range.Contains(pair.Key)) { double dx = pair.Key.X - x, dy = pair.Key.Y - y; if (dx * dx + dy * dy <= radius * radius) { output.Add(pair.Key, pair.Value); } } } } else { foreach (var pair in _data) { if (range.Contains(pair.Key)) { output.Add(pair.Key, pair.Value); } } } return; } bool topRange = (range.Top < Center.Y); bool bottomRange = (range.Bottom >= Center.Y); bool leftRange = (range.Left < Center.X); bool rightRange = (range.Right >= Center.X); if (topRange) { if (leftRange && _topLeft != null) { _topLeft.FindRange(ref range, useCircle, output); } if (rightRange && _topRight != null) { _topRight.FindRange(ref range, useCircle, output); } } if (bottomRange) { if (leftRange && _bottomLeft != null) { _bottomLeft.FindRange(ref range, useCircle, output); } if (rightRange && _bottomRight != null) { _bottomRight.FindRange(ref range, useCircle, output); } } }
public bool IsInBox(IInputModeContext context, RectD rectangle) { return(rectangle.Contains(this.rectangle.GetTopLeft()) && rectangle.Contains(this.rectangle.GetBottomRight())); }
public void ContainsPoint() { Assert.IsTrue(rectD.Contains(rectD.TopLeft)); Assert.IsTrue(rectD.Contains(rectD.TopRight)); Assert.IsTrue(rectD.Contains(rectD.BottomLeft)); Assert.IsTrue(rectD.Contains(rectD.BottomRight)); Assert.IsTrue(rectD.Contains(3, 4)); Assert.IsFalse(rectD.Contains(0, 1)); Assert.IsTrue(rectF.Contains(rectF.TopLeft)); Assert.IsTrue(rectF.Contains(rectF.TopRight)); Assert.IsTrue(rectF.Contains(rectF.BottomLeft)); Assert.IsTrue(rectF.Contains(rectF.BottomRight)); Assert.IsTrue(rectF.Contains(3, 4)); Assert.IsFalse(rectF.Contains(0, 1)); Assert.IsTrue(rectI.Contains(rectI.TopLeft)); Assert.IsFalse(rectI.Contains(rectI.TopRight)); Assert.IsFalse(rectI.Contains(rectI.BottomLeft)); Assert.IsFalse(rectI.Contains(rectI.BottomRight)); Assert.IsTrue(rectI.Contains(3, 4)); Assert.IsFalse(rectI.Contains(0, 1)); }