C
Christ Kennedy
Guest
I'm making a jigsaw puzzle-er app that takes a bitmap, chops it into regular sized rectangles then places to adjacent pieces together on a temp bitmap to add/remove the jigsaw puzzle piece 'tongues'.
when I use a graphicsPath to mask out the tongue and isolate each piece on either side of the tongue outline i end up with a problem. the tongue itself is draw using three separate Ellipse Segments that are defined by two points and a 'height'(similar to diagram found at Radius of an Arc or Arch - Math Open Reference where the W is derived by taking the distance between the two points)
here is the code that does that :
public static void GraphicsPath_Add(ref GraphicsPath grPath, bool bolClockwise, PointF pt0, Point pt1, int intSegmentHeight)
{
////////////////////////////////////////////// overwriting pt0 to equal last point in path ///////////////////////////////////////////////////////
if (grPath.PathData.Points.Length > 0)
;// pt0 = grPath.PathData.Points[grPath.PathData.Points.Length - 1];
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int intGrPathIndexStart = grPath.PathData.Points.Length-1;
double dblArc_Height = (double)intSegmentHeight;
classRadialCoordinate cRad = new classRadialCoordinate(pt0, pt1);
double dblArc_Width = cRad.Magnitude;
Point ptBetweenInputs = new Point((int)(pt0.X + (pt1.X - pt0.X) / 2),(int)( pt0.Y + (pt1.Y - pt0.Y) / 2));
float fltBaseAngle = (float)(cRad.Degrees
+ (bolClockwise ? -90 : 90));
if (bolClockwise)
cRad.Radians += Math.PI / 2;
else
cRad.Radians -= Math.PI / 2;
//Radius of an Arc or Arch - Math Open Reference
// R = h/2 + w^2/(8h)
double dblRadius = dblArc_Height/ 2 + Math.Pow(dblArc_Width, 2) / (8 * dblArc_Height);
double dblTheta = Math.Asin((dblArc_Width/2)/ dblRadius);
float fltDegree_Start = fltBaseAngle - (float)(180.0 / Math.PI * dblTheta);
float fltDegree_Sweep = (float)(360.0 / Math.PI * dblTheta);
cRad.Magnitude = dblRadius - dblArc_Height;
Point ptCenterEllipse = AddTwoPoints(ptBetweenInputs, cRad.toPoint());
Rectangle recEllipse = new Rectangle(ptCenterEllipse.X - (int)dblRadius, ptCenterEllipse.Y - (int)dblRadius, (int)(2.0 * dblRadius), (int)(2.0 * dblRadius));
if (fltDegree_Sweep > 0)
{
grPath.AddArc(recEllipse, fltDegree_Start, fltDegree_Sweep);
}
}
this code does give me the necessary information to create an arc on the GraphicsPath but there are issues.
the points around the tongue are first calculated. Then they are used in sequence to generate the path
pt0 with pt1
pt1 with pt2
pt2 with pt3 and so on around the tongue each call to the above function including a clockwise/counter-clockwise boolean as well as the arc-segment's 'height'.
since all the arc-segments start with the end point of the previous arc-segment it was reasonable to expect them to create a smooth series of continuous arcs but the unexpected result is that it occasionally. These transitions seem to reverse the sequence of the previous arc before starting the next one and creates an unsightly line between the two points of the previous arc.
see image:
in the image above you can see that the arc from points 2-3 is counter-clockwise(CC), then from 3-4 is clockwise(C) and from 4-5 is CC but there's an ugly line connecting points 4-5 which I don't want.
so I added a line at the start of the function included above which sets the input parameter pt0 equal to the last point in the graphicsPath's list of Points to make certain that the next arc starts at exactly the same place as the previous arc(un-comment the third line of the code-above). When I do this I wind up with something similar to the image below.
which, as you can see, is even less desireable. Here it appears to transition from 2-3(CC) to 3-4(C) by starting the 3-4 arc at location 2 ?!?? which is obviously not what I want.
any idea how to solve this one?
Christ
my code is perfect until i don't find a bug
Continue reading...
when I use a graphicsPath to mask out the tongue and isolate each piece on either side of the tongue outline i end up with a problem. the tongue itself is draw using three separate Ellipse Segments that are defined by two points and a 'height'(similar to diagram found at Radius of an Arc or Arch - Math Open Reference where the W is derived by taking the distance between the two points)
here is the code that does that :
public static void GraphicsPath_Add(ref GraphicsPath grPath, bool bolClockwise, PointF pt0, Point pt1, int intSegmentHeight)
{
////////////////////////////////////////////// overwriting pt0 to equal last point in path ///////////////////////////////////////////////////////
if (grPath.PathData.Points.Length > 0)
;// pt0 = grPath.PathData.Points[grPath.PathData.Points.Length - 1];
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int intGrPathIndexStart = grPath.PathData.Points.Length-1;
double dblArc_Height = (double)intSegmentHeight;
classRadialCoordinate cRad = new classRadialCoordinate(pt0, pt1);
double dblArc_Width = cRad.Magnitude;
Point ptBetweenInputs = new Point((int)(pt0.X + (pt1.X - pt0.X) / 2),(int)( pt0.Y + (pt1.Y - pt0.Y) / 2));
float fltBaseAngle = (float)(cRad.Degrees
+ (bolClockwise ? -90 : 90));
if (bolClockwise)
cRad.Radians += Math.PI / 2;
else
cRad.Radians -= Math.PI / 2;
//Radius of an Arc or Arch - Math Open Reference
// R = h/2 + w^2/(8h)
double dblRadius = dblArc_Height/ 2 + Math.Pow(dblArc_Width, 2) / (8 * dblArc_Height);
double dblTheta = Math.Asin((dblArc_Width/2)/ dblRadius);
float fltDegree_Start = fltBaseAngle - (float)(180.0 / Math.PI * dblTheta);
float fltDegree_Sweep = (float)(360.0 / Math.PI * dblTheta);
cRad.Magnitude = dblRadius - dblArc_Height;
Point ptCenterEllipse = AddTwoPoints(ptBetweenInputs, cRad.toPoint());
Rectangle recEllipse = new Rectangle(ptCenterEllipse.X - (int)dblRadius, ptCenterEllipse.Y - (int)dblRadius, (int)(2.0 * dblRadius), (int)(2.0 * dblRadius));
if (fltDegree_Sweep > 0)
{
grPath.AddArc(recEllipse, fltDegree_Start, fltDegree_Sweep);
}
}
this code does give me the necessary information to create an arc on the GraphicsPath but there are issues.
the points around the tongue are first calculated. Then they are used in sequence to generate the path
pt0 with pt1
pt1 with pt2
pt2 with pt3 and so on around the tongue each call to the above function including a clockwise/counter-clockwise boolean as well as the arc-segment's 'height'.
since all the arc-segments start with the end point of the previous arc-segment it was reasonable to expect them to create a smooth series of continuous arcs but the unexpected result is that it occasionally. These transitions seem to reverse the sequence of the previous arc before starting the next one and creates an unsightly line between the two points of the previous arc.
see image:
in the image above you can see that the arc from points 2-3 is counter-clockwise(CC), then from 3-4 is clockwise(C) and from 4-5 is CC but there's an ugly line connecting points 4-5 which I don't want.
so I added a line at the start of the function included above which sets the input parameter pt0 equal to the last point in the graphicsPath's list of Points to make certain that the next arc starts at exactly the same place as the previous arc(un-comment the third line of the code-above). When I do this I wind up with something similar to the image below.
which, as you can see, is even less desireable. Here it appears to transition from 2-3(CC) to 3-4(C) by starting the 3-4 arc at location 2 ?!?? which is obviously not what I want.
any idea how to solve this one?
Christ
my code is perfect until i don't find a bug
Continue reading...