Re: Drawing Arcs
Re: Drawing Arcs
- Subject: Re: Drawing Arcs
- From: Henry McGilton <email@hidden>
- Date: Sun, 6 Jul 2003 12:14:56 -0700
From: Henry McGilton <email@hidden>
Date: Sun Jul 6, 2003 12:09:34 PM US/Pacific
To: "Alastair J.Houghton" <email@hidden>
Subject: Re: Drawing Arcs
On Sunday, July 6, 2003, at 05:11 AM, Alastair J.Houghton wrote:
On Sunday, July 6, 2003, at 05:26 am, Jim Crafton wrote:
Hi again,
* * I am trying to draw an arc given the following where:
* * x1, y1, x2, y2 define the bounding rectangle of the
* * arc. The arc follows along the ellipse that fits this
* * rect
Start off looking at:
NSBezierPath bezierPathWithOvalInRect: (NSRect)rect
and
- (void)appendBezierPathWithOvalInRect: (NSRect)rect
* * x3,y3 define the starting point which intersects with
* * edge of arc and the center of rect x4,y4 define the
* * ending point which intersects with edge of arc and the
* * center of rect (for those with Win32 experience this
* * is the same as Win32's Arc function)
Now this one is slightly more tricky, which is only to be expected
if it's being described in terms of Windows APIs.
What you would use here is
appendBezierPathWithArcFromPoint:toPoint:radius:
This method is roughly analogous to the PostScript language arcto
or arct operators. The arcto/arct operators draw what is known
as a fillet in mechanical drawing terms --- nothing to do with
cuts of meat.
The toPoint parameter is the point at which the fillet is to end
up (and will define the new current point). The toPoint parameter
defines the corner of the fillet (not its starting point). The
actual starting point of the fillet is defined by the current point.
You might see if you have any PostScript language reference manual
around, or my book 'PostScript by Example', which goes through all
of this stuff in detail, with code samples and pictures as well,
to show you what happens.
* * I notice that NSBezierPath can draw arcs that trace
* * along a circle, but not elliptical arcs. What's
* * the best approach for tackling this?
Sorry, I notice that NSBezierPath *can* draw arcs that trace along
elliptical arcs. The ovalInRect methods are obvious cases. The
less obvious case --- the one you want --- can be obtained by the
appendBezierPathWithArcFromPoint:toPoint:radius: mentioned here,
plus an affine transform to scale the coordinates and then transform
the Bezier path if required.
* You can use Bezier curves to approximate an arc; see
*
http://www.tinaja.com/cubic01.asp (in particular, see
*
http://www.tinaja.com/glib/bezarc1.pdf for a solution
* to the problem of fitting a cubic Bezier curve to a
* circular arc; remember that an elliptical arc is the
* same but for a constant factor). Also check out the
* comp.graphics.algorithms FAQ, at
*
http://www.faqs.org/faqs/graphics/algorithms-faq/ (see
* section 4.04).
Yes, you *can* use Bezier curves to approximate an arc, but you
hardly ever need to do so --- the current set of functions do
ninety-nine and nine nines of most of the cases you will ever run
into. The only time in the past ten years that I have used Bezier
curves to approximate an arc was when using Coons patches to smooth
shade a circle.
Look at it this way: The NSBezierPath functions provide the
capabilities that were present in the PostScript language and the
Display PostScript system. There was never a time using PostScript
operators that you had to use Bezier paths to approximate arcs of
circles (or ellipses for that matter), because that was what the
arc, arcn, arcto, and arct operators did for you anyway.
So any time you see somebody writing about using Bezier curve
operators to approximate arcs, you can be sure they have overlooked
the obvious.
You can get most of what is wanted using
NSBezierPath bezierPathWithOvalInRect: (NSRect)rect
- (void)appendBezierPathWithOvalInRect: (NSRect)rect
appendBezierPathWithArcWithCenter:radius:startAngle:endAngle:
and a few others.
* An alternative would be to approximate the arc with
* straight line segments (similar to the standard algorithms
* for rendering Bezier curves, in fact); for example,
* you could compute points on the arc (using the parametric
* formula for an ellipse), and continue to subdivide
* until you find a chord whose gradient is approximately
* constant, then render it as a straight line segment.
This is a position of absolutely last resort. It is turning
something moderately simple into something unbelievably complicated.
No wonder the newbies are confused.
* The one thing you *can't* do is to use a transformation
* to distort a circular arc, because in Quartz things
* like line width, dash patterns etcetera are _geometric_
* attributes (on most other systems, Win32 included AFAIK,
* such things are _cosmetic_ attributes, which means that
* they are not affected by geometric transformation;
* Quartz is a more advanced graphics subsystem and as
* such, line styles etcetera *are* affected by any
* transformations in effect).
What you say is true to a point, and very well said in making the
distinction between geometric attributes versus cosmetic attributes.
But, you get the desired effect (uniformly rendered attributes in
a transformed coordinate system) by using NSAffineTransform's
transformBezierPath method, which appears ready-made for just this
application.
Best Wishes,
........ Henry
===============================+============================
Henry McGilton, Boulevardier | Trilithon Software
Objective-C/Java Composer | Seroia Research
-------------------------------+----------------------------
mailto:email@hidden |
http://www.trilithon.com
|
===============================+============================
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.