Index: src/librt/primitives/arbn/arbn.c
===================================================================
--- src/librt/primitives/arbn/arbn.c	(Revision 58708)
+++ src/librt/primitives/arbn/arbn.c	(Arbeitskopie)
@@ -1325,7 +1325,20 @@
 }
 
 
+/* contains information used to analyze a polygonal face */
+struct poly_face
+{
+    char label[5];
+    size_t npts;
+    point_t *pts;
+    plane_t plane_eqn;
+    fastf_t area;
+    fastf_t vol_pyramid;
+    point_t cent_pyramid;
+    point_t cent;
+};
 
+
 /* plane used by ccw to compare 2 points */
 static plane_t *cmp_plane = NULL;
 
@@ -1344,15 +1357,6 @@
 void
 rt_arbn_surf_area(fastf_t *area, const struct rt_db_internal *ip)
 {
-    /* contains information used to analyze a polygonal face */
-    struct poly_face
-    {
-	char label[5];
-	size_t npts;
-	point_t *pts;
-	plane_t plane_eqn;
-	fastf_t area;
-    };
     struct poly_face *faces;
     struct rt_arbn_internal *aip = (struct rt_arbn_internal *)ip->idb_ptr;
     size_t i, j, k, l;
@@ -1414,6 +1418,147 @@
 }
 
 
+void
+rt_arbn_centroid(point_t *cent, const struct rt_db_internal *ip)
+{
+    struct poly_face *faces;
+    struct rt_arbn_internal *aip = (struct rt_arbn_internal *)ip->idb_ptr;
+    size_t i, j, k, l;
+    point_t arbit_point = VINIT_ZERO;
+    fastf_t volume;
+
+    *cent[0] = 0.0;
+    *cent[1] = 0.0;
+    *cent[2] = 0.0;
+
+    if(cent == NULL)
+	return;
+
+    /* allocate array of face structs */
+    faces = (struct poly_face *)bu_calloc(aip->neqn, sizeof(struct poly_face), "arbn_centroid: faces");
+    for (i = 0; i < aip->neqn; i++) {
+	HMOVE(faces[i].plane_eqn, aip->eqn[i]);
+	VUNITIZE(faces[i].plane_eqn);
+	/* allocate array of pt structs, max number of verts per faces = (# of faces) - 1 */
+	faces[i].pts = (point_t *)bu_calloc(aip->neqn - 1, sizeof(point_t), "arbn_centroid: pts");
+    }
+
+    /* find all vertices */
+    for (i = 0; i < aip->neqn - 2; i++) {
+    for (j = i + 1; j < aip->neqn - 1; j++) {
+	for (k = j + 1; k < aip->neqn; k++) {
+	    point_t pt;
+	    int keep_point = 1;
+	    if (bn_mkpoint_3planes(pt, aip->eqn[i], aip->eqn[j], aip->eqn[k]) < 0) {
+		continue;
+	    }
+	    /* discard pt if it is outside the arbn */
+	    for (l = 0; l < aip->neqn; l++) {
+		if (l == i || l == j || l == k) {
+		    continue;
+		}
+		if (DIST_PT_PLANE(pt, aip->eqn[l]) >  BN_TOL_DIST) {
+		    keep_point = 0;
+		    break;
+		}
+	    }
+	    /* found a good point, add it to each of the intersecting faces */
+	    if (keep_point) {
+		VMOVE((faces[i]).pts[(faces[i]).npts], (pt)); (faces[i]).npts++;
+		VMOVE((faces[j]).pts[(faces[j]).npts], (pt)); (faces[j]).npts++;
+		VMOVE((faces[k]).pts[(faces[k]).npts], (pt)); (faces[k]).npts++;
+	    }
+	}
+    }
+    }
+    for (i = 0; i < aip->neqn; i++){
+	fastf_t x_0, x_1, y_0, y_1, z_0, z_1, a, signedArea = 0.0;
+	/* sort points */
+	cmp_plane = &faces[i].plane_eqn;
+	qsort(faces[i].pts, faces[i].npts, sizeof(point_t), ccw);
+	cmp_plane = NULL;
+	/* Calculate Centroid projection for face for x-y-plane */
+	for (j = 0; j < faces[i].npts-1; j++){
+	    x_0 = faces[i].pts[j][0];
+	    y_0 = faces[i].pts[j][1];
+	    x_1 = faces[i].pts[j+1][0];
+	    y_1 = faces[i].pts[j+1][1];
+	    a = x_0 *y_1 - x_1*y_0;
+	    signedArea += a;
+	    faces[i].cent[0] += (x_0 + x_1)*a;
+	    faces[i].cent[1] += (y_0 + y_1)*a;
+	}
+	x_0 = faces[i].pts[j][0];
+	y_0 = faces[i].pts[j][1];
+	x_1 = faces[i].pts[0][0];
+	y_1 = faces[i].pts[0][1];
+	a = x_0 *y_1 - x_1*y_0;
+	signedArea += a;
+	faces[i].cent[0] += (x_0 + x_1)*a;
+	faces[i].cent[1] += (y_0 + y_1)*a;
+
+	signedArea *= 0.5;
+	faces[i].cent[0] /= (6.0*signedArea);
+	faces[i].cent[1] /= (6.0*signedArea);
+
+	/* calculate Centroid projection for face for x-z-plane */
+
+	signedArea = 0.0;
+	for (j = 0; j < faces[i].npts-1; j++){
+	    x_0 = faces[i].pts[j][0];
+	    z_0 = faces[i].pts[j][2];
+	    x_1 = faces[i].pts[j+1][0];
+	    z_1 = faces[i].pts[j+1][2];
+	    a = x_0 *z_1 - x_1*z_0;
+	    signedArea += a;
+	    faces[i].cent[2] += (z_0 + z_1)*a;
+	}
+	x_0 = faces[i].pts[j][0];
+	z_0 = faces[i].pts[j][2];
+	x_1 = faces[i].pts[0][0];
+	z_0 = faces[i].pts[0][2];
+	a = x_0 *z_1 - x_1*z_0;
+	signedArea += a;
+	faces[i].cent[2] += (z_0 + z_1)*a;
+
+	signedArea *= 0.5;
+	faces[i].cent[2] /= (6.0*signedArea);
+	VADD2(arbit_point, arbit_point, faces[i].cent);
+
+    }
+    VSCALE(arbit_point, arbit_point, (1/aip->neqn));
+
+    for (i = 0; i < aip->neqn; i++) {
+	vect_t tmp, tot = VINIT_ZERO;
+	/* N-Sided Face - compute area using Green's Theorem */
+	for (j = 0; j < faces[i].npts; j++) {
+	    VCROSS(tmp, faces[i].pts[j], faces[i].pts[j + 1 == faces[i].npts ? 0 : j + 1]);
+	    VADD2(tot, tot, tmp);
+	}
+	faces[i].area = (fabs(VDOT(faces[i].plane_eqn, tot)) * 0.5);
+	/* calculate volume */
+	VSCALE(tmp, faces[i].plane_eqn, faces[i].area);
+	faces[i].vol_pyramid = (VDOT(faces[i].pts[0], tmp)/3);
+	volume += faces[i].vol_pyramid;
+	/*Vector from arbit_point to centroid of face, results in h of pyramid */
+	VSUB2(faces[i].cent_pyramid, faces[i].cent, arbit_point);
+	/*centroid of pyramid is 1/4 up from the bottom */
+	VSCALE(faces[i].cent_pyramid, faces[i].cent_pyramid, 0.75f);
+	/* now cent_pyramid is back in the polyhedron */
+	VADD2(faces[i].cent_pyramid, faces[i].cent_pyramid, arbit_point);
+	/* weight centroid of pyramid by pyramid's volume */
+	VSCALE(faces[i].cent_pyramid, faces[i].cent_pyramid, faces[i].vol_pyramid);
+	/* add cent_pyramid to the centroid of the polyhedron */
+	VADD2(*cent, *cent, faces[i].cent_pyramid);
+    }
+    /* reverse the weighting */
+    VSCALE(*cent, *cent, (1/volume));
+    for (i = 0; i < aip->neqn; i++) {
+	bu_free((char *)faces[i].pts, "rt_arbn_centroid: pts");
+    }
+    bu_free((char *)faces, "rt_arbn_centroid: faces");
+}
+
 /** @} */
 /*
  * Local Variables:
Index: src/librt/primitives/table.c
===================================================================
--- src/librt/primitives/table.c	(Revision 58708)
+++ src/librt/primitives/table.c	(Arbeitskopie)
@@ -824,10 +824,10 @@
 	rt_arbn_bbox,
 	NULL,
 	rt_arbn_surf_area,
+	rt_arbn_centroid,
 	NULL,
 	NULL,
 	NULL,
-	NULL,
 	NULL
     },
 
