Hi Hez,
I've found a couple of bugs in your plarc routine which I've also fixed,
but since this is your code I'll leave you to look over it and commit
as/when necessary. There were 3 bugs in your plarc_approx routine.
Looking through the devices, it seems that with the exception of the
cairo devices, all the others don't drive any native arc-drawing and so
drop into your approx version. [I guess most/all ps and pdf, and svg,
devices probably know how to draw an arc, so I guess these drivers could
be modified, but that's another story. The approx version is perfectly
adequate for most purposes.]
1 When you filled an arc, you did so by OVERWRITING the last point in
the set of arc segments by the origin, so the filled arc stops short of
the last theta.
2 While you check to ensure that there are at least 2 segments so you
can fill the polygon, again since you overwrite the last point you only
end up with a polygon with 2 points which plfill can't fill.
3 When you calculate the number of segments, you don't allow for an arc
drawn backward, and so end up with a negative number of segments, which
then turns into 2 which is still not enough (see (2)).
All these were pretty easy to fix. I attach a test programme together
with my version of your plarc_approx for you to look at and commit. All
my changes (I think) have been commented with /* sjs ... */ comments.
Regards,
Steve
--
+-------------------------------------------------------------------+
Professor Steven J Schwartz Phone: +44-(0)20-7594-7660
Head, Space & Atmospheric Physics Fax: +44-(0)20-7594-7772
The Blackett Laboratory E-mail: s.schwa...@imperial.ac.uk
Imperial College London Office: Huxley 6M67A
London SW7 2AZ, U.K. Web: www.sp.ph.ic.ac.uk/~sjs
+-------------------------------------------------------------------+
/* sjs plarc July 2010 */
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include "plConfig.h"
#include "plplot.h"
#include "plplotP.h" /* for PL_MAXPOLY */
/* prototpyes */
void plot1();
void
plarc_approx_sjs(PLFLT x, PLFLT y, PLFLT a, PLFLT b, PLFLT angle1, PLFLT angle2, PLBOOL fill);
/*************************************************/
int main(int argc, const char *argv[]){
plparseopts(&argc, argv, PL_PARSE_FULL);
plstar(1,1);
plot1();
plend();
exit(0);
}
void plot1(){
PLFLT x[10],y[10],r[10],th[10], xl[10],yl[10];
PLFLT ox, oy;
double DEG_TO_RAD = atan(1.0)/45.;
int i;
/* orgin */
ox=0.0; oy=0.0;
r[0] = 1.0; r[1] = 1.0;
th[0] = 20; th[1] = 60.;
for (i=0; i<2; i++){
x[i] = xl[i] = r[i]*cos(DEG_TO_RAD*th[i]);
y[i] = yl[i] = r[i]*sin(DEG_TO_RAD*th[i]);
}
xl[2] = ox; yl[2] = oy;
xl[3] = xl[0]; yl[3] = yl[0];
plcol0(2);
plenv(-0.5, 1.5, -0.5, 1.5, 0, 0);
pllab("(x)", "(y)", "plarc");
/* use plplot's plarc */
plarc(0.0,0.0,r[0],r[1],th[0],th[1],1);
/* mark corners */
plpoin(2,x,y,5);
plpoin(1,&ox,&oy,5);
plcol0(1);
plline(4, xl,yl);
/* now try with sjs routine instead */
plcol0(2);
plenv(-0.5, 1.5, -0.5, 1.5, 0, 0);
pllab("(x)", "(y)", "sjs plarc_approx");
plarc_approx_sjs(0.0,0.0,r[0],r[1],th[0],th[1],1);
plpoin(2,x,y,5);
plpoin(1,&ox,&oy,5);
plcol0(1);
plline(4, xl,yl);
return;
}
/**********************************************************
* fix to plarc_approx to avoid replacing last point by origin
*
* sjs July 2010
*
************************************************************/
#define DEG_TO_RAD(x) ((x) * M_PI / 180.0)
#define PLARC_POINT_X(x, a, b, theta) ((x) + ((a) * cos(theta)))
#define PLARC_POINT_Y(y, a, b, theta) ((y) + ((b) * sin(theta)))
#define CIRCLE_SEGMENTS PL_MAXPOLY-1 /* sjs */
/* sjs: NOTE: reserve last segment of polygon for center if needed */
void
plarc_approx_sjs(PLFLT x, PLFLT y, PLFLT a, PLFLT b, PLFLT angle1, PLFLT angle2, PLBOOL fill)
{
PLINT i;
PLFLT theta0, theta_step, theta, d_angle;
PLINT segments;
PLFLT xs[PL_MAXPOLY], ys[PL_MAXPOLY]; /* sjs: CIRCLE_SEGMENTS +1 for center */
/* The difference between the start and end angles */
d_angle = DEG_TO_RAD(angle2 - angle1);
if (fabs(d_angle) > M_PI * 2.0)
d_angle = M_PI * 2.0;
/* The number of line segments used to approximate the arc */
/* sjs: ensure segments is positive even if angle2 < angle2 */
segments = fabs(d_angle) / (2.0 * M_PI) * CIRCLE_SEGMENTS;
/* Always use at least 2 arc points, otherwise fills will break. */
if (segments < 2) /* sjs: NB this fails in orig as fill needs 3 pts */
segments = 2;
/* The start angle in radians and number of radians in each approximating
segment. */
theta0 = DEG_TO_RAD(angle1);
theta_step = d_angle / (segments - 1);
/* The coordinates for the circle outline */
for (i = 0; i < segments; i++) {
theta = theta0 + theta_step * (PLFLT) i;
xs[i] = PLARC_POINT_X(x, a, b, theta);
ys[i] = PLARC_POINT_Y(y, a, b, theta);
}
if (fill) {
/* Add the center point if we aren't drawing a circle */
if (fabs(d_angle) < M_PI * 2.0) {
xs[segments] = x; /* sjs: DON'T erase last point */
ys[segments] = y;
segments++; /* sjs: increment segments */
}
/* Draw a filled arc */
plfill(segments, xs, ys);
}
else {
/* Draw the arc outline */
plline(segments, xs, ys);
}
}
------------------------------------------------------------------------------
This SF.net email is sponsored by Sprint
What will you do first with EVO, the first 4G phone?
Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first
_______________________________________________
Plplot-devel mailing list
Plplot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/plplot-devel