public bool CollidesWith(OrientedRectangle orientedRectangle) { LineSegment edge = Edge(0); if (edge.SeparatingAxisForOrientedRectangle(orientedRectangle)) { return false; } edge = Edge(1); if (edge.SeparatingAxisForOrientedRectangle(orientedRectangle)) { return false; } edge = orientedRectangle.Edge(0); if (edge.SeparatingAxisForOrientedRectangle(this)) { return false; } edge = orientedRectangle.Edge(1); return !edge.SeparatingAxisForOrientedRectangle(this); }
/// <summary> /// For the given parameter, calculate the actual geometry of the specified label in absolute world coordinates. /// </summary> /// <remarks>The actual position is calculated from the <see cref="MyNodeLabelModelParameter.Ratio"/> specified in the parameter as /// the counterclock-wise angle on the label owner's circumference. Note that we also rotate the label layout itself accordingly.</remarks> public IOrientedRectangle GetGeometry(ILabel label, ILabelModelParameter parameter) { var modelParameter = parameter as MyNodeLabelModelParameter; var ownerNode = label.Owner as INode; if (modelParameter != null && ownerNode != null) { //If we have a matching parameter and a node as owner, calculate the angle for the label position and the matchin rotation of the label layout box itself. var center = ownerNode.Layout.GetCenter(); var radius = Math.Max(ownerNode.Layout.Width, ownerNode.Layout.Height) * 0.5d; var ratio = modelParameter.Ratio; double angle = ratio * Math.PI * 2; double x = Math.Sin(angle); double y = Math.Cos(angle); PointD up = new PointD(-y, x); OrientedRectangle result = new OrientedRectangle(); result.SetUpVector(up); result.Size = label.PreferredSize; result.SetCenter(center + (offset + radius + label.PreferredSize.Height * 0.5d) * up); return(result); } else { return(OrientedRectangle.Empty); } }
/// <summary> /// Creates a new instance with the given layout. /// </summary> public CachingOrientedRectangle(RectD layout) { upVector = new PointD(0, -1); angle = 0.0; cachedLayout = layout; cachedOrientedRect = new OrientedRectangle(cachedLayout); }
/// <summary> /// Converts the given <see cref="OrientedRectangle"/> from the world into the view coordinate space. /// </summary> internal static void WorldToIntermediateCoordinates(ICanvasContext context, OrientedRectangle rect) { var anchor = new PointD(rect.Anchor); var anchorAndUp = anchor + rect.GetUp(); var renderContext = context as IRenderContext ?? context.Lookup(typeof(IRenderContext)) as IRenderContext; if (renderContext != null) { anchor = renderContext.WorldToIntermediateCoordinates(anchor); anchorAndUp = renderContext.WorldToIntermediateCoordinates(anchorAndUp); } else { var cc = context.Lookup(typeof(CanvasControl)) as CanvasControl; if (cc != null) { anchor = cc.WorldToIntermediateCoordinates(anchor); anchorAndUp = cc.WorldToIntermediateCoordinates(anchorAndUp); } else { // too bad - infer trivial scale matrix anchor *= context.Zoom; anchorAndUp *= context.Zoom; } } rect.SetUpVector((anchorAndUp - anchor).Normalized); rect.SetAnchor(anchor); rect.Width *= context.Zoom; rect.Height *= context.Zoom; }
/// <inheritdoc/> public IOrientedRectangle GetGeometry(ILabel label, ILabelModelParameter parameter) { OrientedRectangle rect = new OrientedRectangle(0, 0, 10, 10); ((RatioParameter)parameter).SetGeometry(this, label, rect); return(rect); }
public bool CollidesWith(OrientedRectangle orientedRectangle) { var edge = this.Edge(0); if (orientedRectangle.IsSeparatingAxis(edge)) { return(false); } edge = this.Edge(1); if (orientedRectangle.IsSeparatingAxis(edge)) { return(false); } edge = orientedRectangle.Edge(0); if (this.IsSeparatingAxis(edge)) { return(false); } edge = orientedRectangle.Edge(1); if (this.IsSeparatingAxis(edge)) { return(false); } return(true); }
public void TransformPoint() { var obb = new OrientedRectangle(Vector2.One, Vector2.Zero, MathF.PI / 2); var worldPoint = new Vector2(2, 0); var localPoint = obb.TransformPoint(worldPoint); Assert.That(localPoint, Is.Approximately(new Vector2(1, 3))); }
public void ClosestPoint() { var obb = new OrientedRectangle(Vector2.One, Vector2.One * 0.5f, MathF.PI / 2); var worldPoint = new Vector2(13, -13); var closestPoint = obb.ClosestPointWorld(worldPoint); Assert.That(closestPoint, Is.Approximately(new Vector2(1.5f, 0.5f))); }
public void RectCircle_NotCollide() { var a = new OrientedRectangle(Vector2.Zero, Vector2.One * 0.5f, MathF.PI / 4); var b = new Circle(new Vector2(1, 1), 0.5f); CollisionSolver.CalculateCollisionFeatures(in a, in b, 1, out var results); Assert.That(results.Collided, Is.EqualTo(false)); }
public RotatedNodeResizeHandle(HandlePositions position, INode node, IReshapeHandler reshapeHandler, bool symmetricResize) { this.position = position; this.node = node; this.reshapeHandler = reshapeHandler; this.symmetricResize = symmetricResize; portHandles = new List <IHandle>(); initialLayout = new OrientedRectangle(GetNodeBasedOrientedRectangle()); }
public static void Set(this OrientedRectangle mutable, IOrientedRectangle r) { mutable.AnchorX = r.AnchorX; mutable.AnchorY = r.AnchorY; mutable.Width = r.Width; mutable.Height = r.Height; mutable.UpX = r.UpX; mutable.UpY = r.UpY; }
public void TransformPointRoundTrip() { var obb = new OrientedRectangle(new Vector2(3, 5), Vector2.Zero, MathF.PI / 4); var worldPoint = new Vector2(11, 13); var localPoint = obb.InverseTransformPoint(worldPoint); var result = obb.TransformPoint(localPoint); Assert.That(result, Is.EqualTo(worldPoint)); }
public bool CollidesWith(OrientedRectangle orientedRectangle) { var r = new Rectangle(new Vector(0, 0), orientedRectangle.HalfExtent.MultiplyBy(2)); var c = new Circle(new Vector(0, 0), this.Radius); var distance = this.Center.Subtract(orientedRectangle.Center); c.Center = distance.Add(orientedRectangle.HalfExtent); return(c.CollidesWith(r)); }
public bool CollidesWith(OrientedRectangle orientedRectangle) { Rectangle localRectangle = orientedRectangle.TransformToLocalRectangle(); IVector2D lp = Position.Substract(orientedRectangle.Center); lp = lp.Rotate(-orientedRectangle.Rotation); lp = lp.Add(orientedRectangle.HalfExtend); var localPoint = new Point(lp); return localPoint.CollidesWith(localRectangle); }
public bool CollidesWith(OrientedRectangle orientedRectangle) { Rectangle lr = orientedRectangle.TransformToLocalRectangle(); IVector2D basee = Base.Substract(orientedRectangle.Center); basee = basee.Rotate(-orientedRectangle.Rotation); basee = basee.Add(orientedRectangle.HalfExtend); IVector2D direction = Direction.Rotate(-orientedRectangle.Rotation); var line = new Line(basee, direction); return line.CollidesWith(lr); }
/// <summary> /// Returns whether or not the given node is inside the rectangle. /// </summary> protected override bool IsInBox(IInputModeContext context, RectD rectangle, INode node) { var nodeOrientedRect = GetRotatedLayout(node); // Create an oriented rectangle with the size of the wrapped bounds and the location and rotation of the node var wrappedBounds = Wrapped.Renderer.GetBoundsProvider(node, Wrapped).GetBounds(context); var orientedRectangle = new OrientedRectangle(0, 0, wrappedBounds.Width, wrappedBounds.Height, nodeOrientedRect.UpX, nodeOrientedRect.UpY); orientedRectangle.SetCenter(node.Layout.GetCenter()); return(rectangle.Intersects(orientedRectangle, 0.01)); }
public void ORectCircle_Collide() { var a = new OrientedRectangle(Vector2.Zero, new Vector2(3, 1), MathF.PI / 2); var b = new Circle(new Vector2(1.5f, 0), 1f); CollisionSolver.CalculateCollisionFeatures(in a, in b, false, out var results); Assert.AreEqual(true, results.Collided); Assert.That(results.Normal, Is.Approximately(Vector2.UnitX)); Assert.AreEqual(0.5f / 2, results.Penetration); Assert.IsNotNull(results.Contacts); Assert.AreEqual(1, results.Contacts.Length); Assert.That(results.Contacts[0], Is.Approximately(new Vector2(0.75f, 0))); }
public void RectCircle_Collide() { var a = new OrientedRectangle(Vector2.Zero, new Vector2(3, 1), MathF.PI / 2); var b = new Circle(new Vector2(1.5f, 0), 1f); CollisionSolver.CalculateCollisionFeatures(in a, in b, 1, out var results); Assert.That(results.Collided); Assert.That(results.Normal, Is.Approximately(Vector2.UnitX)); Assert.That(results.Penetration, Is.EqualTo(0.5f / 2)); Assert.That(results.Contacts, Is.Not.Null); Assert.That(results.Contacts.Length, Is.EqualTo(1)); Assert.That(results.Contacts[0], Is.Approximately(new Vector2(0.75f, 0))); }
/// <summary> /// Returns bounds based on the size provided by the wrapped style and the location and rotation of the node. /// </summary> protected override RectD GetBounds(ICanvasContext context, INode node) { var nodeOrientedRect = GetRotatedLayout(node); // Create an oriented rectangle with the size of the wrapped bounds and the location and rotation of the node var wrappedBounds = Wrapped.Renderer.GetBoundsProvider(node, Wrapped).GetBounds(context); var orientedRectangle = new OrientedRectangle(0, 0, wrappedBounds.Width, wrappedBounds.Height, nodeOrientedRect.UpX, nodeOrientedRect.UpY); orientedRectangle.SetCenter(node.Layout.GetCenter()); return(orientedRectangle.GetBounds()); }
public bool CollidesWith(OrientedRectangle orientedRectangle) { Rectangle lr = orientedRectangle.TransformToLocalRectangle(); IVector2D point1 = Point1.Substract(orientedRectangle.Center); point1 = point1.Rotate(-orientedRectangle.Rotation); point1 = point1.Add(orientedRectangle.HalfExtend); IVector2D point2 = Point2.Substract(orientedRectangle.Center); point2 = point2.Rotate(-orientedRectangle.Rotation); point2 = point2.Add(orientedRectangle.HalfExtend); var ls = new LineSegment(point1, point2); return lr.CollidesWith(ls); }
/// <summary> /// Sets the original node bounds according to the given anchor location and size. /// </summary> private RectD SetNodeLocationAndSize(IInputModeContext inputModeContext, PointD anchor, SizeD size) { var graph = inputModeContext.GetGraph(); if (graph == null) { return(RectD.Empty); } var orientedRectangle = new OrientedRectangle(anchor.X, anchor.Y, size.Width, size.Height, initialLayout.UpX, initialLayout.UpY); var center = orientedRectangle.GetCenter(); var layout = RectD.FromCenter(center, size); graph.SetNodeLayout(node, layout); return(layout); }
public IOrientedRectangle GetGeometry(ILabel label, ILabelModelParameter parameter) { var php = parameter as PoolHeaderParameter; INode owner = (INode)label.Owner; if (php == null || owner == null) { return(null); } ITable table = owner.Lookup <ITable>(); InsetsD insets = table != null && table.Insets != InsetsD.Empty ? table.Insets : new InsetsD(0); var orientedRectangle = new OrientedRectangle(); orientedRectangle.Resize(label.PreferredSize); switch (php.Side) { case 0: // North orientedRectangle.SetUpVector(0, -1); orientedRectangle.SetCenter(new PointD(owner.Layout.X + owner.Layout.Width / 2, owner.Layout.Y + insets.Top / 2)); break; case 1: // East orientedRectangle.SetUpVector(1, 0); orientedRectangle.SetCenter(new PointD(owner.Layout.GetMaxX() - insets.Right / 2, owner.Layout.Y + owner.Layout.Height / 2)); break; case 2: // South orientedRectangle.SetUpVector(0, -1); orientedRectangle.SetCenter(new PointD(owner.Layout.X + owner.Layout.Width / 2, owner.Layout.GetMaxY() - insets.Bottom / 2)); break; case 3: // West default: orientedRectangle.SetUpVector(-1, 0); orientedRectangle.SetCenter(new PointD(owner.Layout.X + insets.Left / 2, owner.Layout.Y + owner.Layout.Height / 2)); break; } return(orientedRectangle); }
/// <summary> /// Returns the current geometry of the given label. /// </summary> public IOrientedRectangle GetGeometry(ILabel label, ILabelModelParameter parameter) { var styleWrapper = GetNodeStyleWrapper(label); var wrappedParameter = GetWrappedParameter(parameter); var orientedRectangle = wrappedParameter.Model.GetGeometry(label, wrappedParameter); var node = label.Owner as INode; if (!UseNodeRotation || node == null || styleWrapper == null || styleWrapper.Angle == 0) { return(orientedRectangle); } var rotatedCenter = styleWrapper.GetRotatedPoint(orientedRectangle.GetCenter(), node, true); var rotatedLayout = styleWrapper.GetRotatedLayout(node); var rectangle = new OrientedRectangle(orientedRectangle); rectangle.Angle += rotatedLayout.GetRadians(); rectangle.SetCenter(rotatedCenter); return(rectangle); }
public void SetAnchor(SliderEdgeLabelModel labelModel, IEdge edge, OrientedRectangle geometry) { IPathGeometry pathGeometry = GetPathGeometry(edge); if (pathGeometry != null) { int count = pathGeometry.GetSegmentCount(); int index = segmentIndex; if (index >= count) { index = count - 1; } if (index < 0) { index = count + index; } if (index < 0) { index = 0; } else if (index >= count) { index = count - 1; } double thisRatio = ratio; var validTangent = pathGeometry.GetTangent(index, thisRatio); if (validTangent.HasValue) { var p = validTangent.Value.Point; var t = validTangent.Value.Vector; AnchorGeometry(geometry, labelModel.EdgeRelativeDistance, labelModel.Distance, p.X, p.Y, thisRatio, t.X, t.Y); return; } } geometry.Width = -1; geometry.Height = -1; }
///<inheritdoc/> public IOrientedRectangle GetGeometry(ILabel label, ILabelModelParameter parameter) { OrientedRectangle geometry = new OrientedRectangle(0, 0, 10, 10); IEdge edge = (IEdge)label.Owner; if (edge == null) { geometry.Width = -1; geometry.Height = -1; return(geometry); } SliderParameter sliderParameter = (SliderParameter)parameter; SizeD preferredSize = label.PreferredSize; geometry.Width = preferredSize.Width; geometry.Height = preferredSize.Height; geometry.SetUpVector(upX, upY); sliderParameter.SetAnchor(this, edge, geometry); return(geometry); }
/// <summary> /// Finds the label model parameter that describes the given label layout best. /// </summary> /// <remarks> /// Sometimes the layout cannot be met exactly, then the nearest location is used. /// </remarks> public ILabelModelParameter FindBestParameter(ILabel label, ILabelModel model, IOrientedRectangle labelLayout) { var wrapperModel = model as RotatableNodeLabelModelDecorator; var styleWrapper = wrapperModel.GetNodeStyleWrapper(label); if (!wrapperModel.UseNodeRotation || styleWrapper == null || styleWrapper.Angle == 0) { return (wrapperModel.CreateWrappingParameter(wrappedFinder.FindBestParameter(label, wrapperModel.Wrapped, labelLayout))); } var node = label.Owner as INode; var rotatedCenter = styleWrapper.GetRotatedPoint(labelLayout.GetCenter(), node, false); var rotatedLayout = styleWrapper.GetRotatedLayout(node); var rectangle = new OrientedRectangle(labelLayout); rectangle.Angle -= rotatedLayout.GetRadians(); rectangle.SetCenter(rotatedCenter); return (wrapperModel.CreateWrappingParameter(wrappedFinder.FindBestParameter(label, wrapperModel.Wrapped, rectangle))); }
public bool CollidesWith(OrientedRectangle orientedRectangle) { var orHull = orientedRectangle.GetRectangleHull(); if (!orHull.CollidesWith(this)) { return(false); } var edge = orientedRectangle.Edge(0); if (this.IsSeparatingAxis(edge)) { return(false); } edge = orientedRectangle.Edge(1); if (this.IsSeparatingAxis(edge)) { return(false); } return(true); }
public Visual UpdateSelectionVisual(IRenderContext context, Visual oldVisual, IOrientedRectangle layout) { var container = oldVisual as VisualGroup; if (container != null && container.Children.Count == 1) { var visual = container.Children[0] as FrameworkElement; if (visual != null) { Transform transform = context.IntermediateTransform; container.Transform = transform; var anchor = layout.GetAnchorLocation(); var anchorAndUp = anchor + layout.GetUp(); anchor = context.WorldToIntermediateCoordinates(anchor); anchorAndUp = context.WorldToIntermediateCoordinates(anchorAndUp); var or = new OrientedRectangle(); or.SetUpVector((anchorAndUp - anchor).Normalized); or.SetAnchor(anchor); or.Width = layout.Width * context.Zoom; or.Height = layout.Height * context.Zoom; visual.Width = or.Width; visual.Height = or.Height; visual.SetCanvasArrangeRect(new Rect(0, 0, or.Width, or.Height)); ArrangeByLayout(context, visual, or, false); if (!container.IsMeasureValid) { container.Arrange(new Rect(0, 0, or.Width, or.Height)); } return(container); } } return(CreateSelectionVisual(context, layout)); }
protected override VisualGroup CreateVisual(IRenderContext context, ILabel label) { // Updates the dummy label which is internally used for rendering with the properties of the given label. UpdateDummyLabel(context, label); // creates the container for the visual and sets a transform for view coordinates var container = new VisualGroup(); var toViewTransform = context.WorldTransform.Clone(); toViewTransform.Invert(); // ReSharper disable once PossibleUnintendedReferenceComparison if (container.Transform != toViewTransform) { container.Transform = toViewTransform; } var creator = InnerLabelStyle.Renderer.GetVisualCreator(dummyLabel, InnerLabelStyle); // create a new IRenderContext with a zoom of 1 // TODO: Projections var innerContext = new RenderContext(context.Graphics, context.CanvasControl) { ViewTransform = context.ViewTransform, WorldTransform = context.WorldTransform, Zoom = 1 }; //The wrapped style should always think it's rendering with zoom level 1 var visual = creator.CreateVisual(innerContext); if (visual == null) { return(container); } // add the created visual to the container container.Children.Add(visual); IGraphSelection selection = context.CanvasControl != null?context.CanvasControl.Lookup <IGraphSelection>() : null; bool selected = selection != null && selection.IsSelected(label); // if the label is selected, add the selection visualization, too. if (selected) { //The selection descriptor performs its own calculation in the view coordinate system, so //the size and the position of the visualization would be wrong and need to be converted back into world //coordinates var layout = dummyLabel.GetLayout(); var p1 = context.CanvasControl.ToWorldCoordinates(layout.GetAnchorLocation()); var selectionLayout = new OrientedRectangle { Anchor = p1, Width = layout.Width / context.Zoom, Height = layout.Height / context.Zoom }; selectionLayout.SetUpVector(layout.UpX, layout.UpY); var selectionVisual = new OrientedRectangleIndicatorInstaller().Template; container.Children.Add(selectionVisual); } return(container); }
public bool CollidesWith(OrientedRectangle orientedRectangle) { Rectangle localRectangle = orientedRectangle.TransformToLocalRectangle(); IVector2D distance = Center.Substract(orientedRectangle.Center); distance = distance.Rotate(-orientedRectangle.Rotation); var localCenter = distance.Add(orientedRectangle.HalfExtend); var localCircle = new Circle(localCenter, Radius); return localCircle.CollidesWith(localRectangle); }
/// <summary> /// Instantiates a new label style. /// </summary> public ZoomInvariantLabelStyle(ILabelStyle innerLabelStyle) { InnerLabelStyle = innerLabelStyle; rectangle = new OrientedRectangle(); dummyLabel = new SimpleLabel(null, string.Empty, new FreeLabelModel().CreateDynamic(rectangle)); }
private static void AnchorGeometry(OrientedRectangle geometry, bool edgeRelativeDistance, double labelModelDistance, double x, double y, double thisRatio, double tx, double ty) { // sanitize tangent if (tx == 0 && ty == 0) { tx = 1; } // apply edge relative logic double distance; if (!edgeRelativeDistance && tx < 0) { distance = -labelModelDistance; } else { distance = labelModelDistance; } // transformation matrix double m11 = -geometry.UpY; double m12 = geometry.UpX; double m21 = -m12; double m22 = m11; // transform to make labels aligned with x-y axes // transform point double nx = x * m11 + y * m12; double ny = x * m21 + y * m22; // transform tangent double ntx = tx * m11 + ty * m12; double nty = tx * m21 + ty * m22; x = nx; y = ny; tx = ntx; ty = nty; double width = geometry.Width; double height = geometry.Height; // see if we should stack vertically or horizontally bool verticalStacking; if (distance != 0) { double atx = Math.Abs(tx); double aty = Math.Abs(ty); if (atx > 2 * aty) { verticalStacking = true; } else if (aty > 2 * atx) { verticalStacking = false; } else { if ((tx * ty) > 0) { verticalStacking = distance > 0; } else { verticalStacking = distance < 0; } if (thisRatio > 0.5) { verticalStacking = !verticalStacking; } } } else { verticalStacking = Math.Abs(tx) > Math.Abs(ty); } // calculate the center position using the ratio if (verticalStacking) { y = -y; UpdatePosition(distance, height, width, thisRatio, -ty, tx, ref y, ref x); y = -y; } else { UpdatePosition(distance, width, height, thisRatio, tx, ty, ref x, ref y); } // go to the anchor x -= width * 0.5; y += height * 0.5; // retransform to original coordinate system and assign as anchor geometry.AnchorX = x * m11 + y * m21; geometry.AnchorY = x * m12 + y * m22; }
public bool CollidesWith(OrientedRectangle orientedRectangle) { Rectangle orHull = orientedRectangle.RectangleHull(); if (!orHull.CollidesWith(this)) { return false; } LineSegment edge = orientedRectangle.Edge(0); if (edge.SeparatingAxisForRectangle(this)) { return false; } edge = orientedRectangle.Edge(1); return !edge.SeparatingAxisForRectangle(this); }
public bool SeparatingAxisForOrientedRectangle(OrientedRectangle orientedRectangle) { LineSegment rEdge0 = orientedRectangle.Edge(0); LineSegment rEdge2 = orientedRectangle.Edge(2); IVector2D n = Point1.Substract(Point2); Range axisRange = ProjectOnto(n); Range r0Range = rEdge0.ProjectOnto(n); Range r2Range = rEdge2.ProjectOnto(n); Range rProjection = r0Range.Hull(r2Range); return !axisRange.Overlaps(rProjection); }
public static void SetSize(this OrientedRectangle rect, SizeD size) { rect.Width = size.Width; rect.Height = size.Height; }
public bool CollidesWith(OrientedRectangle orientedRectangle) => orientedRectangle.CollidesWith(this);