Fixes to appending an arc

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@9252 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Nicola Pero 2001-03-01 01:47:32 +00:00
parent 94fe65783b
commit c76c32bc0f

View file

@ -828,103 +828,132 @@ static Class NSBezierPath_concrete_class = nil;
[self lineToPoint: points[i]];
}
- (void)appendBezierPathWithOvalInRect:(NSRect)aRect
- (void) appendBezierPathWithOvalInRect: (NSRect)aRect
{
[self appendBezierPath: [isa bezierPathWithOvalInRect: aRect]];
}
- (void)appendBezierPathWithArcWithCenter:(NSPoint)center
radius:(float)radius
startAngle:(float)startAngle
endAngle:(float)endAngle
clockwise:(BOOL)clockwise
/* startAngle and endAngle are in degrees, counterclockwise, from the
x axis */
- (void) appendBezierPathWithArcWithCenter: (NSPoint)center
radius: (float)radius
startAngle: (float)startAngle
endAngle: (float)endAngle
clockwise: (BOOL)clockwise
{
NSBezierPath *path = [isa bezierPath];
float strtangrd, endangrd, diff;
float startAngle_rad, endAngle_rad, diff;
NSPoint p0, p1, p2, p3;
while(startAngle < 0)
while (startAngle < 0)
startAngle = startAngle + 360;
while(startAngle > 360)
while (startAngle > 360)
startAngle = startAngle - 360;
while(endAngle < 0)
while (endAngle < 0)
endAngle = endAngle + 360;
while(endAngle > 360)
while (endAngle > 360)
endAngle = endAngle - 360;
strtangrd = PI * startAngle / 180;
endangrd = PI * endAngle / 180;
/* Convert the angles to radians */
startAngle_rad = PI * startAngle / 180;
endAngle_rad = PI * endAngle / 180;
p0 = NSMakePoint(center.x + radius * cos(strtangrd), center.y + radius * sin(strtangrd));
[path moveToPoint: p0];
/* Start point */
p0 = NSMakePoint (center.x + radius * cos (startAngle_rad),
center.y + radius * sin (startAngle_rad));
[self moveToPoint: p0];
if (clockwise)
{
diff = -PI / 2;
if (strtangrd < endangrd)
strtangrd += 2 * PI;
if (startAngle_rad < endAngle_rad)
{
startAngle_rad += 2 * PI;
}
}
else
{
diff = PI / 2;
if (strtangrd > endangrd)
strtangrd -= 2 * PI;
if (startAngle_rad > endAngle_rad)
{
startAngle_rad -= 2 * PI;
}
}
while (strtangrd > endangrd)
{
if (strtangrd + diff >= endangrd)
{
float sin_sta = sin(strtangrd);
float cos_sta = cos(strtangrd);
// FIXME: Add a quarter circle, for clockwise the signs are not correct!
p1 = NSMakePoint(center.x + radius * (cos_sta - KAPPA * sin_sta),
center.y + radius * (sin_sta + KAPPA * cos_sta));
p2 = NSMakePoint(center.x + radius * (KAPPA * cos_sta -sin_sta),
center.y + radius * (cos_sta + KAPPA * sin_sta));
p3 = NSMakePoint(center.x + radius * (-sin_sta),
center.y + radius * cos_sta);
[path curveToPoint: p3 controlPoint1: p1 controlPoint2: p2];
strtangrd += diff;
}
else
{
float diff_ang = (endangrd - strtangrd) / 2;
float cos_da = cos(diff_ang);
float sin_da = sin(diff_ang);
double x, y;
float sin_sta = sin(strtangrd + diff_ang);
float cos_sta = cos(strtangrd + diff_ang);
x = (4 - cos_da) / 3;
y = ((1- cos_da) * (cos_da - 3)) / (3 * sin_da);
// FIXME: Add just the missing bit, for clockwise the signs are not correct!
p1 = NSMakePoint(center.x + radius * (cos_sta * x - sin_sta * y),
center.y + radius * (sin_sta * y + cos_sta * x));
p2 = NSMakePoint(center.x + radius * (cos_sta * x + sin_sta * y),
center.y + radius * (sin_sta * (-y) + cos_sta * x));
p3 = NSMakePoint(center.x + radius * cos(endangrd),
center.y + radius * sin(endangrd));
[path curveToPoint: p3 controlPoint1: p1 controlPoint2: p2];
break;
}
while ((clockwise) ? (startAngle_rad > endAngle_rad)
: (startAngle_rad < endAngle_rad))
{
/* Add a quarter circle */
if ((clockwise) ? (startAngle_rad + diff >= endAngle_rad)
: (startAngle_rad + diff <= endAngle_rad))
{
float sin_start = sin (startAngle_rad);
float cos_start = cos (startAngle_rad);
float sign = (clockwise) ? -1.0 : 1.0;
p1 = NSMakePoint (center.x
+ radius * (cos_start - KAPPA * sin_start * sign),
center.y
+ radius * (sin_start + KAPPA * cos_start * sign));
p2 = NSMakePoint (center.x
+ radius * (-sin_start * sign + KAPPA * cos_start),
center.y
+ radius * (cos_start * sign + KAPPA * sin_start));
p3 = NSMakePoint (center.x + radius * (-sin_start * sign),
center.y + radius * cos_start * sign);
[self curveToPoint: p3 controlPoint1: p1 controlPoint2: p2];
startAngle_rad += diff;
}
else
{
/* Add the missing bit
* We require that the arc be less than a semicircle.
* The arc may go either clockwise or counterclockwise.
* The approximation is a very simple one: a single curve
* whose middle two control points are a fraction F of the way
* to the intersection of the tangents, where
* F = (4/3) / (1 + sqrt (1 + (d / r)^2))
* where r is the radius and d is the distance from either tangent
* point to the intersection of the tangents. This produces
* a curve whose center point, as well as its ends, lies on
* the desired arc.
*/
NSPoint ps = [self currentPoint];
/* tangent is the tangent of half the angle */
float tangent = tan ((endAngle_rad - startAngle_rad) / 2);
/* trad is the distance from either tangent point to the
intersection of the tangents */
float trad = radius * tangent;
/* pt is the intersection of the tangents */
NSPoint pt = NSMakePoint (ps.x - trad * sin (startAngle_rad),
ps.y + trad * cos (startAngle_rad));
/* This is F - in this expression we need to compute
(trad/radius)^2, which is simply tangent^2 */
float f = (4.0 / 3.0) / (1.0 + sqrt (1.0 + (tangent * tangent)));
p1 = NSMakePoint (ps.x + (pt.x - ps.x) * f, ps.y + (pt.y - ps.y) * f);
p3 = NSMakePoint(center.x + radius * cos (endAngle_rad),
center.y + radius * sin (endAngle_rad));
p2 = NSMakePoint (p3.x + (pt.x - p3.x) * f, p3.y + (pt.y - p3.y) * f);
[self curveToPoint: p3 controlPoint1: p1 controlPoint2: p2];
break;
}
}
}
- (void)appendBezierPathWithArcWithCenter:(NSPoint)center
radius:(float)radius
startAngle:(float)startAngle
endAngle:(float)endAngle
- (void) appendBezierPathWithArcWithCenter: (NSPoint)center
radius: (float)radius
startAngle: (float)startAngle
endAngle: (float)endAngle
{
[self appendBezierPathWithArcWithCenter: center radius: radius
startAngle: startAngle endAngle: endAngle clockwise: NO];
[self appendBezierPathWithArcWithCenter: center radius: radius
startAngle: startAngle endAngle: endAngle clockwise: NO];
}
- (void)appendBezierPathWithArcFromPoint:(NSPoint)point1
toPoint:(NSPoint)point2
radius:(float)radius
- (void) appendBezierPathWithArcFromPoint: (NSPoint)point1
toPoint: (NSPoint)point2
radius: (float)radius
{
// TODO
}
@ -1326,9 +1355,9 @@ typedef struct _PathElement
INVALIDATE_CACHE();
}
- (void)curveToPoint:(NSPoint)aPoint
controlPoint1:(NSPoint)controlPoint1
controlPoint2:(NSPoint)controlPoint2
- (void) curveToPoint: (NSPoint)aPoint
controlPoint1: (NSPoint)controlPoint1
controlPoint2: (NSPoint)controlPoint2
{
PathElement elem;
@ -1666,3 +1695,4 @@ static void flatten(NSPoint coeff[], float flatness, NSBezierPath *path)
[path lineToPoint: coeff[3]];
}
}