Index: src/librt/primitives/nmg/nmg.c
===================================================================
--- src/librt/primitives/nmg/nmg.c	(Revision 58500)
+++ src/librt/primitives/nmg/nmg.c	(Arbeitskopie)
@@ -3116,6 +3116,132 @@
 }
 
 
+struct sortable_point
+{
+    point_t pt;
+    plane_t *cmp_plane;
+};
+
+
+/* qsort helper function, used to sort points into
+ * counter-clockwise order */
+HIDDEN int
+ccw(const void *x, const void *y)
+{
+    vect_t tmp;
+    const struct sortable_point *x1 = x;
+    const struct sortable_point *y1 = y;
+    VCROSS(tmp,(fastf_t *)x1->pt, (fastf_t *)y1->pt);
+    return VDOT(*x1->cmp_plane, tmp);
+}
+
+
+void
+rt_nmg_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 model *m;
+    struct nmgregion* r;
+
+    /*Iterate through all regions and shells */
+    m = (struct model *)ip->idb_ptr;
+    r = BU_LIST_FIRST(nmgregion, &m->r_hd);
+    while(BU_LIST_NOT_HEAD(r, &m->r_hd)) {
+	struct shell* s;
+
+	s = BU_LIST_FIRST(shell, &r->s_hd);
+	while(BU_LIST_NOT_HEAD(s, &r->s_hd)){
+	    struct bu_ptbl nmg_faces;
+	    unsigned int num_faces, i, j, k, l;
+	    struct poly_face *faces;
+
+	    /*get faces of this shell*/
+	    nmg_face_tabulate(&nmg_faces, &s->l.magic);
+	    num_faces = BU_PTBL_LEN(&nmg_faces);
+	    faces = (struct poly_face *)bu_calloc(num_faces, sizeof(struct poly_face), "nmg_surf_area: faces");
+
+	    for(i = 0; i < num_faces; i++) {
+		struct face *f;
+		f = (struct face *)BU_PTBL_GET(&nmg_faces, i);
+		HMOVE(faces[i].plane_eqn, f->g.plane_p->N);
+		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(num_faces - 1, sizeof(point_t), "nmg_surf_area: pts");
+	    }
+	    /* find all vertices */
+	    for (i = 0; i < num_faces - 2; i++) {
+		for (j = i + 1; j < num_faces - 1; j++) {
+		    for (k = j + 1; k < num_faces; k++) {
+			point_t pt;
+			int keep_point = 1;
+			if (bn_mkpoint_3planes(pt, faces[i].plane_eqn, faces[j].plane_eqn, faces[k].plane_eqn) < 0) {
+			    continue;
+			}
+			/* discard pt if it is outside the arbn */
+			for (l = 0; l < num_faces; l++) {
+			    if (l == i || l == j || l == k) {
+				continue;
+			    }
+			    if (DIST_PT_PLANE(pt, faces[l].plane_eqn) >  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 < num_faces; i++) {
+		vect_t tmp, tot = VINIT_ZERO;
+		struct sortable_point *sort_points;
+		sort_points = (struct sortable_point *)bu_calloc(faces[i].npts, sizeof(struct sortable_point), "nmg_surf_area: sort_points");
+
+		for(j = 0; j < faces[i].npts; i++) {
+		    sort_points[j].pt[0] =  faces[i].pts[j][0];
+		    sort_points[j].pt[1] =  faces[i].pts[j][1];
+		    sort_points[j].pt[2] =  faces[i].pts[j][2];
+		    sort_points[j].cmp_plane = &faces[i].plane_eqn;
+		}
+		/* sort points */
+		qsort(sort_points, faces[i].npts, sizeof(struct sortable_point), ccw);
+		for(j = 0; j < faces[i].npts; i++) {
+		    faces[i].pts[j][0] = sort_points[j].pt[0];
+		    faces[i].pts[j][1] = sort_points[j].pt[1];
+		    faces[i].pts[j][2] = sort_points[j].pt[2];
+		}
+		bu_free((char *)sort_points, "nmg_surf_area: sort_points");
+		/* 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);
+		}
+		*area += (fabs(VDOT(faces[i].plane_eqn, tot)) * 0.5);
+	    }
+	    for (i = 0; i < num_faces; i++) {
+		bu_free((char *)faces[i].pts, "rt_nmg_surf_area: pts");
+	    }
+	    bu_free((char *)faces, "rt_nmg_surf_area: faces");
+	    s = BU_LIST_PNEXT(shell, s);
+	}
+	r = BU_LIST_PNEXT(nmgregion, r);
+    }
+}
+
 /*
  * Local Variables:
  * mode: C
Index: src/librt/primitives/table.c
===================================================================
--- src/librt/primitives/table.c	(Revision 58500)
+++ src/librt/primitives/table.c	(Arbeitskopie)
@@ -688,11 +688,11 @@
 	rt_nmg_params,
 	rt_nmg_bbox,
 	NULL,
+	rt_nmg_surf_area,
 	NULL,
 	NULL,
 	NULL,
 	NULL,
-	NULL,
 	NULL
     },
 
