Index: src/librt/primitives/sketch/sketch.c
===================================================================
--- src/librt/primitives/sketch/sketch.c	(revision 63578)
+++ src/librt/primitives/sketch/sketch.c	(working copy)
@@ -905,22 +905,83 @@
     return myret;
 }
 
+/**
+ * Given a sketch, bounds, and precision for rt_sketch_centroid, check
+ * if the precision is large enough (if the sample size is small
+ * enough) to intersect every curve of the given sketch.
+ *
+ * Returns -
+ * 0 precision is sufficiently large
+ * !0 precision is too small
+ */
+int
+rt_sketch_centroid_check_precision(const struct rt_sketch_internal *skt,
+				   fastf_t precision,
+				   fastf_t bounds[4])
+{
+    fastf_t x_inc, y_inc, min_inc;
+    fastf_t min_size = INFINITY;
+    unsigned int i;
+    const struct rt_curve *crv = &skt->curve;
+    x_inc = (bounds[1]-bounds[0])/precision;
+    y_inc = (bounds[3]-bounds[2])/precision;
+    min_inc = x_inc < y_inc ? x_inc : y_inc;
+    for (i = 0; i < crv->count; i++) {
+	point2d_t size;
+	const struct line_seg *lsg;
+	const struct carc_seg *csg;
+	const struct nurb_seg *nsg;
+	const struct bezier_seg *bsg;
+	const uint32_t *lng;
+	int j;
+	point2d_t min_pt, max_pt;
+
+	lng = (uint32_t *)crv->segment[i];
+
+	switch (*lng) {
+	    case CURVE_LSEG_MAGIC:
+		lsg = (struct line_seg *)lng;
+		V2SUB2(size, skt->verts[lsg->end], skt->verts[lsg->start]);
+		V_MIN(min_size, MAGNITUDE2(size));
+		break;
+	    case CURVE_CARC_MAGIC:
+		csg = (struct carc_seg *)lng;
+		V2SUB2(size, skt->verts[csg->end], skt->verts[csg->start]);
+		V_MIN(min_size, MAGNITUDE2(size));
+		break;
+ 	    case CURVE_NURB_MAGIC:
+		nsg = (struct nurb_seg *)lng;
+		for (j = 0; j < nsg->c_size; j++) {
+		    V2MINMAX(min_pt, max_pt, skt->verts[nsg->ctl_points[j]]);
+		}
+		V2SUB2(size, max_pt, min_pt);
+		V_MIN(min_size, MAGNITUDE2(size));
+		break;
+     	    case CURVE_BEZIER_MAGIC:
+		bsg = (struct bezier_seg *)lng;
+		for (j = 0; j <= bsg->degree; j++) {
+		    V2MINMAX(min_pt, max_pt, skt->verts[bsg->ctl_points[j]]);
+		}
+		V2SUB2(size, max_pt, min_pt);
+		V_MIN(min_size, MAGNITUDE2(size));
+		break;
+	}
+    }
+    return (min_size < min_inc);
+}
+
 void
-rt_sketch_centroid(point_t *cent, const struct rt_db_internal *ip)
+rt_sketch_centroid_with_precision(point_t *cent,
+				  struct rt_sketch_internal *skt,
+				  fastf_t precision,
+				  fastf_t bounds[4])
 {
-    const int PRECISION = 1000;
-    fastf_t bounds[4];
     fastf_t x_inc, y_inc;
     fastf_t i, j;
     long n = 0;
-    struct rt_sketch_internal *sketch_ip = (struct rt_sketch_internal *)ip->idb_ptr;
-    RT_SKETCH_CK_MAGIC(sketch_ip);
 
-    VSETALL(*cent, 0.0);
-
-    rt_sketch_bounds(sketch_ip, bounds);
-    x_inc = (bounds[1]-bounds[0])/PRECISION;
-    y_inc = (bounds[3]-bounds[2])/PRECISION;
+    x_inc = (bounds[1]-bounds[0])/precision;
+    y_inc = (bounds[3]-bounds[2])/precision;
     for (i = bounds[0]; i < bounds[1]; i += x_inc) {
 	for (j = bounds[2]; j < bounds[3]; j += y_inc) {
 	    point2d_t pt;
@@ -927,7 +988,7 @@
 	    point_t pt3d;
 	    V2SET(pt, i, j);
 	    VSET(pt3d, i, j, 0);
-	    if (rt_sketch_contains(sketch_ip, pt)) {
+	    if (rt_sketch_contains(skt, pt)) {
 		VADD2(*cent, *cent, pt3d);
 		n++;
 	    }
@@ -936,7 +997,43 @@
     VSCALE(*cent, *cent, 1.0 / (fastf_t)n);
 }
 
+void
+rt_sketch_centroid(point_t *cent, const struct rt_db_internal *ip)
+{
+    /* With BN_TOL_DIST instead, even relatively simple sketches can
+     * bounce back and forth between points < 0.005 apart but > 0.0005
+     * for a long time.  Since calculating is very computationally
+     * intensive, using this TOLERANCE instead makes the computation
+     * finish significantly faster without a huge loss of accuracy
+     */
+    const fastf_t TOLERANCE = 0.005;
+    fastf_t precision = 1024;
+    fastf_t bounds[4];
+    struct rt_sketch_internal *sketch_ip = (struct rt_sketch_internal *)ip->idb_ptr;
+    point_t current_cent, previous_cent;
+    point_t difference = {INFINITY, INFINITY, INFINITY};
+    RT_SKETCH_CK_MAGIC(sketch_ip);
 
+    VSETALL(*cent, 0.0);
+    VSETALL(current_cent, 0.0);
+    VSETALL(previous_cent, 0.0);
+
+    rt_sketch_bounds(sketch_ip, bounds);
+    while (rt_sketch_centroid_check_precision(sketch_ip, precision, bounds)) {
+	precision *= 2;
+    }
+
+    while (!NEAR_ZERO(MAGNITUDE(difference), TOLERANCE)) {
+	VMOVE(previous_cent, current_cent);
+	rt_sketch_centroid_with_precision(&current_cent, sketch_ip, precision, bounds);
+	precision *= M_SQRT2;
+	VSUB2(difference, current_cent, previous_cent);
+    }
+
+    VMOVE(*cent, current_cent);
+}
+
+
 /**
  * Returns -
  * -1 failure
