Revision: 69085
          http://sourceforge.net/p/brlcad/code/69085
Author:   starseeker
Date:     2016-10-16 21:19:25 +0000 (Sun, 16 Oct 2016)
Log Message:
-----------
merge bezier.c into nurb_bezier.c

Modified Paths:
--------------
    brlcad/trunk/src/librt/CMakeLists.txt
    brlcad/trunk/src/librt/primitives/bspline/nurb_bezier.c

Removed Paths:
-------------
    brlcad/trunk/src/librt/bezier.c

Modified: brlcad/trunk/src/librt/CMakeLists.txt
===================================================================
--- brlcad/trunk/src/librt/CMakeLists.txt       2016-10-16 21:12:51 UTC (rev 
69084)
+++ brlcad/trunk/src/librt/CMakeLists.txt       2016-10-16 21:19:25 UTC (rev 
69085)
@@ -28,7 +28,6 @@
 set(LIBRT_SOURCES
   attributes.c
   bbox.c
-  bezier.c
   binunif/binunif.c
   binunif/db5_bin.c
   bool.c

Deleted: brlcad/trunk/src/librt/bezier.c
===================================================================
--- brlcad/trunk/src/librt/bezier.c     2016-10-16 21:12:51 UTC (rev 69084)
+++ brlcad/trunk/src/librt/bezier.c     2016-10-16 21:19:25 UTC (rev 69085)
@@ -1,464 +0,0 @@
-/*                        B E Z I E R . C
- * BRL-CAD
- *
- * Copyright (c) 2004-2016 United States Government as represented by
- * the U.S. Army Research Laboratory.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this file; see the file named COPYING for more
- * information.
- */
-/** @addtogroup ray */
-/** @{ */
-/** @file librt/bezier.c
- *
- * The following routines are for 2D Bezier curves.
- *
- * The following routines are borrowed from Graphics Gems I, Academic
- * Press, Inc., 1990, Andrew S. Glassner (editor), "A Bezier
- * Curve-based Root-finder", Philip J. Schneider.
- *
- * Modifications have been made for inclusion in BRL-CAD and to
- * generalize the codes for finding intersections with any 2D line
- * rather than just the X-axis.
- */
-
-#include "common.h"
-
-#include "bio.h"
-
-#include "vmath.h"
-#include "nmg.h"
-#include "raytrace.h"
-
-#define SGN(_x) (((_x)<0) ? -1 : 1)
-#define MAXDEPTH 64
-
-/*
- * Count the number of times a Bezier control polygon
- * crosses the ray. This number is >= the number of roots.
- */
-HIDDEN int
-crossing_count(
-    point2d_t *V,              /* 2D Control pts of Bezier curve */
-    int degree,                 /* Degree of Bezier curve */
-    point2d_t ray_start,       /* starting point for ray */
-    point2d_t ray_perp)                /* unit vector perpendicular to ray 
direction */
-{
-    int i;
-    int n_crossings = 0;        /* Number of crossings */
-    int sign, old_sign;         /* Sign of coefficients */
-    point2d_t to_pt;           /* vector from ray start to a control point */
-
-    V2SUB2(to_pt, ray_start, V[0]);
-    sign = old_sign = SGN(V2DOT(to_pt, ray_perp));
-    for (i = 1; i <= degree; i++) {
-       V2SUB2(to_pt, ray_start, V[i]);
-       sign = SGN(V2DOT(to_pt, ray_perp));
-       if (sign != old_sign) n_crossings++;
-       old_sign = sign;
-    }
-
-    return n_crossings;
-}
-
-
-/*
- * Check if the control polygon of a Bezier curve is flat enough for
- * recursive subdivision to bottom out.
- */
-HIDDEN int
-control_polygon_flat_enough(
-    point2d_t *V,              /* Control points */
-    int degree,                        /* Degree of polynomial */
-    fastf_t epsilon)           /* Maximum allowable error */
-{
-    int i;                     /* Index variable */
-    double *distance;          /* Distances from pts to line */
-    double max_distance_above; /* maximum of these */
-    double max_distance_below;
-    double error;              /* Precision of root */
-    double intercept_1,
-       intercept_2,
-       left_intercept,
-       right_intercept;
-    double a, b, c;            /* Coefficients of implicit */
-    /* eqn for line from V[0]-V[deg]*/
-
-    /* Find the perpendicular distance */
-    /* from each interior control point to */
-    /* line connecting V[0] and V[degree] */
-    distance = (double *)bu_malloc((unsigned)(degree + 1) * sizeof(double), 
"control_polygon_flat_enough");
-    {
-       double abSquared;
-
-       /* Derive the implicit equation for line connecting first */
-       /* and last control points */
-       a = V[0][Y] - V[degree][Y];
-       b = V[degree][X] - V[0][X];
-       c = V[0][X] * V[degree][Y] - V[degree][X] * V[0][Y];
-
-       abSquared = 1.0 / ((a * a) + (b * b));
-
-       for (i = 1; i < degree; i++) {
-           /* Compute distance from each of the points to that line */
-           distance[i] = a * V[i][X] + b * V[i][Y] + c;
-           if (distance[i] > 0.0) {
-               distance[i] = (distance[i] * distance[i]) * abSquared;
-           }
-           if (distance[i] < 0.0) {
-               distance[i] = -((distance[i] * distance[i]) * abSquared);
-           }
-       }
-    }
-
-
-    /* Find the largest distance */
-    max_distance_above = 0.0;
-    max_distance_below = 0.0;
-    for (i = 1; i < degree; i++) {
-       if (distance[i] < 0.0) {
-           max_distance_below = FMIN(max_distance_below, distance[i]);
-       }
-       if (distance[i] > 0.0) {
-           max_distance_above = FMAX(max_distance_above, distance[i]);
-       }
-    }
-    bu_free((char *)distance, "control_polygon_flat_enough");
-
-    {
-       double det, dInv;
-       double a1, b1, c1, a2, b2, c2;
-
-       if (NEAR_ZERO(a, VUNITIZE_TOL)) {
-           a1 = 1.0;
-           b1 = 1.0;
-           c1 = 0.0;
-       } else {
-           /* Implicit equation for zero line */
-           a1 = 0.0;
-           b1 = 1.0;
-           c1 = 0.0;
-       }
-
-       /* Implicit equation for "above" line */
-       a2 = a;
-       b2 = b;
-       c2 = c + max_distance_above;
-
-       det = a1 * b2 - a2 * b1;
-       dInv = 1.0/det;
-
-       intercept_1 = (b1 * c2 - b2 * c1) * dInv;
-
-       /* Implicit equation for "below" line */
-       a2 = a;
-       b2 = b;
-       c2 = c + max_distance_below;
-
-       det = a1 * b2 - a2 * b1;
-       dInv = 1.0/det;
-
-       intercept_2 = (b1 * c2 - b2 * c1) * dInv;
-    }
-
-    /* Compute intercepts of bounding box */
-    left_intercept = FMIN(intercept_1, intercept_2);
-    right_intercept = FMAX(intercept_1, intercept_2);
-
-    error = 0.5 * (right_intercept-left_intercept);
-
-    if (error < epsilon) {
-       return 1;
-    } else {
-       return 0;
-    }
-}
-
-
-void
-bezier(
-    point2d_t *V,              /* Control pts */
-    int degree,                        /* Degree of bezier curve */
-    double t,                  /* Parameter value [0..1]       */
-    point2d_t *Left,           /* RETURN left half ctl pts */
-    point2d_t *Right,          /* RETURN right half ctl pts */
-    point2d_t eval_pt,         /* RETURN evaluated point */
-    point2d_t normal)          /* RETURN unit normal at evaluated pt (may be 
NULL) */
-{
-    int i, j;                  /* Index variables */
-    fastf_t len;
-    point2d_t tangent;
-    point2d_t **Vtemp;
-
-
-    Vtemp = (point2d_t **)bu_calloc(degree+1, sizeof(point2d_t *), "bezier: 
Vtemp array");
-    for (i=0; i<=degree; i++)
-       Vtemp[i] = (point2d_t *)bu_calloc(degree+1, sizeof(point2d_t),
-                                         "bezier: Vtemp[i] array");
-    /* Copy control points */
-    for (j =0; j <= degree; j++) {
-       V2MOVE(Vtemp[0][j], V[j]);
-    }
-
-    /* Triangle computation */
-    for (i = 1; i <= degree; i++) {
-       for (j =0; j <= degree - i; j++) {
-           Vtemp[i][j][X] =
-               (1.0 - t) * Vtemp[i-1][j][X] + t * Vtemp[i-1][j+1][X];
-           Vtemp[i][j][Y] =
-               (1.0 - t) * Vtemp[i-1][j][Y] + t * Vtemp[i-1][j+1][Y];
-       }
-    }
-
-    if (Left != NULL) {
-       for (j = 0; j <= degree; j++) {
-           V2MOVE(Left[j], Vtemp[j][0]);
-       }
-    }
-    if (Right != NULL) {
-       for (j = 0; j <= degree; j++) {
-           V2MOVE(Right[j], Vtemp[degree-j][j]);
-       }
-    }
-
-    V2MOVE(eval_pt, Vtemp[degree][0]);
-
-    if (normal) {
-       V2SUB2(tangent, Vtemp[degree-1][1], Vtemp[degree-1][0]);
-       normal[X] = tangent[Y];
-       normal[Y] = -tangent[X];
-       len = sqrt(MAG2SQ(normal));
-       normal[X] /= len;
-       normal[Y] /= len;
-    }
-
-    for (i=0; i<=degree; i++)
-       bu_free((char *)Vtemp[i], "bezier: Vtemp[i]");
-    bu_free((char *)Vtemp, "bezier: Vtemp");
-
-    return;
-}
-
-
-/*
- * Compute intersection of chord from first control point to last
- * with ray.
- *
- * Returns :
- *
- * 0 - no intersection
- * 1 - found an intersection
- *
- * intercept - contains calculated intercept
- */
-HIDDEN int
-compute_x_intercept(
-    point2d_t *V,               /* Control points */
-    int degree,                 /* Degree of curve */
-    point2d_t ray_start,       /* starting point of ray */
-    point2d_t ray_dir,         /* unit ray direction */
-    point2d_t intercept,       /* calculated intercept point */
-    point2d_t normal)          /* calculated unit normal at intercept */
-{
-    fastf_t beta;
-    fastf_t denom;
-    fastf_t len;
-    point2d_t seg_line;
-
-    denom = (V[degree][X] - V[0][X]) * ray_dir[Y] -
-       (V[degree][Y] - V[0][Y]) * ray_dir[X];
-
-    if (ZERO(denom))
-       return 0;
-
-    beta = (V[0][Y] * ray_dir[X] - V[0][X] * ray_dir[Y] +
-           ray_start[X] * ray_dir[Y] - ray_start[Y] * ray_dir[X]) / denom;
-
-    if (beta < 0.0 || beta > 1.0)
-       return 0;
-
-    V2SUB2(seg_line, V[degree], V[0]);
-    V2JOIN1(intercept, V[0], beta, seg_line);
-
-    /* calculate normal */
-    normal[X] = seg_line[Y];
-    normal[Y] = -seg_line[X];
-    len = sqrt(MAG2SQ(seg_line));
-    normal[X] /= len;
-    normal[Y] /= len;
-
-    return 1;
-}
-
-
-int
-bezier_roots(
-    point2d_t *w,               /* The control points */
-    int degree,                /* The degree of the polynomial */
-    point2d_t **intercept,     /* list of intersections found */
-    point2d_t **normal,                /* corresponding normals */
-    point2d_t ray_start,       /* starting point of ray */
-    point2d_t ray_dir,         /* Unit direction for ray */
-    point2d_t ray_perp,                /* Unit vector normal to ray_dir */
-    int depth,                 /* The depth of the recursion */
-    fastf_t epsilon)           /* maximum allowable error */
-{
-    int i;
-    point2d_t *Left,            /* New left and right */
-       *Right;                 /* control polygons */
-    int left_count,             /* Solution count from */
-       right_count;            /* children */
-    point2d_t *left_t,          /* Solutions from kids */
-       *right_t;
-    point2d_t *left_n,         /* normals from kids */
-       *right_n;
-    int total_count;
-    point2d_t eval_pt;
-
-    switch (crossing_count(w, degree, ray_start, ray_perp)) {
-       case 0 : {
-           /* No solutions here */
-           return 0;
-       }
-       case 1 : {
-           /* Unique solution */
-           /* Stop recursion when the tree is deep enough */
-           /* if deep enough, return 1 solution at midpoint */
-           if (depth >= MAXDEPTH) {
-               BU_ALLOC(*intercept, point2d_t);
-               BU_ALLOC(*normal, point2d_t);
-               bezier(w, degree, 0.5, NULL, NULL, *intercept[0], *normal[0]);
-               return 1;
-           }
-           if (control_polygon_flat_enough(w, degree, epsilon)) {
-               BU_ALLOC(*intercept, point2d_t);
-               BU_ALLOC(*normal, point2d_t);
-               if (!compute_x_intercept(w, degree, ray_start, ray_dir, 
*intercept[0], *normal[0])) {
-                   bu_free((char *)(*intercept), "bezier_roots: no solution");
-                   bu_free((char *)(*normal), "bezier_roots: no solution");
-                   return 0;
-               }
-               return 1;
-           }
-           break;
-       }
-    }
-
-    /* Otherwise, solve recursively after */
-    /* subdividing control polygon */
-    Left = (point2d_t *)bu_calloc(degree+1, sizeof(point2d_t), "bezier_roots: 
Left");
-    Right = (point2d_t *)bu_calloc(degree+1, sizeof(point2d_t), "bezier_roots: 
Right");
-    bezier(w, degree, 0.5, Left, Right, eval_pt, NULL);
-
-    left_count  = bezier_roots(Left,  degree, &left_t, &left_n, ray_start, 
ray_dir, ray_perp, depth+1, epsilon);
-    right_count = bezier_roots(Right, degree, &right_t, &right_n, ray_start, 
ray_dir, ray_perp, depth+1, epsilon);
-
-    total_count = left_count + right_count;
-
-    bu_free((char *)Left, "bezier_roots: Left");
-    bu_free((char *)Right, "bezier_roots: Right");
-    if (total_count) {
-       *intercept = (point2d_t *)bu_calloc(total_count, sizeof(point2d_t),
-                                           "bezier_roots: roots compilation");
-       *normal = (point2d_t *)bu_calloc(total_count, sizeof(point2d_t),
-                                        "bezier_roots: normal compilation");
-    }
-
-    /* Gather solutions together */
-    for (i = 0; i < left_count; i++) {
-       V2MOVE((*intercept)[i], left_t[i]);
-       V2MOVE((*normal)[i], left_n[i]);
-    }
-    for (i = 0; i < right_count; i++) {
-       V2MOVE((*intercept)[i+left_count], right_t[i]);
-       V2MOVE((*normal)[i+left_count], right_n[i]);
-    }
-
-    if (left_count) {
-       bu_free((char *)left_t, "Left roots");
-       bu_free((char *)left_n, "Left normals");
-    }
-    if (right_count) {
-       bu_free((char *)right_t, "Right roots");
-       bu_free((char *)right_n, "Right normals");
-    }
-
-    /* Send back total number of solutions */
-    return total_count;
-}
-
-
-struct bezier_2d_list *
-bezier_subdivide(struct bezier_2d_list *bezier_in, int degree, fastf_t 
epsilon, int depth)
-{
-    struct bezier_2d_list *bz_l, *bz_r, *new_head;
-    struct bezier_2d_list *left_rtrn, *rt_rtrn;
-    point2d_t pt;
-
-    /* create a new head */
-    BU_ALLOC(new_head, struct bezier_2d_list);
-
-    BU_LIST_INIT(&new_head->l);
-    if (depth >= MAXDEPTH) {
-       BU_LIST_APPEND(&new_head->l, &bezier_in->l);
-       return new_head;
-    }
-
-    if (control_polygon_flat_enough(bezier_in->ctl, degree, epsilon)) {
-       BU_LIST_APPEND(&new_head->l, &bezier_in->l);
-       return new_head;
-    }
-
-    /* allocate memory for left and right curves */
-    BU_ALLOC(bz_l, struct bezier_2d_list);
-    BU_LIST_INIT(&bz_l->l);
-    BU_ALLOC(bz_r, struct bezier_2d_list);
-    BU_LIST_INIT(&bz_r->l);
-    bz_l->ctl = (point2d_t *)bu_calloc(degree + 1, sizeof(point2d_t),
-                                      "bezier_subdivide: bz_l->ctl");
-    bz_r->ctl = (point2d_t *)bu_calloc(degree + 1, sizeof(point2d_t),
-                                      "bezier_subdivide: bz_r->ctl");
-
-    /* subdivide at t = 0.5 */
-    bezier(bezier_in->ctl, degree, 0.5, bz_l->ctl, bz_r->ctl, pt, NULL);
-
-    /* eliminate original */
-    BU_LIST_DEQUEUE(&bezier_in->l);
-    bu_free((char *)bezier_in->ctl, "bezier_subdivide: bezier_in->ctl");
-    bu_free((char *)bezier_in, "bezier_subdivide: bezier_in");
-
-    /* recurse on left curve */
-    left_rtrn = bezier_subdivide(bz_l, degree, epsilon, depth+1);
-
-    /* recurse on right curve */
-    rt_rtrn = bezier_subdivide(bz_r, degree, epsilon, depth+1);
-
-    BU_LIST_APPEND_LIST(&new_head->l, &left_rtrn->l);
-    BU_LIST_APPEND_LIST(&new_head->l, &rt_rtrn->l);
-    bu_free((char *)left_rtrn, "bezier_subdivide: left_rtrn (head)");
-    bu_free((char *)rt_rtrn, "bezier_subdivide: rt_rtrn (head)");
-
-    return new_head;
-}
-
-
-/** @} */
-/*
- * Local Variables:
- * mode: C
- * tab-width: 8
- * indent-tabs-mode: t
- * c-file-style: "stroustrup"
- * End:
- * ex: shiftwidth=4 tabstop=8
- */

Modified: brlcad/trunk/src/librt/primitives/bspline/nurb_bezier.c
===================================================================
--- brlcad/trunk/src/librt/primitives/bspline/nurb_bezier.c     2016-10-16 
21:12:51 UTC (rev 69084)
+++ brlcad/trunk/src/librt/primitives/bspline/nurb_bezier.c     2016-10-16 
21:19:25 UTC (rev 69085)
@@ -33,9 +33,422 @@
 
 #include "vmath.h"
 #include "bu/list.h"
+#include "bu/malloc.h"
 #include "nmg.h"
 
 
+#define SGN(_x) (((_x)<0) ? -1 : 1)
+#define MAXDEPTH 64
+
+/*
+ * Count the number of times a Bezier control polygon
+ * crosses the ray. This number is >= the number of roots.
+ */
+HIDDEN int
+crossing_count(
+    point2d_t *V,              /* 2D Control pts of Bezier curve */
+    int degree,                 /* Degree of Bezier curve */
+    point2d_t ray_start,       /* starting point for ray */
+    point2d_t ray_perp)                /* unit vector perpendicular to ray 
direction */
+{
+    int i;
+    int n_crossings = 0;        /* Number of crossings */
+    int sign, old_sign;         /* Sign of coefficients */
+    point2d_t to_pt;           /* vector from ray start to a control point */
+
+    V2SUB2(to_pt, ray_start, V[0]);
+    sign = old_sign = SGN(V2DOT(to_pt, ray_perp));
+    for (i = 1; i <= degree; i++) {
+       V2SUB2(to_pt, ray_start, V[i]);
+       sign = SGN(V2DOT(to_pt, ray_perp));
+       if (sign != old_sign) n_crossings++;
+       old_sign = sign;
+    }
+
+    return n_crossings;
+}
+
+
+/*
+ * Check if the control polygon of a Bezier curve is flat enough for
+ * recursive subdivision to bottom out.
+ */
+HIDDEN int
+control_polygon_flat_enough(
+    point2d_t *V,              /* Control points */
+    int degree,                        /* Degree of polynomial */
+    fastf_t epsilon)           /* Maximum allowable error */
+{
+    int i;                     /* Index variable */
+    double *distance;          /* Distances from pts to line */
+    double max_distance_above; /* maximum of these */
+    double max_distance_below;
+    double error;              /* Precision of root */
+    double intercept_1,
+       intercept_2,
+       left_intercept,
+       right_intercept;
+    double a, b, c;            /* Coefficients of implicit */
+    /* eqn for line from V[0]-V[deg]*/
+
+    /* Find the perpendicular distance */
+    /* from each interior control point to */
+    /* line connecting V[0] and V[degree] */
+    distance = (double *)bu_malloc((unsigned)(degree + 1) * sizeof(double), 
"control_polygon_flat_enough");
+    {
+       double abSquared;
+
+       /* Derive the implicit equation for line connecting first */
+       /* and last control points */
+       a = V[0][Y] - V[degree][Y];
+       b = V[degree][X] - V[0][X];
+       c = V[0][X] * V[degree][Y] - V[degree][X] * V[0][Y];
+
+       abSquared = 1.0 / ((a * a) + (b * b));
+
+       for (i = 1; i < degree; i++) {
+           /* Compute distance from each of the points to that line */
+           distance[i] = a * V[i][X] + b * V[i][Y] + c;
+           if (distance[i] > 0.0) {
+               distance[i] = (distance[i] * distance[i]) * abSquared;
+           }
+           if (distance[i] < 0.0) {
+               distance[i] = -((distance[i] * distance[i]) * abSquared);
+           }
+       }
+    }
+
+
+    /* Find the largest distance */
+    max_distance_above = 0.0;
+    max_distance_below = 0.0;
+    for (i = 1; i < degree; i++) {
+       if (distance[i] < 0.0) {
+           max_distance_below = FMIN(max_distance_below, distance[i]);
+       }
+       if (distance[i] > 0.0) {
+           max_distance_above = FMAX(max_distance_above, distance[i]);
+       }
+    }
+    bu_free((char *)distance, "control_polygon_flat_enough");
+
+    {
+       double det, dInv;
+       double a1, b1, c1, a2, b2, c2;
+
+       if (NEAR_ZERO(a, VUNITIZE_TOL)) {
+           a1 = 1.0;
+           b1 = 1.0;
+           c1 = 0.0;
+       } else {
+           /* Implicit equation for zero line */
+           a1 = 0.0;
+           b1 = 1.0;
+           c1 = 0.0;
+       }
+
+       /* Implicit equation for "above" line */
+       a2 = a;
+       b2 = b;
+       c2 = c + max_distance_above;
+
+       det = a1 * b2 - a2 * b1;
+       dInv = 1.0/det;
+
+       intercept_1 = (b1 * c2 - b2 * c1) * dInv;
+
+       /* Implicit equation for "below" line */
+       a2 = a;
+       b2 = b;
+       c2 = c + max_distance_below;
+
+       det = a1 * b2 - a2 * b1;
+       dInv = 1.0/det;
+
+       intercept_2 = (b1 * c2 - b2 * c1) * dInv;
+    }
+
+    /* Compute intercepts of bounding box */
+    left_intercept = FMIN(intercept_1, intercept_2);
+    right_intercept = FMAX(intercept_1, intercept_2);
+
+    error = 0.5 * (right_intercept-left_intercept);
+
+    if (error < epsilon) {
+       return 1;
+    } else {
+       return 0;
+    }
+}
+
+
+void
+bezier(
+    point2d_t *V,              /* Control pts */
+    int degree,                        /* Degree of bezier curve */
+    double t,                  /* Parameter value [0..1]       */
+    point2d_t *Left,           /* RETURN left half ctl pts */
+    point2d_t *Right,          /* RETURN right half ctl pts */
+    point2d_t eval_pt,         /* RETURN evaluated point */
+    point2d_t normal)          /* RETURN unit normal at evaluated pt (may be 
NULL) */
+{
+    int i, j;                  /* Index variables */
+    fastf_t len;
+    point2d_t tangent;
+    point2d_t **Vtemp;
+
+
+    Vtemp = (point2d_t **)bu_calloc(degree+1, sizeof(point2d_t *), "bezier: 
Vtemp array");
+    for (i=0; i<=degree; i++)
+       Vtemp[i] = (point2d_t *)bu_calloc(degree+1, sizeof(point2d_t),
+                                         "bezier: Vtemp[i] array");
+    /* Copy control points */
+    for (j =0; j <= degree; j++) {
+       V2MOVE(Vtemp[0][j], V[j]);
+    }
+
+    /* Triangle computation */
+    for (i = 1; i <= degree; i++) {
+       for (j =0; j <= degree - i; j++) {
+           Vtemp[i][j][X] =
+               (1.0 - t) * Vtemp[i-1][j][X] + t * Vtemp[i-1][j+1][X];
+           Vtemp[i][j][Y] =
+               (1.0 - t) * Vtemp[i-1][j][Y] + t * Vtemp[i-1][j+1][Y];
+       }
+    }
+
+    if (Left != NULL) {
+       for (j = 0; j <= degree; j++) {
+           V2MOVE(Left[j], Vtemp[j][0]);
+       }
+    }
+    if (Right != NULL) {
+       for (j = 0; j <= degree; j++) {
+           V2MOVE(Right[j], Vtemp[degree-j][j]);
+       }
+    }
+
+    V2MOVE(eval_pt, Vtemp[degree][0]);
+
+    if (normal) {
+       V2SUB2(tangent, Vtemp[degree-1][1], Vtemp[degree-1][0]);
+       normal[X] = tangent[Y];
+       normal[Y] = -tangent[X];
+       len = sqrt(MAG2SQ(normal));
+       normal[X] /= len;
+       normal[Y] /= len;
+    }
+
+    for (i=0; i<=degree; i++)
+       bu_free((char *)Vtemp[i], "bezier: Vtemp[i]");
+    bu_free((char *)Vtemp, "bezier: Vtemp");
+
+    return;
+}
+
+
+/*
+ * Compute intersection of chord from first control point to last
+ * with ray.
+ *
+ * Returns :
+ *
+ * 0 - no intersection
+ * 1 - found an intersection
+ *
+ * intercept - contains calculated intercept
+ */
+HIDDEN int
+compute_x_intercept(
+    point2d_t *V,               /* Control points */
+    int degree,                 /* Degree of curve */
+    point2d_t ray_start,       /* starting point of ray */
+    point2d_t ray_dir,         /* unit ray direction */
+    point2d_t intercept,       /* calculated intercept point */
+    point2d_t normal)          /* calculated unit normal at intercept */
+{
+    fastf_t beta;
+    fastf_t denom;
+    fastf_t len;
+    point2d_t seg_line;
+
+    denom = (V[degree][X] - V[0][X]) * ray_dir[Y] -
+       (V[degree][Y] - V[0][Y]) * ray_dir[X];
+
+    if (ZERO(denom))
+       return 0;
+
+    beta = (V[0][Y] * ray_dir[X] - V[0][X] * ray_dir[Y] +
+           ray_start[X] * ray_dir[Y] - ray_start[Y] * ray_dir[X]) / denom;
+
+    if (beta < 0.0 || beta > 1.0)
+       return 0;
+
+    V2SUB2(seg_line, V[degree], V[0]);
+    V2JOIN1(intercept, V[0], beta, seg_line);
+
+    /* calculate normal */
+    normal[X] = seg_line[Y];
+    normal[Y] = -seg_line[X];
+    len = sqrt(MAG2SQ(seg_line));
+    normal[X] /= len;
+    normal[Y] /= len;
+
+    return 1;
+}
+
+
+int
+bezier_roots(
+    point2d_t *w,               /* The control points */
+    int degree,                /* The degree of the polynomial */
+    point2d_t **intercept,     /* list of intersections found */
+    point2d_t **normal,                /* corresponding normals */
+    point2d_t ray_start,       /* starting point of ray */
+    point2d_t ray_dir,         /* Unit direction for ray */
+    point2d_t ray_perp,                /* Unit vector normal to ray_dir */
+    int depth,                 /* The depth of the recursion */
+    fastf_t epsilon)           /* maximum allowable error */
+{
+    int i;
+    point2d_t *Left,            /* New left and right */
+       *Right;                 /* control polygons */
+    int left_count,             /* Solution count from */
+       right_count;            /* children */
+    point2d_t *left_t,          /* Solutions from kids */
+       *right_t;
+    point2d_t *left_n,         /* normals from kids */
+       *right_n;
+    int total_count;
+    point2d_t eval_pt;
+
+    switch (crossing_count(w, degree, ray_start, ray_perp)) {
+       case 0 : {
+           /* No solutions here */
+           return 0;
+       }
+       case 1 : {
+           /* Unique solution */
+           /* Stop recursion when the tree is deep enough */
+           /* if deep enough, return 1 solution at midpoint */
+           if (depth >= MAXDEPTH) {
+               BU_ALLOC(*intercept, point2d_t);
+               BU_ALLOC(*normal, point2d_t);
+               bezier(w, degree, 0.5, NULL, NULL, *intercept[0], *normal[0]);
+               return 1;
+           }
+           if (control_polygon_flat_enough(w, degree, epsilon)) {
+               BU_ALLOC(*intercept, point2d_t);
+               BU_ALLOC(*normal, point2d_t);
+               if (!compute_x_intercept(w, degree, ray_start, ray_dir, 
*intercept[0], *normal[0])) {
+                   bu_free((char *)(*intercept), "bezier_roots: no solution");
+                   bu_free((char *)(*normal), "bezier_roots: no solution");
+                   return 0;
+               }
+               return 1;
+           }
+           break;
+       }
+    }
+
+    /* Otherwise, solve recursively after */
+    /* subdividing control polygon */
+    Left = (point2d_t *)bu_calloc(degree+1, sizeof(point2d_t), "bezier_roots: 
Left");
+    Right = (point2d_t *)bu_calloc(degree+1, sizeof(point2d_t), "bezier_roots: 
Right");
+    bezier(w, degree, 0.5, Left, Right, eval_pt, NULL);
+
+    left_count  = bezier_roots(Left,  degree, &left_t, &left_n, ray_start, 
ray_dir, ray_perp, depth+1, epsilon);
+    right_count = bezier_roots(Right, degree, &right_t, &right_n, ray_start, 
ray_dir, ray_perp, depth+1, epsilon);
+
+    total_count = left_count + right_count;
+
+    bu_free((char *)Left, "bezier_roots: Left");
+    bu_free((char *)Right, "bezier_roots: Right");
+    if (total_count) {
+       *intercept = (point2d_t *)bu_calloc(total_count, sizeof(point2d_t),
+                                           "bezier_roots: roots compilation");
+       *normal = (point2d_t *)bu_calloc(total_count, sizeof(point2d_t),
+                                        "bezier_roots: normal compilation");
+    }
+
+    /* Gather solutions together */
+    for (i = 0; i < left_count; i++) {
+       V2MOVE((*intercept)[i], left_t[i]);
+       V2MOVE((*normal)[i], left_n[i]);
+    }
+    for (i = 0; i < right_count; i++) {
+       V2MOVE((*intercept)[i+left_count], right_t[i]);
+       V2MOVE((*normal)[i+left_count], right_n[i]);
+    }
+
+    if (left_count) {
+       bu_free((char *)left_t, "Left roots");
+       bu_free((char *)left_n, "Left normals");
+    }
+    if (right_count) {
+       bu_free((char *)right_t, "Right roots");
+       bu_free((char *)right_n, "Right normals");
+    }
+
+    /* Send back total number of solutions */
+    return total_count;
+}
+
+
+struct bezier_2d_list *
+bezier_subdivide(struct bezier_2d_list *bezier_in, int degree, fastf_t 
epsilon, int depth)
+{
+    struct bezier_2d_list *bz_l, *bz_r, *new_head;
+    struct bezier_2d_list *left_rtrn, *rt_rtrn;
+    point2d_t pt;
+
+    /* create a new head */
+    BU_ALLOC(new_head, struct bezier_2d_list);
+
+    BU_LIST_INIT(&new_head->l);
+    if (depth >= MAXDEPTH) {
+       BU_LIST_APPEND(&new_head->l, &bezier_in->l);
+       return new_head;
+    }
+
+    if (control_polygon_flat_enough(bezier_in->ctl, degree, epsilon)) {
+       BU_LIST_APPEND(&new_head->l, &bezier_in->l);
+       return new_head;
+    }
+
+    /* allocate memory for left and right curves */
+    BU_ALLOC(bz_l, struct bezier_2d_list);
+    BU_LIST_INIT(&bz_l->l);
+    BU_ALLOC(bz_r, struct bezier_2d_list);
+    BU_LIST_INIT(&bz_r->l);
+    bz_l->ctl = (point2d_t *)bu_calloc(degree + 1, sizeof(point2d_t),
+                                      "bezier_subdivide: bz_l->ctl");
+    bz_r->ctl = (point2d_t *)bu_calloc(degree + 1, sizeof(point2d_t),
+                                      "bezier_subdivide: bz_r->ctl");
+
+    /* subdivide at t = 0.5 */
+    bezier(bezier_in->ctl, degree, 0.5, bz_l->ctl, bz_r->ctl, pt, NULL);
+
+    /* eliminate original */
+    BU_LIST_DEQUEUE(&bezier_in->l);
+    bu_free((char *)bezier_in->ctl, "bezier_subdivide: bezier_in->ctl");
+    bu_free((char *)bezier_in, "bezier_subdivide: bezier_in");
+
+    /* recurse on left curve */
+    left_rtrn = bezier_subdivide(bz_l, degree, epsilon, depth+1);
+
+    /* recurse on right curve */
+    rt_rtrn = bezier_subdivide(bz_r, degree, epsilon, depth+1);
+
+    BU_LIST_APPEND_LIST(&new_head->l, &left_rtrn->l);
+    BU_LIST_APPEND_LIST(&new_head->l, &rt_rtrn->l);
+    bu_free((char *)left_rtrn, "bezier_subdivide: left_rtrn (head)");
+    bu_free((char *)rt_rtrn, "bezier_subdivide: rt_rtrn (head)");
+
+    return new_head;
+}
+
+
 /**
  * Given a single snurb, if it is in Bezier form, duplicate the snurb,
  * and enqueue it on the bezier_hd list.  If the original snurb is NOT

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
BRL-CAD Source Commits mailing list
brlcad-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to