From 8b517a26a21a3abb8c8d7d2c0412ea207b633721 Mon Sep 17 00:00:00 2001 From: lecoanet Date: Mon, 26 Jan 2004 09:35:10 +0000 Subject: ZnLineToPointDist can optionally return the closest point on the line. Added ZnRectOrigin2Anchor to compute the anchor position on any rectangles (ZnOrigin2Anchor works only for bounding boxes). --- generic/Geo.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 7 deletions(-) (limited to 'generic/Geo.c') diff --git a/generic/Geo.c b/generic/Geo.c index b1ad802..5a284c1 100644 --- a/generic/Geo.c +++ b/generic/Geo.c @@ -227,6 +227,56 @@ ZnOrigin2Anchor(ZnPoint *origin, } } +/* + * Compute the anchor position given a rectangle and + * the anchor. The rectangle vertices must be ordered + * as for a triangle strip: + * + * v0 ------------ v2 + * | | + * | | + * v1 ------------ v3 + */ +void +ZnRectOrigin2Anchor(ZnPoint *rect, + Tk_Anchor anchor, + ZnPoint *position) +{ + switch (anchor) { + case TK_ANCHOR_CENTER: + position->x = (rect[0].x + rect[3].x) / 2.0; + position->y = (rect[0].y + rect[3].y) / 2.0; + break; + case TK_ANCHOR_NW: + *position = *rect; + break; + case TK_ANCHOR_N: + position->x = (rect[0].x + rect[2].x) / 2.0; + position->y = (rect[0].y + rect[2].y) / 2.0; + break; + case TK_ANCHOR_NE: + *position = rect[2]; + break; + case TK_ANCHOR_E: + position->x = (rect[2].x + rect[3].x) / 2.0; + position->y = (rect[2].y + rect[3].y) / 2.0; + break; + case TK_ANCHOR_SE: + *position = rect[3]; + break; + case TK_ANCHOR_S: + position->x = (rect[1].x + rect[3].x) / 2.0; + position->y = (rect[1].y + rect[3].y) / 2.0; + break; + case TK_ANCHOR_SW: + *position = rect[1]; + break; + case TK_ANCHOR_W: + position->x = (rect[0].x + rect[1].x) / 2.0; + position->y = (rect[0].y + rect[1].y) / 2.0; + break; + } +} void ZnBBox2XRect(ZnBBox *bbox, @@ -1392,14 +1442,14 @@ ZnRectangleToPointDist(ZnBBox *bbox, p1.x = bbox->orig.x; p1.y = p2.y = bbox->orig.y; p2.x = bbox->corner.x; - dist = ZnLineToPointDist(&p1, &p2, p); + dist = ZnLineToPointDist(&p1, &p2, p, NULL); if (dist == 0.0) { return 0.0; } p1 = p2; p2.y = bbox->corner.y; - new_dist = ZnLineToPointDist(&p1, &p2, p); + new_dist = ZnLineToPointDist(&p1, &p2, p, NULL); dist = MIN(dist, new_dist); if (dist == 0.0) { return 0.0; @@ -1407,7 +1457,7 @@ ZnRectangleToPointDist(ZnBBox *bbox, p1 = p2; p2.x = bbox->orig.x; - new_dist = ZnLineToPointDist(&p1, &p2, p); + new_dist = ZnLineToPointDist(&p1, &p2, p, NULL); dist = MIN(dist, new_dist); if (dist == 0.0) { return 0.0; @@ -1415,7 +1465,7 @@ ZnRectangleToPointDist(ZnBBox *bbox, p1 = p2; p2.y = bbox->orig.y; - new_dist = ZnLineToPointDist(&p1, &p2, p); + new_dist = ZnLineToPointDist(&p1, &p2, p, NULL); dist = MIN(dist, new_dist); if (ZnPointInBBox(bbox, p->x, p->y)) { @@ -1434,7 +1484,8 @@ ZnRectangleToPointDist(ZnBBox *bbox, ZnDim ZnLineToPointDist(ZnPoint *p1, ZnPoint *p2, - ZnPoint *p) + ZnPoint *p, + ZnPoint *closest) { ZnReal x, y; ZnReal x_int, y_int; @@ -1511,6 +1562,11 @@ ZnLineToPointDist(ZnPoint *p1, } } } + + if (closest) { + closest->x = x; + closest->y = y; + } /* Return the distance */ return hypot(p->x - x, p->y - y); @@ -1994,9 +2050,9 @@ ZnGetBezierPoints(ZnPoint *p1, { ZnReal dist; - dist = ZnLineToPointDist(p1, p2, c1); + dist = ZnLineToPointDist(p1, p2, c1, NULL); if ((dist < eps) && ((c1->x != c2->x) || (c1->y != c2->y))) { - dist = ZnLineToPointDist(p1, p2, c2); + dist = ZnLineToPointDist(p1, p2, c2, NULL); } if (dist > eps) { -- cgit v1.1