4 /* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004
5 Free Software Foundation, Inc.
6 Written by Gaius Mulley <gaius@glam.ac.uk>
7 using adjust_arc_center() from printer.cpp, written by James Clark.
9 This file is part of groff.
11 groff is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 2, or (at your option) any later
16 groff is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License along
22 with groff; see the file COPYING. If not, write to the Free Software
23 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
30 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
33 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
36 // This utility function adjusts the specified center of the
37 // arc so that it is equidistant between the specified start
38 // and end points. (p[0], p[1]) is a vector from the current
39 // point to the center; (p[2], p[3]) is a vector from the
40 // center to the end point. If the center can be adjusted,
41 // a vector from the current point to the adjusted center is
42 // stored in c[0], c[1] and 1 is returned. Otherwise 0 is
46 int adjust_arc_center(const int *p
, double *c
)
48 // We move the center along a line parallel to the line between
49 // the specified start point and end point so that the center
50 // is equidistant between the start and end point.
51 // It can be proved (using Lagrange multipliers) that this will
52 // give the point nearest to the specified center that is equidistant
53 // between the start and end point.
55 double x
= p
[0] + p
[2]; // (x, y) is the end point
56 double y
= p
[1] + p
[3];
61 double k
= .5 - (c
[0]*x
+ c
[1]*y
)/n
;
70 int printer::adjust_arc_center(const int *p
, double *c
)
72 int x
= p
[0] + p
[2]; // (x, y) is the end point
74 // Start at the current point; go in the direction of the specified
75 // center point until we reach a point that is equidistant between
76 // the specified starting point and the specified end point. Place
77 // the center of the arc there.
78 double n
= p
[0]*double(x
) + p
[1]*double(y
);
80 double k
= (double(x
)*x
+ double(y
)*y
)/(2.0*n
);
81 // (cx, cy) is our chosen center
87 // We would never reach such a point. So instead start at the
88 // specified end point of the arc. Go towards the specified
89 // center point until we reach a point that is equidistant between
90 // the specified start point and specified end point. Place
91 // the center of the arc there.
92 n
= p
[2]*double(x
) + p
[3]*double(y
);
94 double k
= 1 - (double(x
)*x
+ double(y
)*y
)/(2.0*n
);
95 // (c[0], c[1]) is our chosen center
108 * check_output_arc_limits - works out the smallest box that will encompass
109 * an arc defined by an origin (x, y) and two
110 * vectors (p0, p1) and (p2, p3).
111 * (x1, y1) -> start of arc
112 * (x1, y1) + (xv1, yv1) -> center of circle
113 * (x1, y1) + (xv1, yv1) + (xv2, yv2) -> end of arc
115 * Works out in which quadrant the arc starts and
116 * stops, and from this it determines the x, y
117 * max/min limits. The arc is drawn clockwise.
120 void check_output_arc_limits(int x_1
, int y_1
,
123 double c_0
, double c_1
,
124 int *minx
, int *maxx
,
125 int *miny
, int *maxy
)
127 int radius
= (int)sqrt(c_0
* c_0
+ c_1
* c_1
);
128 // clockwise direction
129 int xcenter
= x_1
+ xv_1
;
130 int ycenter
= y_1
+ yv_1
;
131 int xend
= xcenter
+ xv_2
;
132 int yend
= ycenter
+ yv_2
;
133 // for convenience, transform to counterclockwise direction,
134 // centered at the origin
135 int xs
= xend
- xcenter
;
136 int ys
= yend
- ycenter
;
137 int xe
= x_1
- xcenter
;
138 int ye
= y_1
- ycenter
;
149 int qs
, qe
; // quadrants 0..3
151 qs
= (ys
>= 0) ? 0 : 3;
153 qs
= (ys
>= 0) ? 1 : 2;
155 qe
= (ye
>= 0) ? 0 : 3;
157 qe
= (ye
>= 0) ? 1 : 2;
158 // make qs always smaller than qe
160 || ((qs
== qe
) && (double(xs
) * ye
< double(xe
) * ys
)))
162 for (int i
= qs
; i
< qe
; i
++)