diff options
Diffstat (limited to 'generic')
-rw-r--r-- | generic/Geo.c | 213 | ||||
-rw-r--r-- | generic/Geo.h | 9 |
2 files changed, 222 insertions, 0 deletions
diff --git a/generic/Geo.c b/generic/Geo.c index 91e36a1..c07d2f5 100644 --- a/generic/Geo.c +++ b/generic/Geo.c @@ -2013,6 +2013,219 @@ GetBezierPath(ZnList from_points, } } + +/* + ********************************************************************************** + * + * GetCirclePoints -- + * Return a pointer to an array of points describing a + * circle arc of radius 1.0. The arc is described by start_angle, + * end_angle and the type: 0 for arc, 1 for chord, 2 for pie slice, + * 3 for a full circle (in which case start_angle and end_angle are + * not used. + * The number of points is returned in num_points. If type is not 3, + * point_list must not be NULL. If not NULL, it is filled with the + * computed points. + * + ********************************************************************************** + */ +ZnPoint * +GetCirclePoints(int type, + int quality, + ZnReal start_angle, + ZnReal end_angle, + int *num_points, + ZnList point_list) +{ + static ZnPoint genarc64[] = { + {1.0, 0.0}, + {0.99518472653, 0.0980171417729}, + {0.980785279837, 0.195090324861}, + {0.956940334469, 0.290284681418}, + {0.923879530291, 0.382683437725}, + {0.88192126093, 0.471396743221}, + {0.831469607468, 0.555570240255}, + {0.773010446922, 0.634393292011}, + {0.707106772982, 0.707106789391}, + {0.634393274074, 0.773010461643}, + {0.555570220961, 0.83146962036}, + {0.471396722756, 0.881921271869}, + {0.382683416286, 0.923879539171}, + {0.290284659212, 0.956940341205}, + {0.195090302102, 0.980785284364}, + {0.0980171186795, 0.995184728805}, + {-2.32051033331e-08, 1.0}, + {-0.0980171648663, 0.995184724256}, + {-0.19509034762, 0.98078527531}, + {-0.290284703624, 0.956940327733}, + {-0.382683459163, 0.923879521411}, + {-0.471396763686, 0.881921249991}, + {-0.555570259549, 0.831469594576}, + {-0.634393309949, 0.773010432201}, + {-0.707106805799, 0.707106756574}, + {-0.773010476365, 0.634393256136}, + {-0.831469633252, 0.555570201666}, + {-0.881921282808, 0.471396702291}, + {-0.923879548052, 0.382683394847}, + {-0.956940347941, 0.290284637006}, + {-0.980785288892, 0.195090279343}, + {-0.995184731079, 0.0980170955862}, + {-1.0, -4.64102066663e-08}, + {-0.995184721981, -0.0980171879596}, + {-0.980785270783, -0.195090370379}, + {-0.956940320997, -0.29028472583}, + {-0.923879512531, -0.382683480602}, + {-0.881921239052, -0.471396784151}, + {-0.831469581684, -0.555570278844}, + {-0.77301041748, -0.634393327887}, + {-0.707106740165, -0.707106822208}, + {-0.634393238198, -0.773010491086}, + {-0.555570182372, -0.831469646144}, + {-0.471396681826, -0.881921293746}, + {-0.382683373409, -0.923879556932}, + {-0.2902846148, -0.956940354677}, + {-0.195090256583, -0.980785293419}, + {-0.0980170724928, -0.995184733354}, + {6.96153097774e-08, -1.0}, + {0.098017211053, -0.995184719707}, + {0.195090393139, -0.980785266256}, + {0.290284748036, -0.956940314261}, + {0.382683502041, -0.923879503651}, + {0.471396804617, -0.881921228114}, + {0.555570298138, -0.831469568792}, + {0.634393345825, -0.773010402759}, + {0.707106838616, -0.707106723757}, + {0.773010505807, -0.63439322026}, + {0.831469659036, -0.555570163078}, + {0.881921304685, -0.471396661361}, + {0.923879565812, -0.38268335197}, + {0.956940361414, -0.290284592594}, + {0.980785297946, -0.195090233824}, + {0.995184735628, -0.0980170493994}, + {1.0, 0.0}}; + + static ZnPoint genarc20[] = { + {1.0, 0.0}, + {0.951056514861, 0.309016998789}, + {0.809016988919, 0.587785259802}, + {0.587785241028, 0.809017002559}, + {0.309016976719, 0.951056522032}, + {-2.32051033331e-08, 1.0}, + {-0.309017020858, 0.95105650769}, + {-0.587785278575, 0.809016975279}, + {-0.809017016198, 0.587785222255}, + {-0.951056529203, 0.30901695465}, + {-1.0, -4.64102066663e-08}, + {-0.951056500519, -0.309017042928}, + {-0.80901696164, -0.587785297348}, + {-0.587785203482, -0.809017029838}, + {-0.309016932581, -0.951056536373}, + {6.96153097774e-08, -1.0}, + {0.309017064997, -0.951056493349}, + {0.587785316122, -0.809016948}, + {0.809017043478, -0.587785184709}, + {0.951056543544, -0.309016910511}, + {1.0, 0.0}}; + + static ZnPoint genarc8[] = { + {1.0, 0.0}, + {0.707106772982, 0.707106789391}, + {-2.32051033331e-08, 1.0}, + {-0.707106805799, 0.707106756574}, + {-1.0, -4.64102066663e-08}, + {-0.707106740165, -0.707106822208}, + {6.96153097774e-08, -1.0}, + {0.707106838616, -0.707106723757}, + {1.0, 0.0}}; + int num_p, i; + ZnPoint *p, *p_from; + ZnPoint center_p = { 0.0, 0.0 }; + ZnPoint start_p, wp; + ZnReal iangle; + + switch (quality) { + case ZN_CIRCLE_COARSE: + num_p = sizeof(genarc8)/sizeof(ZnPoint); + p = p_from = genarc8; + break; + case ZN_CIRCLE_MEDIUM: + num_p = sizeof(genarc20)/sizeof(ZnPoint); + p = p_from = genarc20; + break; + default: + case ZN_CIRCLE_FINEST: + num_p = sizeof(genarc64)/sizeof(ZnPoint); + p = p_from = genarc64; + } + + if (type != 3) { + /* + * normalize start_angle and end_angle. + */ + start_angle = fmod(start_angle, 2.0*M_PI); + if (start_angle < 0.0) { + start_angle += 2.0*M_PI; + } + end_angle = fmod(end_angle, 2.0*M_PI); + if (end_angle < 0.0) { + end_angle += 2.0*M_PI; + } + if (start_angle >= end_angle) { + if (start_angle == end_angle) { + type = 3; + } + end_angle += 2.0*M_PI; + } + } + + /* + * Now 0 <= start_angle < 2 * M_PI and start_angle <= end_angle. + */ + if ((type != 3) || (point_list != NULL)) { + if (type == 3) { + ZnListAssertSize(point_list, num_p); + p = ZnListArray(point_list); + for (i = 0; i < num_p; i++, p++, p_from++) { + *p = *p_from; + } + } + else { + ZnListEmpty(point_list); + iangle = 2*M_PI / (num_p-1); + start_p.x = cos(start_angle); + start_p.y = sin(start_angle); + ZnListAdd(point_list, &start_p, ZnListTail); + i = start_angle / iangle; + if ((i * iangle) < start_angle) { + i++; + } + p = &p_from[i]; + while (start_angle < end_angle) { + ZnListAdd(point_list, &p[i], ZnListTail); + start_angle += iangle; + i++; + if (i == num_p-1) { + i = 0; + } + } + wp.x = cos(end_angle); + wp.y = sin(end_angle); + if (type == 1) { + ZnListAdd(point_list, &start_p, ZnListTail); + } + else if (type == 2) { + ZnListAdd(point_list, ¢er_p, ZnListTail); + ZnListAdd(point_list, &start_p, ZnListTail); + } + } + p = ZnListArray(point_list); + num_p = ZnListSize(point_list); + } + + *num_points = num_p; + return p; +} + /* ********************************************************************************** * diff --git a/generic/Geo.h b/generic/Geo.h index 1304adf..5229012 100644 --- a/generic/Geo.h +++ b/generic/Geo.h @@ -279,6 +279,15 @@ void GetBezierPath(ZnList from_points, ZnList to_points); + +ZnPoint * +GetCirclePoints(int type, + int quality, + ZnReal start_angle, + ZnReal end_angle, + int *num_points, + ZnList point_list); + void GetArcPath(ZnReal start_angle, ZnReal end_angle, |