aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/map/libmap/twocirc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/map/libmap/twocirc.c')
-rw-r--r--src/cmd/map/libmap/twocirc.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/cmd/map/libmap/twocirc.c b/src/cmd/map/libmap/twocirc.c
new file mode 100644
index 00000000..0d0e48a4
--- /dev/null
+++ b/src/cmd/map/libmap/twocirc.c
@@ -0,0 +1,80 @@
+#include <u.h>
+#include <libc.h>
+#include "map.h"
+
+static double
+quadratic(double a, double b, double c)
+{
+ double disc = b*b - 4*a*c;
+ return disc<0? 0: (-b-sqrt(disc))/(2*a);
+}
+
+/* for projections with meridians being circles centered
+on the x axis and parallels being circles centered on the y
+axis. Find the intersection of the meridian thru (m,0), (90,0),
+with the parallel thru (0,p), (p1,p2) */
+
+static int
+twocircles(double m, double p, double p1, double p2, double *x, double *y)
+{
+ double a; /* center of meridian circle, a>0 */
+ double b; /* center of parallel circle, b>0 */
+ double t,bb;
+ if(m > 0) {
+ twocircles(-m,p,p1,p2,x,y);
+ *x = -*x;
+ } else if(p < 0) {
+ twocircles(m,-p,p1,-p2,x,y);
+ *y = -*y;
+ } else if(p < .01) {
+ *x = m;
+ t = m/p1;
+ *y = p + (p2-p)*t*t;
+ } else if(m > -.01) {
+ *y = p;
+ *x = m - m*p*p;
+ } else {
+ b = p>=1? 1: p>.99? 0.5*(p+1 + p1*p1/(1-p)):
+ 0.5*(p*p-p1*p1-p2*p2)/(p-p2);
+ a = .5*(m - 1/m);
+ t = m*m-p*p+2*(b*p-a*m);
+ bb = b*b;
+ *x = quadratic(1+a*a/bb, -2*a + a*t/bb,
+ t*t/(4*bb) - m*m + 2*a*m);
+ *y = (*x*a+t/2)/b;
+ }
+ return 1;
+}
+
+static int
+Xglobular(struct place *place, double *x, double *y)
+{
+ twocircles(-2*place->wlon.l/PI,
+ 2*place->nlat.l/PI, place->nlat.c, place->nlat.s, x, y);
+ return 1;
+}
+
+proj
+globular(void)
+{
+ return Xglobular;
+}
+
+static int
+Xvandergrinten(struct place *place, double *x, double *y)
+{
+ double t = 2*place->nlat.l/PI;
+ double abst = fabs(t);
+ double pval = abst>=1? 1: abst/(1+sqrt(1-t*t));
+ double p2 = 2*pval/(1+pval);
+ twocircles(-place->wlon.l/PI, pval, sqrt(1-p2*p2), p2, x, y);
+ if(t < 0)
+ *y = -*y;
+ return 1;
+}
+
+proj
+vandergrinten(void)
+{
+ return Xvandergrinten;
+}