about summary refs log tree commit diff
path: root/editor/pamrubber.c
diff options
context:
space:
mode:
Diffstat (limited to 'editor/pamrubber.c')
-rw-r--r--editor/pamrubber.c542
1 files changed, 295 insertions, 247 deletions
diff --git a/editor/pamrubber.c b/editor/pamrubber.c
index 602701ec..f68e36fe 100644
--- a/editor/pamrubber.c
+++ b/editor/pamrubber.c
@@ -1,20 +1,18 @@
-/*----------------------------------------------------------------------------*/
-
-/* pamrubber.c - transform images using Rubber Sheeting algorithm
-**               see: http://www.schaik.com/netpbm/rubber/
-**
-** Copyright (C) 2011 by Willem van Schaik (willem@schaik.com)
-**
-** Permission to use, copy, modify, and distribute this software and its
-** documentation for any purpose and without fee is hereby granted, provided
-** that the above copyright notice appear in all copies and that both that
-** copyright notice and this permission notice appear in supporting
-** documentation.  This software is provided "as is" without express or
-** implied warranty.
-*/
-
-/*----------------------------------------------------------------------------*/
-
+/*=============================================================================
+                              pamrubber
+===============================================================================
+  Transform images using Rubber Sheeting algorithm
+  See: http://www.schaik.com/netpbm/rubber/
+
+  Copyright (C) 2011 by Willem van Schaik (willem@schaik.com)
+
+  Permission to use, copy, modify, and distribute this software and its
+  documentation for any purpose and without fee is hereby granted, provided
+  that the above copyright notice appear in all copies and that both that
+  copyright notice and this permission notice appear in supporting
+  documentation.  This software is provided "as is" without express or
+  implied warranty.
+=============================================================================*/
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -25,12 +23,12 @@
 
 #include "pm_c_util.h"
 #include "mallocvar.h"
+#include "rand.h"
 #include "shhopt.h"
 #include "pam.h"
 #include "pamdraw.h"
 
 
-
 typedef struct {
   double x;
   double y;
@@ -54,7 +52,7 @@ typedef struct {
     point br;  /* bottom right */
 } quadrilateral;
 
-struct cmdlineInfo {
+struct CmdlineInfo {
     unsigned int nCP;
     point        oldCP[4];
     point        newCP[4];
@@ -64,14 +62,14 @@ struct cmdlineInfo {
     unsigned int frame;
     unsigned int linear;
     unsigned int verbose;
-    unsigned int randseedSpec;
-    unsigned int randseed;
+    unsigned int randomseedSpec;
+    unsigned int randomseed;
 };
 
 
 static void
 parseCmdline(int argc, const char ** argv,
-             struct cmdlineInfo * const cmdlineP) {
+             struct CmdlineInfo * const cmdlineP) {
 
 /* parse all parameters from the command line */
 
@@ -92,10 +90,10 @@ parseCmdline(int argc, const char ** argv,
     OPTENT3(0, "frame",    OPT_FLAG, NULL, &cmdlineP->frame,    0);
     OPTENT3(0, "linear",   OPT_FLAG, NULL, &cmdlineP->linear,   0);
     OPTENT3(0, "verbose",  OPT_FLAG, NULL, &cmdlineP->verbose,  0);
-    OPTENT3(0, "randseed", OPT_UINT, &cmdlineP->randseed,
-            &cmdlineP->randseedSpec, 0);
-    OPTENT3(0, "randomseed", OPT_UINT, &cmdlineP->randseed,
-            &cmdlineP->randseedSpec, 0);
+    OPTENT3(0, "randseed", OPT_UINT, &cmdlineP->randomseed,
+            &cmdlineP->randomseedSpec, 0);
+    OPTENT3(0, "randomseed", OPT_UINT, &cmdlineP->randomseed,
+            &cmdlineP->randomseedSpec, 0);
 
     opt.opt_table = option_def;
     opt.short_allowed = FALSE;  /* we have no short (old-fashioned) options */
@@ -195,38 +193,39 @@ makeline(point const p1,
 
 
 
-static bool
-intersect(line *  const l1P,
-          line *  const l2P,
-          point * const pP) {
+static void
+findIntersection(const line *  const l1P,
+                 const line *  const l2P,
+                 bool *        const theyIntersectP,
+                 point *       const intersectionP) {
 
-    bool cross;
+    bool theyIntersect;
 
     if (((l2P->p2.y - l2P->p1.y) * (l1P->p2.x - l1P->p1.x) -
          (l2P->p2.x - l2P->p1.x) * (l1P->p2.y - l1P->p1.y)) == 0) {
         /* parallel lines */
 
-        cross = false;
+        theyIntersect = false;
 
         if ((l1P->p1.x == l1P->p2.x) && (l2P->p1.x == l2P->p2.x)) {
             /* two vertical lines */
-            pP->x = (l1P->p1.x + l2P->p1.x) / 2.0;
-            pP->y = 1e10;
+            intersectionP->x = (l1P->p1.x + l2P->p1.x) / 2.0;
+            intersectionP->y = 1e10;
         } else if ((l1P->p1.y == l1P->p2.y) && (l2P->p1.y == l2P->p2.y)) {
             /* two horizontal lines */
-            pP->x = 1e10;
-            pP->y = (l1P->p1.y + l2P->p1.y) / 2.0;
+            intersectionP->x = 1e10;
+            intersectionP->y = (l1P->p1.y + l2P->p1.y) / 2.0;
         } else {
             if (fabs(l1P->p2.y - l1P->p1.y) > fabs(l1P->p2.x - l1P->p1.x)) {
                 /* steep slope */
-                pP->y = 1e10;
-                pP->x = (l1P->p2.x - l1P->p1.x) / (l1P->p2.y - l1P->p1.y)
-                    * 1e10;
+                intersectionP->y = 1e10;
+                intersectionP->x =
+                    (l1P->p2.x - l1P->p1.x) / (l1P->p2.y - l1P->p1.y) * 1e10;
             } else {
                 /* even slope */
-                pP->x = 1e10;
-                pP->y = (l1P->p2.y - l1P->p1.y) / (l1P->p2.x - l1P->p1.x)
-                    * 1e10;
+                intersectionP->x = 1e10;
+                intersectionP->y =
+                    (l1P->p2.y - l1P->p1.y) / (l1P->p2.x - l1P->p1.x) * 1e10;
             }
         }
     } else {
@@ -244,16 +243,16 @@ intersect(line *  const l1P,
                * (l1P->p2.x - l1P->p1.x) - (l2P->p2.x - l2P->p1.x)
                * (l1P->p2.y - l1P->p1.y));
 
-        pP->x = l1P->p1.x + ua * (l1P->p2.x - l1P->p1.x);
-        pP->y = l1P->p1.y + ua * (l1P->p2.y - l1P->p1.y);
+        intersectionP->x = l1P->p1.x + ua * (l1P->p2.x - l1P->p1.x);
+        intersectionP->y = l1P->p1.y + ua * (l1P->p2.y - l1P->p1.y);
 
         if ((ua >= 0.0) && (ua <= 1.0) && (ub >= 0.0) && (ub <= 1.0))
-            cross = true;
+            theyIntersect = true;
         else
-            cross = false;
+            theyIntersect = false;
     }
-
-    return cross;
+    if (theyIntersectP)
+        *theyIntersectP = theyIntersect;
 }
 
 
@@ -309,28 +308,29 @@ insidetri(triangle * const triP,
 
 
 static bool
-windtriangle(triangle * const tP,
+windtriangle(triangle * const triP,
              point      const p1,
              point      const p2,
              point      const p3) {
     point f, c;
-    line le, lv;
     bool cw;
 
     /* find cross of vertical through p3 and the edge p1-p2 */
     f.x = p3.x;
     f.y = -1.0;
-    lv = makeline(p3, f);
-    le = makeline(p1, p2);
-    intersect(&le, &lv, &c);
+    {
+        line const lv = makeline(p3, f);
+        line const le = makeline(p1, p2);
+        findIntersection(&le, &lv, NULL, &c);
+    }
 
     /* check for clockwise winding triangle */
     if (((p1.x > p2.x) && (p3.y < c.y)) ||
         ((p1.x < p2.x) && (p3.y > c.y))) {
-        *tP = maketriangle(p1, p2, p3);
+        *triP = maketriangle(p1, p2, p3);
         cw = true;
     } else { /* p1/2/3 were counter clockwise */
-        *tP = maketriangle(p1, p3, p2);
+        *triP = maketriangle(p1, p3, p2);
         cw = false;
     }
     return cw;
@@ -339,28 +339,29 @@ windtriangle(triangle * const tP,
 
 
 static double
-tiny(void) {
+tiny(struct pm_randSt * const randStP) {
 
-    if (rand() % 2)
-        return +1E-6 * (double) ((rand() % 90) + 9);
+    if (pm_rand(randStP) % 2)
+        return +1E-6 * (double) ((pm_rand(randStP) % 90) + 9);
     else
-        return -1E-6 * (double) ((rand() % 90) + 9);
+        return -1E-6 * (double) ((pm_rand(randStP) % 90) + 9);
 }
 
 
 
 static void
 angle(point * const p1P,
-      point * const p2P) {
+      point * const p2P,
+      struct pm_randSt * const randStP) {
 /*----------------------------------------------------------------------------
    Move *p2P slightly if necessary to make sure the line (*p1P, *p2P)
    is not horizontal or vertical.
 -----------------------------------------------------------------------------*/
     if (p1P->x == p2P->x) { /* vertical line */
-        p2P->x += tiny();
+        p2P->x += tiny(randStP);
     }
     if (p1P->y == p2P->y) { /* horizontal line */
-        p2P->y += tiny();
+        p2P->y += tiny(randStP);
     }
 }
 
@@ -613,12 +614,16 @@ quadCorner(point           const p0,
 
     /* p0-p1 and p2-p3 are the diagonals */
 
+    triangle tri;
+
     if (fabs(p0.x - p1.x) + fabs(p0.y - p1.y) >=
         fabs(p2.x - p3.x) + fabs(p2.y - p3.y)) {
-        quadCornerSized(p0, p1, p2, p3, mid, quadP, triP);
+        quadCornerSized(p0, p1, p2, p3, mid, quadP, &tri);
     } else {
-        quadCornerSized(p2, p3, p0, p1, mid, quadP, triP);
+        quadCornerSized(p2, p3, p0, p1, mid, quadP, &tri);
     }
+    if (triP)
+        *triP = tri;
 }
 
 
@@ -720,8 +725,10 @@ static void drawClippedTriangle(const struct pam * const pamP,
 
 
 static void
-prepTrig(int const wd,
-         int const ht) {
+prepTrig(int          const wd,
+         int          const ht,
+         bool         const randomseedSpec,
+         unsigned int const randomseed) {
 
 /* create triangles using control points */
 
@@ -729,18 +736,21 @@ prepTrig(int const wd,
     point rtl2, rtr2, rbl2, rbr2;
     point c1p1, c1p2, c1p3, c1p4;
     point c2p1, c2p2, c2p3, c2p4;
-    line l1, l2;
     point p0;
+    struct pm_randSt randSt;
+
+    pm_randinit(&randSt);
+    pm_srand2(&randSt, randomseedSpec, randomseed);
 
-    rtl1 = makepoint(0.0 + tiny(),               0.0 + tiny());
-    rtr1 = makepoint((double) wd - 1.0 + tiny(), 0.0 + tiny());
-    rbl1 = makepoint(0.0 + tiny(),               (double) ht - 1.0 + tiny());
-    rbr1 = makepoint((double) wd - 1.0 + tiny(), (double) ht - 1.0 + tiny());
+    rtl1 = makepoint(0.0 + tiny(&randSt),               0.0 + tiny(&randSt));
+    rtr1 = makepoint((double) wd - 1.0 + tiny(&randSt), 0.0 + tiny(&randSt));
+    rbl1 = makepoint(0.0 + tiny(&randSt),               (double) ht - 1.0 + tiny(&randSt));
+    rbr1 = makepoint((double) wd - 1.0 + tiny(&randSt), (double) ht - 1.0 + tiny(&randSt));
 
-    rtl2 = makepoint(0.0 + tiny(),               0.0 + tiny());
-    rtr2 = makepoint((double) wd - 1.0 + tiny(), 0.0 + tiny());
-    rbl2 = makepoint(0.0 + tiny(),               (double) ht - 1.0 + tiny());
-    rbr2 = makepoint((double) wd - 1.0 + tiny(), (double) ht - 1.0 + tiny());
+    rtl2 = makepoint(0.0 + tiny(&randSt),               0.0 + tiny(&randSt));
+    rtr2 = makepoint((double) wd - 1.0 + tiny(&randSt), 0.0 + tiny(&randSt));
+    rbl2 = makepoint(0.0 + tiny(&randSt),               (double) ht - 1.0 + tiny(&randSt));
+    rbr2 = makepoint((double) wd - 1.0 + tiny(&randSt), (double) ht - 1.0 + tiny(&randSt));
 
     if (nCP == 1) {
         c1p1 = oldCP[0];
@@ -772,8 +782,8 @@ prepTrig(int const wd,
         c2p2 = newCP[1];
 
         /* check for hor/ver edges */
-        angle (&c1p1, &c1p2);
-        angle (&c2p1, &c2p2);
+        angle (&c1p1, &c1p2, &randSt);
+        angle (&c2p1, &c2p2, &randSt);
 
         /* connect two control points to corners to get 6 triangles */
         /* left side */
@@ -811,13 +821,13 @@ prepTrig(int const wd,
         /* Move vertices slightly if necessary to make sure no edge is
            horizontal or vertical.
         */
-        angle(&c1p1, &c1p2);
-        angle(&c1p2, &c1p3);
-        angle(&c1p3, &c1p1);
+        angle(&c1p1, &c1p2, &randSt);
+        angle(&c1p2, &c1p3, &randSt);
+        angle(&c1p3, &c1p1, &randSt);
 
-        angle(&c2p1, &c2p2);
-        angle(&c2p2, &c2p3);
-        angle(&c2p3, &c2p1);
+        angle(&c2p1, &c2p2, &randSt);
+        angle(&c2p2, &c2p3, &randSt);
+        angle(&c2p3, &c2p1, &randSt);
 
         if (windtriangle(&tri1s[0], c1p1, c1p2, c1p3)) {
             tri2s[0] = maketriangle(c2p1, c2p2, c2p3);
@@ -871,19 +881,19 @@ prepTrig(int const wd,
         c2p4 = newCP[3];
 
         /* check for hor/ver edges */
-        angle (&c1p1, &c1p2);
-        angle (&c1p2, &c1p3);
-        angle (&c1p3, &c1p4);
-        angle (&c1p4, &c1p1);
-        angle (&c1p1, &c1p3);
-        angle (&c1p2, &c1p4);
-
-        angle (&c2p1, &c2p2);
-        angle (&c2p2, &c2p3);
-        angle (&c2p3, &c2p4);
-        angle (&c2p4, &c2p1);
-        angle (&c2p1, &c2p3);
-        angle (&c2p2, &c2p4);
+        angle (&c1p1, &c1p2, &randSt);
+        angle (&c1p2, &c1p3, &randSt);
+        angle (&c1p3, &c1p4, &randSt);
+        angle (&c1p4, &c1p1, &randSt);
+        angle (&c1p1, &c1p3, &randSt);
+        angle (&c1p2, &c1p4, &randSt);
+
+        angle (&c2p1, &c2p2, &randSt);
+        angle (&c2p2, &c2p3, &randSt);
+        angle (&c2p3, &c2p4, &randSt);
+        angle (&c2p4, &c2p1, &randSt);
+        angle (&c2p1, &c2p3, &randSt);
+        angle (&c2p2, &c2p4, &randSt);
 
         /*-------------------------------------------------------------------*/
         /*        -1-      -2-        -3-      -4-        -5-      -6-       */
@@ -892,47 +902,58 @@ prepTrig(int const wd,
         /*       3   4    2   4      4   3    2   3      4   2    3   2      */
         /*-------------------------------------------------------------------*/
 
-        /* center two triangles */
-        l1 = makeline(c1p1, c1p4);
-        l2 = makeline(c1p2, c1p3);
-        if (intersect(&l1, &l2, &p0)) {
-            if (windtriangle(&tri1s[0], c1p1, c1p2, c1p3)) {
-                tri1s[1] = maketriangle(c1p4, c1p3, c1p2);
-                tri2s[0] = maketriangle(c2p1, c2p2, c2p3);
-                tri2s[1] = maketriangle(c2p4, c2p3, c2p2);
-            } else {
-                tri1s[1] = maketriangle(c1p4, c1p2, c1p3);
-                tri2s[0] = maketriangle(c2p1, c2p3, c2p2);
-                tri2s[1] = maketriangle(c2p4, c2p2, c2p3);
+        {
+            /* center two triangles */
+            line const l1 = makeline(c1p1, c1p4);
+            line const l2 = makeline(c1p2, c1p3);
+            bool theyIntersect;
+            findIntersection(&l1, &l2, &theyIntersect, &p0);
+            if (theyIntersect) {
+                if (windtriangle(&tri1s[0], c1p1, c1p2, c1p3)) {
+                    tri1s[1] = maketriangle(c1p4, c1p3, c1p2);
+                    tri2s[0] = maketriangle(c2p1, c2p2, c2p3);
+                    tri2s[1] = maketriangle(c2p4, c2p3, c2p2);
+                } else {
+                    tri1s[1] = maketriangle(c1p4, c1p2, c1p3);
+                    tri2s[0] = maketriangle(c2p1, c2p3, c2p2);
+                    tri2s[1] = maketriangle(c2p4, c2p2, c2p3);
+                }
             }
         }
-        l1 = makeline(c1p1, c1p3);
-        l2 = makeline(c1p2, c1p4);
-        if (intersect(&l1, &l2, &p0)) {
-            if (windtriangle(&tri1s[0], c1p1, c1p2, c1p4)) {
-                tri1s[1] = maketriangle(c1p3, c1p4, c1p2);
-                tri2s[0] = maketriangle(c2p1, c2p2, c2p4);
-                tri2s[1] = maketriangle(c2p3, c2p4, c2p2);
-            } else {
-                tri1s[1] = maketriangle(c1p3, c1p2, c1p4);
-                tri2s[0] = maketriangle(c2p1, c2p4, c2p2);
-                tri2s[1] = maketriangle(c2p3, c2p2, c2p4);
+        {
+            line const l1 = makeline(c1p1, c1p3);
+            line const l2 = makeline(c1p2, c1p4);
+            bool theyIntersect;
+            findIntersection(&l1, &l2, &theyIntersect, &p0);
+            if (theyIntersect) {
+                if (windtriangle(&tri1s[0], c1p1, c1p2, c1p4)) {
+                    tri1s[1] = maketriangle(c1p3, c1p4, c1p2);
+                    tri2s[0] = maketriangle(c2p1, c2p2, c2p4);
+                    tri2s[1] = maketriangle(c2p3, c2p4, c2p2);
+                } else {
+                    tri1s[1] = maketriangle(c1p3, c1p2, c1p4);
+                    tri2s[0] = maketriangle(c2p1, c2p4, c2p2);
+                    tri2s[1] = maketriangle(c2p3, c2p2, c2p4);
+                }
             }
         }
-        l1 = makeline(c1p1, c1p2);
-        l2 = makeline(c1p3, c1p4);
-        if (intersect(&l1, &l2, &p0)) {
-            if (windtriangle(&tri1s[0], c1p1, c1p3, c1p4)) {
-                tri1s[1] = maketriangle(c1p2, c1p4, c1p3);
-                tri2s[0] = maketriangle(c2p1, c2p3, c2p4);
-                tri2s[1] = maketriangle(c2p2, c2p4, c2p3);
-            } else {
-                tri1s[1] = maketriangle(c1p2, c1p3, c1p4);
-                tri2s[0] = maketriangle(c2p1, c2p4, c2p3);
-                tri2s[1] = maketriangle(c2p2, c2p3, c2p4);
+        {
+            line const l1 = makeline(c1p1, c1p2);
+            line const l2 = makeline(c1p3, c1p4);
+            bool theyIntersect;
+            findIntersection(&l1, &l2, &theyIntersect, &p0);
+            if (theyIntersect) {
+                if (windtriangle(&tri1s[0], c1p1, c1p3, c1p4)) {
+                    tri1s[1] = maketriangle(c1p2, c1p4, c1p3);
+                    tri2s[0] = maketriangle(c2p1, c2p3, c2p4);
+                    tri2s[1] = maketriangle(c2p2, c2p4, c2p3);
+                } else {
+                    tri1s[1] = maketriangle(c1p2, c1p3, c1p4);
+                    tri2s[0] = maketriangle(c2p1, c2p4, c2p3);
+                    tri2s[1] = maketriangle(c2p2, c2p3, c2p4);
+                }
             }
         }
-
         /* control points in correct orientation */
         c1p1 = tri1s[0].p1;
         c1p2 = tri1s[0].p2;
@@ -979,6 +1000,8 @@ prepTrig(int const wd,
                      &tri2s[9], c2p3, c2p1, rtl2, rtr2, rbl2, rbr2);
         nTri = 10;
     }
+
+    pm_randterm(&randSt);
 }
 
 
@@ -988,11 +1011,6 @@ prepQuad(void) {
 
 /* order quad control points */
 
-    double d01, d12, d20;
-    line l1, l2;
-    point mid;
-    triangle tri;
-
     if (nCP == 1) {
         /* create a rectangle from top-left corner of image and control
            point
@@ -1007,10 +1025,10 @@ prepQuad(void) {
         } else if ((oldCP[0].x > oldCP[1].x) && (oldCP[0].y < oldCP[1].y)) {
             /* top-right and bottom-left */
             quad1 = quadRect(oldCP[1].x, oldCP[0].x, oldCP[0].y, oldCP[1].y);
-        } else if ((oldCP[0].x < oldCP[1].x) && (oldCP[0].y < oldCP[1].y)) {
+        } else if ((oldCP[0].x < oldCP[1].x) && (oldCP[0].y > oldCP[1].y)) {
             /* bottom-left and top-right */
             quad1 = quadRect(oldCP[0].x, oldCP[1].x, oldCP[1].y, oldCP[0].y);
-        } else if ((oldCP[0].x > oldCP[1].x) && (oldCP[0].y < oldCP[1].y)) {
+        } else if ((oldCP[0].x > oldCP[1].x) && (oldCP[0].y > oldCP[1].y)) {
             /* bottom-right and top-left */
             quad1 = quadRect(oldCP[1].x, oldCP[0].x, oldCP[1].y, oldCP[0].y);
         }
@@ -1021,10 +1039,10 @@ prepQuad(void) {
         } else if ((newCP[0].x > newCP[1].x) && (newCP[0].y < newCP[1].y)) {
             /* top-right and bottom-left */
             quad2 = quadRect(newCP[1].x, newCP[0].x, newCP[0].y, newCP[1].y);
-        } else if ((newCP[0].x < newCP[1].x) && (newCP[0].y < newCP[1].y)) {
+        } else if ((newCP[0].x < newCP[1].x) && (newCP[0].y > newCP[1].y)) {
             /* bottom-left and top-right */
             quad2 = quadRect(newCP[0].x, newCP[1].x, newCP[1].y, newCP[0].y);
-        } else if ((newCP[0].x > newCP[1].x) && (newCP[0].y < newCP[1].y)) {
+        } else if ((newCP[0].x > newCP[1].x) && (newCP[0].y > newCP[1].y)) {
             /* bottom-right and top-left */
             quad2 = quadRect(newCP[1].x, newCP[0].x, newCP[1].y, newCP[0].y);
         }
@@ -1035,9 +1053,9 @@ prepQuad(void) {
                furthest apart
             */
 
-            d01 = distance(newCP[0], newCP[1]);
-            d12 = distance(newCP[1], newCP[2]);
-            d20 = distance(newCP[2], newCP[0]);
+            double const d01 = distance(newCP[0], newCP[1]);
+            double const d12 = distance(newCP[1], newCP[2]);
+            double const d20 = distance(newCP[2], newCP[0]);
 
             if ((d01 > d12) && (d01 > d20)) {
                 oldCP[3].x = oldCP[0].x + oldCP[1].x - oldCP[2].x;
@@ -1067,51 +1085,72 @@ prepQuad(void) {
 
         /* nCP = 3 or 4 */
 
-        /* find the intersection of the diagonals */
-        l1 = makeline(oldCP[0], oldCP[1]);
-        l2 = makeline(oldCP[2], oldCP[3]);
-        if (intersect(&l1, &l2, &mid)) {
-            quadCorner(oldCP[0], oldCP[1], oldCP[2], oldCP[3],
-                       mid, &quad1, &tri);
-        } else {
-            l1 = makeline(oldCP[0], oldCP[2]);
-            l2 = makeline(oldCP[1], oldCP[3]);
-            if (intersect(&l1, &l2, &mid))
-                quadCorner(oldCP[0], oldCP[2], oldCP[1], oldCP[3],
-                           mid, &quad1, &tri);
+        {
+            /* find the intersection of the diagonals */
+            line const l1 = makeline(oldCP[0], oldCP[1]);
+            line const l2 = makeline(oldCP[2], oldCP[3]);
+            bool theyIntersect;
+            point mid;
+            findIntersection(&l1, &l2, &theyIntersect, &mid);
+            if (theyIntersect)
+                quadCorner(oldCP[0], oldCP[1], oldCP[2], oldCP[3],
+                           mid, &quad1, NULL);
             else {
-                l1 = makeline(oldCP[0], oldCP[3]);
-                l2 = makeline(oldCP[1], oldCP[2]);
-                if (intersect(&l1, &l2, &mid))
-                    quadCorner(oldCP[0], oldCP[3],
-                               oldCP[1], oldCP[2], mid, &quad1, &tri);
-                else
-                    pm_error("The four old control points don't seem "
-                             "to be corners.");
+                line const l1 = makeline(oldCP[0], oldCP[2]);
+                line const l2 = makeline(oldCP[1], oldCP[3]);
+                bool theyIntersect;
+                point mid;
+                findIntersection(&l1, &l2, &theyIntersect, &mid);
+                if (theyIntersect)
+                    quadCorner(oldCP[0], oldCP[2], oldCP[1], oldCP[3],
+                               mid, &quad1, NULL);
+                else {
+                    line const l1 = makeline(oldCP[0], oldCP[3]);
+                    line const l2 = makeline(oldCP[1], oldCP[2]);
+                    bool theyIntersect;
+                    point mid;
+                    findIntersection(&l1, &l2, &theyIntersect, &mid);
+                    if (theyIntersect)
+                        quadCorner(oldCP[0], oldCP[3],
+                                   oldCP[1], oldCP[2], mid, &quad1, NULL);
+                    else
+                        pm_error("The four old control points don't seem "
+                                 "to be corners.");
+                }
             }
         }
-
-        /* repeat for the "to-be" control points */
-        l1 = makeline(newCP[0], newCP[1]);
-        l2 = makeline(newCP[2], newCP[3]);
-        if (intersect(&l1, &l2, &mid))
-            quadCorner(newCP[0], newCP[1], newCP[2], newCP[3],
-                       mid, &quad2, &tri);
-        else {
-            l1 = makeline(newCP[0], newCP[2]);
-            l2 = makeline(newCP[1], newCP[3]);
-            if (intersect(&l1, &l2, &mid))
-                quadCorner(newCP[0], newCP[2], newCP[1], newCP[3],
-                           mid, &quad2, &tri);
+        {
+            /* repeat for the "to-be" control points */
+            line const l1 = makeline(newCP[0], newCP[1]);
+            line const l2 = makeline(newCP[2], newCP[3]);
+            bool theyIntersect;
+            point mid;
+            findIntersection(&l1, &l2, &theyIntersect, &mid);
+            if (theyIntersect)
+                quadCorner(newCP[0], newCP[1], newCP[2], newCP[3],
+                           mid, &quad2, NULL);
             else {
-                l1 = makeline(newCP[0], newCP[3]);
-                l2 = makeline(newCP[1], newCP[2]);
-                if (intersect(&l1, &l2, &mid))
-                    quadCorner(newCP[0], newCP[3],
-                               newCP[1], newCP[2], mid, &quad2, &tri);
-                else
-                    pm_error("The four new control points don't seem "
-                             "to be corners.");
+                line const l1 = makeline(newCP[0], newCP[2]);
+                line const l2 = makeline(newCP[1], newCP[3]);
+                bool theyIntersect;
+                point mid;
+                findIntersection(&l1, &l2, &theyIntersect, &mid);
+                if (theyIntersect)
+                    quadCorner(newCP[0], newCP[2], newCP[1], newCP[3],
+                               mid, &quad2, NULL);
+                else {
+                    line const l1 = makeline(newCP[0], newCP[3]);
+                    line const l2 = makeline(newCP[1], newCP[2]);
+                    bool theyIntersect;
+                    point mid;
+                    findIntersection(&l1, &l2, &theyIntersect, &mid);
+                    if (theyIntersect)
+                        quadCorner(newCP[0], newCP[3],
+                                   newCP[1], newCP[2], mid, &quad2, NULL);
+                    else
+                        pm_error("The four new control points don't seem "
+                                 "to be corners.");
+                }
             }
         }
     }
@@ -1127,14 +1166,11 @@ warpTrig(point   const p2,
 
     point e1p1, e1p2, e1p3;
     point e2p1, e2p2, e2p3;
-    line lp, le;
-    line l1, l2, l3;
-    double d1, d2, d3;
-    int i;
+    unsigned int i;
 
     /* find in which triangle p2 lies */
-    for (i = 0; i < nTri; i++) {
-        if (insidetri (&tri2s[i], p2))
+    for (i = 0; i < nTri; ++i) {
+        if (insidetri(&tri2s[i], p2))
             break;
     }
 
@@ -1142,25 +1178,33 @@ warpTrig(point   const p2,
         *p1P = makepoint(0.0, 0.0);
     else {
         /* where in triangle is point */
-        d1 = fabs (p2.x - tri2s[i].p1.x) + fabs (p2.y - tri2s[i].p1.y);
-        d2 = fabs (p2.x - tri2s[i].p2.x) + fabs (p2.y - tri2s[i].p2.y);
-        d3 = fabs (p2.x - tri2s[i].p3.x) + fabs (p2.y - tri2s[i].p3.y);
-
-        /* line through p1 and p intersecting with edge p2-p3 */
-        lp = makeline(tri2s[i].p1, p2);
-        le = makeline(tri2s[i].p2, tri2s[i].p3);
-        intersect (&lp, &le, &e2p1);
-
-        /* line through p2 and p intersecting with edge p3-p1 */
-        lp = makeline(tri2s[i].p2, p2);
-        le = makeline(tri2s[i].p3, tri2s[i].p1);
-        intersect (&lp, &le, &e2p2);
+        double const d1 =
+            fabs (p2.x - tri2s[i].p1.x) + fabs (p2.y - tri2s[i].p1.y);
+        double const d2 =
+            fabs (p2.x - tri2s[i].p2.x) + fabs (p2.y - tri2s[i].p2.y);
+        double const d3 =
+            fabs (p2.x - tri2s[i].p3.x) + fabs (p2.y - tri2s[i].p3.y);
+
+        {
+            /* line through p1 and p intersecting with edge p2-p3 */
+            line const lp = makeline(tri2s[i].p1, p2);
+            line const le = makeline(tri2s[i].p2, tri2s[i].p3);
+            findIntersection(&lp, &le, NULL, &e2p1);
+        }
 
-        /* line through p3 and p intersecting with edge p1-p2 */
-        lp = makeline(tri2s[i].p3, p2);
-        le = makeline(tri2s[i].p1, tri2s[i].p2);
-        intersect (&lp, &le, &e2p3);
+        {
+            /* line through p2 and p intersecting with edge p3-p1 */
+            line const lp = makeline(tri2s[i].p2, p2);
+            line const le = makeline(tri2s[i].p3, tri2s[i].p1);
+            findIntersection(&lp, &le, NULL, &e2p2);
+        }
 
+        {
+            /* line through p3 and p intersecting with edge p1-p2 */
+            line const lp = makeline(tri2s[i].p3, p2);
+            line const le = makeline(tri2s[i].p1, tri2s[i].p2);
+            findIntersection(&lp, &le, NULL, &e2p3);
+        }
         /* map target control points to source control points */
         e1p1.x = tri1s[i].p2.x
             + (e2p1.x - tri2s[i].p2.x)/(tri2s[i].p3.x - tri2s[i].p2.x)
@@ -1181,17 +1225,19 @@ warpTrig(point   const p2,
             + (e2p3.y - tri2s[i].p1.y)/(tri2s[i].p2.y - tri2s[i].p1.y)
             * (tri1s[i].p2.y - tri1s[i].p1.y);
 
-        /* intersect grid lines in source */
-        l1 = makeline(tri1s[i].p1, e1p1);
-        l2 = makeline(tri1s[i].p2, e1p2);
-        l3 = makeline(tri1s[i].p3, e1p3);
-
-        if ((d1 < d2) && (d1 < d3))
-            intersect (&l2, &l3, p1P);
-        else if (d2 < d3)
-            intersect (&l1, &l3, p1P);
-        else
-            intersect (&l1, &l2, p1P);
+        {
+            /* intersect grid lines in source */
+            line const l1 = makeline(tri1s[i].p1, e1p1);
+            line const l2 = makeline(tri1s[i].p2, e1p2);
+            line const l3 = makeline(tri1s[i].p3, e1p3);
+
+            if ((d1 < d2) && (d1 < d3))
+                findIntersection(&l2, &l3, NULL, p1P);
+            else if (d2 < d3)
+                findIntersection(&l1, &l3, NULL, p1P);
+            else
+                findIntersection(&l1, &l2, NULL, p1P);
+        }
     }
 }
 
@@ -1208,8 +1254,6 @@ warpQuad(point   const p2,
     point c2tl, c2tr, c2bl, c2br;
     point e1t, e1b, e1l, e1r;
     point e2t, e2b, e2l, e2r;
-    line l2t, l2b, l2l, l2r;
-    line lh, lv;
 
     c1tl = quad1.tl;
     c1tr = quad1.tr;
@@ -1221,24 +1265,27 @@ warpQuad(point   const p2,
     c2bl = quad2.bl;
     c2br = quad2.br;
 
-    l2t = makeline(c2tl, c2tr);
-    l2b = makeline(c2bl, c2br);
-    l2l = makeline(c2tl, c2bl);
-    l2r = makeline(c2tr, c2br);
-
-    /* find intersections of lines through control points */
-    intersect (&l2t, &l2b, &h2);
-    intersect (&l2l, &l2r, &v2);
-
-    /* find intersections of axes through P with control point box */
-    lv = makeline(p2, v2);
-    intersect (&l2t, &lv, &e2t);
-    intersect (&l2b, &lv, &e2b);
-
-    lh = makeline(p2, h2);
-    intersect (&l2l, &lh, &e2l);
-    intersect (&l2r, &lh, &e2r);
-
+    {
+        line const l2t = makeline(c2tl, c2tr);
+        line const l2b = makeline(c2bl, c2br);
+        line const l2l = makeline(c2tl, c2bl);
+        line const l2r = makeline(c2tr, c2br);
+
+        /* find intersections of lines through control points */
+        findIntersection(&l2t, &l2b, NULL, &h2);
+        findIntersection(&l2l, &l2r, NULL, &v2);
+
+        {
+            /* find intersections of axes through P with control point box */
+            line const lv = makeline(p2, v2);
+            line const lh = makeline(p2, h2);
+
+            findIntersection(&l2t, &lv, NULL, &e2t);
+            findIntersection(&l2b, &lv, NULL, &e2b);
+            findIntersection(&l2l, &lh, NULL, &e2l);
+            findIntersection(&l2r, &lh, NULL, &e2r);
+        }
+    }
     /* map target control points to source control points */
     e1t.x = c1tl.x + (e2t.x - c2tl.x)/(c2tr.x - c2tl.x) * (c1tr.x - c1tl.x);
     if (c1tl.y == c1tr.y)
@@ -1268,16 +1315,18 @@ warpQuad(point   const p2,
             = c1tr.x + (e2r.y - c2tr.y)/(c2br.y - c2tr.y) * (c1br.x - c1tr.x);
     e1r.y = c1tr.y + (e2r.y - c2tr.y)/(c2br.y - c2tr.y) * (c1br.y - c1tr.y);
 
-    /* intersect grid lines in source */
-    lv = makeline(e1t, e1b);
-    lh = makeline(e1l, e1r);
-    intersect (&lh, &lv, p1P);
+    {
+        /* intersect grid lines in source */
+        line const lv = makeline(e1t, e1b);
+        line const lh = makeline(e1l, e1r);
+        findIntersection(&lh, &lv, NULL, p1P);
+    }
 }
 
 
 
 static void
-setGlobalCP(struct cmdlineInfo const cmdline) {
+setGlobalCP(struct CmdlineInfo const cmdline) {
 
     unsigned int i;
 
@@ -1392,7 +1441,7 @@ pix(tuple **     const tuples,
 int
 main(int argc, const char ** const argv) {
 
-    struct cmdlineInfo cmdline;
+    struct CmdlineInfo cmdline;
     FILE * ifP;
     struct pam inpam, outpam;
     tuple ** inTuples;
@@ -1405,8 +1454,6 @@ main(int argc, const char ** const argv) {
 
     setGlobalCP(cmdline);
 
-    srand(cmdline.randseedSpec ? cmdline.randseed : pm_randseed());
-
     ifP = pm_openr(cmdline.fileName);
 
     inTuples = pnm_readpam(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type));
@@ -1421,7 +1468,8 @@ main(int argc, const char ** const argv) {
     makeAllWhite(&outpam, outTuples);
 
     if (cmdline.tri)
-        prepTrig(inpam.width, inpam.height);
+        prepTrig(inpam.width, inpam.height,
+                 cmdline.randomseedSpec, cmdline.randomseed);
     if (cmdline.quad)
         prepQuad();