Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic Aligning AnchorPoints to ShapeNode border (Read 3386 times)
adavis
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 9
Joined: May 6th, 2009
Aligning AnchorPoints to ShapeNode border
Jun 22nd, 2009 at 4:16pm
Print Post  
Hi,

I'm experimenting with an application which programmatically creates nodes and sets their anchor patterns. However, the AnchorPoint constructor takes x and y locations as percentages, and the actual location of the resulting AnchorPoint is based on the ShapeNode's bounding rectangle, and not its actual shape. So, for example, a Shapes.Hourglass node with AnchorPoints at (0%, 50%) and (100%, 50%) comes out like this:



What is the best way to programmatically define the anchor points such that they will actually coincide with the edges of the shape? If at all possible I'd like to find a general solution, as creating the AnchorPattern differently for each different node shape would get rather cumbersome.
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Aligning AnchorPoints to ShapeNode border
Reply #1 - Jun 23rd, 2009 at 6:34am
Print Post  
Hi,

You could use the following method to find the shape points coordinates. You might also add some arguments to customize the result, e.g. to include additional points such as the middle points of line segments.

Code
Select All
List<PointF> shapePoints = GetShapePoints(Shapes.Tape);
foreach (PointF p in shapePoints)
	Debug.WriteLine(p.ToString());

List<PointF> GetShapePoints(Shape shape)
{
	List<PointF> points = new List<PointF>();

	foreach (ElementTemplate element in shape.Outline)
	{
		LineTemplate line = element as LineTemplate;
		if (line != null)
		{
			AddPoint(points, line.Coordinates[0], line.Coordinates[1]);
			AddPoint(points, line.Coordinates[2], line.Coordinates[3]);
		}

		BezierTemplate bezier = element as BezierTemplate;
		if (bezier != null)
		{
			AddPoint(points, bezier.Coordinates[0], bezier.Coordinates[1]);
			AddPoint(points, bezier.Coordinates[6], bezier.Coordinates[7]);
		}

		ArcTemplate arc = element as ArcTemplate;
		if (arc != null)
		{
			if (arc.SweepAngle == 360)
			{
				AddRect(points, arc.Bounds);
			}
			else
			{
				GraphicsPath path = new GraphicsPath();
				path.AddArc(arc.Bounds, arc.StartAngle, arc.SweepAngle);
				AddPoint(points, path.PathPoints[0]);
				AddPoint(points, path.PathPoints[path.PathPoints.Length - 1]);
				path.Dispose();
			}
		}

		RoundRectangleTemplate roundRect = element as RoundRectangleTemplate;
		if (roundRect != null)
		{
			AddRect(points, roundRect.Bounds);
		}
	}

	if (points[0] == points[points.Count - 1])
		points.RemoveAt(points.Count - 1);
	return points;
}

void AddRect(List<PointF> points, RectangleF r)
{
	AddPoint(points, r.X + r.Width / 2, r.Top);
	AddPoint(points, r.Right, r.Y + r.Height / 2);
	AddPoint(points, r.X + r.Width / 2, r.Bottom);
	AddPoint(points, r.Left, r.Y + r.Height / 2);
}

void AddPoint(List<PointF> points, float x, float y)
{
	AddPoint(points, new PointF(x, y));
}

void AddPoint(List<PointF> points, PointF point)
{
	if (points.Count == 0 || points[points.Count - 1] != point)
		points.Add(point);
}
 



I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
adavis
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 9
Joined: May 6th, 2009
Re: Aligning AnchorPoints to ShapeNode border
Reply #2 - Jun 23rd, 2009 at 11:49am
Print Post  
That looks great, thanks!  I should be able to modify that to suit my needs without much trouble.  8)
  
Back to top
 
IP Logged
 
adavis
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 9
Joined: May 6th, 2009
Re: Aligning AnchorPoints to ShapeNode border
Reply #3 - Jun 23rd, 2009 at 2:55pm
Print Post  
I just thought of something I might as well ask: what do you think would be the easiest way to figure out which element(s) in a Shape outline correspond to which 'sides' of the shape?

I haven't started coding this yet, but the obvious solution is to first loop through all the elements in the shape and sort/classify them (probably based on start and end points of each element), and then deriving the anchorpoints for each 'side' individually instead of doing a foreach loop over the entire shape.Outline collection.

'Sorting' the shape elements into 'sides' seems like a messy and potentially problematic solution, though, especially for things like ellipses. Can you think of a better way?

What I specifically need to do is have one incoming anchor in the (vertical) center of the left side; another incoming anchor in the (horizontal) middle of the top; one outgoing anchor in the (vertical) center of the right side; and a variable number of outgoing links evenly spaced along the bottom.

Another idea just occurred to me -- I could determine the center point of the shape, create imaginary lines out from that point in the directions I desire, and then find intersections between those lines and the elements in shape.Outline. Would that be a good solution? I just looked through the documentation a little and haven't found any easy way of finding the intersection point between a line and one of the shape outline elements, though I could just code that myself if necessary.
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Aligning AnchorPoints to ShapeNode border
Reply #4 - Jun 23rd, 2009 at 3:11pm
Print Post  
The second idea should be easy to implement using the DiagramNode.GetIntersection(Point segmentStart, Point segmentEnd) method. Create a ShapeNode with bounds = 0, 0, 100, 100, set its Shape to whatever shape you need to find the intersections for, and call that method with segmentStart set to 50, 50 and segmentEnd set to a point from the outline.

I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
adavis
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 9
Joined: May 6th, 2009
Re: Aligning AnchorPoints to ShapeNode border
Reply #5 - Jun 23rd, 2009 at 5:19pm
Print Post  
That sounds like it should work perfectly.

Thanks for your help!
  
Back to top
 
IP Logged
 
adavis
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 9
Joined: May 6th, 2009
Re: Aligning AnchorPoints to ShapeNode border
Reply #6 - Jun 23rd, 2009 at 8:17pm
Print Post  
I've implemented this functionality now, and for the most part it's working well. However, I have run into a few little quirks. Are these known issues, or caused by something I'm doing? Or should I submit them in the bug forum?

- When I call GetIntersection() with an end segment that has X or Y = 0, it doesn't actually find an intersection on the outside edge of a Rectangle or RoundRect; I have to set the values to -1 instead of 0 to have it find the intersection. X or Y values of 100 work fine, though.

- Using the 'DataTransmition' shape, GetIntersection() never finds an intersection when the endpoint's X >= 100 and Y = 50; but it works fine when I set Y = 50.1, so presumably it's something to do with the two lines that make up the right-hand side of a 'DataTransmition' shape not quite meeting each other in the middle.
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Aligning AnchorPoints to ShapeNode border
Reply #7 - Jun 24th, 2009 at 6:06am
Print Post  
It seems this method looks for the intersection point of the shape outline with the segment defined by the two points, and not the line defined by them. So one of the points should be from outside the shape and the other one should be inside for this to work. I suppose this might also fail if the segments coincide only at one end point, depending on some precision errors in the floating point operations used.

Instead of node.GetIntersection, try using the Utilities.LineIntersect method. It finds the intersection point of the lines defined by two pairs of points, so you will need to loop over the points that define the node outline and call it for each line segment.

I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint