Revision: 55956
http://sourceforge.net/p/brlcad/code/55956
Author: phoenixyjll
Date: 2013-07-04 05:55:31 +0000 (Thu, 04 Jul 2013)
Log Message:
-----------
Clean up and split the two steps (intersecting bounding boxes and triangular
approximation).
Modified Paths:
--------------
brlcad/trunk/src/libbrep/intersect.cpp
Modified: brlcad/trunk/src/libbrep/intersect.cpp
===================================================================
--- brlcad/trunk/src/libbrep/intersect.cpp 2013-07-04 05:17:06 UTC (rev
55955)
+++ brlcad/trunk/src/libbrep/intersect.cpp 2013-07-04 05:55:31 UTC (rev
55956)
@@ -677,7 +677,7 @@
if (intersection_tolerance <= 0.0)
intersection_tolerance = CCI_DEFAULT_TOLERANCE;
- if (overlap_tolerance <= 0.0)
+ if (overlap_tolerance < intersection_tolerance)
overlap_tolerance = 2*intersection_tolerance;
double t1_tolerance = intersection_tolerance;
double t2_tolerance = intersection_tolerance;
@@ -1134,7 +1134,7 @@
if (intersection_tolerance <= 0.0)
intersection_tolerance = CSI_DEFAULT_TOLERANCE;
- if (overlap_tolerance <= 0.0)
+ if (overlap_tolerance < intersection_tolerance)
overlap_tolerance = 2*intersection_tolerance;
double t_tolerance = intersection_tolerance;
double u_tolerance = intersection_tolerance;
@@ -1727,8 +1727,8 @@
const ON_Surface* surfB,
ON_ClassArray<ON_SSX_EVENT>& x,
double intersection_tolerance,
- double UNUSED(overlap_tolerance),
- double UNUSED(fitting_tolerance),
+ double overlap_tolerance,
+ double fitting_tolerance,
const ON_Interval* surfaceA_udomain,
const ON_Interval* surfaceA_vdomain,
const ON_Interval* surfaceB_udomain,
@@ -1738,176 +1738,166 @@
return -1;
}
+ if (intersection_tolerance <= 0.0)
+ intersection_tolerance = SSI_DEFAULT_TOLERANCE;
+ if (overlap_tolerance < intersection_tolerance)
+ overlap_tolerance = 2*intersection_tolerance;
+ if (fitting_tolerance < intersection_tolerance)
+ fitting_tolerance = intersection_tolerance;
+
/* First step: Initialize the first two Subsurface.
* It's just like getting the root of the surface tree.
*/
typedef std::vector<std::pair<Subsurface*, Subsurface*> > NodePairs;
- NodePairs nodepairs;
- Subsurface *rootA = new Subsurface(), *rootB = new Subsurface();
- build_surface_root(surfA, surfaceA_udomain, surfaceA_vdomain, *rootA);
- build_surface_root(surfB, surfaceB_udomain, surfaceB_vdomain, *rootB);
- nodepairs.push_back(std::make_pair(rootA, rootB));
+ NodePairs candidates, next_candidates;
+ Subsurface rootA, rootB;
+ build_surface_root(surfA, surfaceA_udomain, surfaceA_vdomain, rootA);
+ build_surface_root(surfB, surfaceB_udomain, surfaceB_vdomain, rootB);
+ if (rootA.Intersect(rootB, intersection_tolerance))
+ candidates.push_back(std::make_pair(&rootA, &rootB));
+
ON_3dPointArray curvept;
ON_2dPointArray curveuv, curvest;
- int bbox_count = 0;
- /* Second step: calculate the intersection of the bounding boxes, using
- * trigonal approximation.
+ /* Second step: calculate the intersection of the bounding boxes.
* Only the children of intersecting b-box pairs need to be considered.
* The children will be generated only when they are needed, using the
* method of splitting a NURBS surface.
* So finally only a small subset of the surface tree is created.
*/
for (int h = 0; h <= MAX_SSI_DEPTH; h++) {
- if (nodepairs.empty())
+ if (candidates.empty())
break;
- NodePairs tmp_pairs;
- if (h) {
- for (NodePairs::iterator i = nodepairs.begin(); i !=
nodepairs.end(); i++) {
- int ret1 = (*i).first->Split();
- int ret2 = (*i).second->Split();
- if (ret1) {
- if (ret2) {
- /* both splits failed */
- tmp_pairs.push_back(*i);
- h = MAX_SSI_DEPTH;
- } else {
- /* the first failed */
- for (int j = 0; j < 4; j++)
- tmp_pairs.push_back(std::make_pair((*i).first,
(*i).second->m_children[j]));
- }
- } else {
- if (ret2) {
- /* the second failed */
- for (int j = 0; j < 4; j++)
-
tmp_pairs.push_back(std::make_pair((*i).first->m_children[j], (*i).second));
- } else {
- /* both success */
- for (int j = 0; j < 4; j++)
- for (int k = 0; k < 4; k++)
-
tmp_pairs.push_back(std::make_pair((*i).first->m_children[j],
(*i).second->m_children[k]));
- }
- }
+ next_candidates.clear();
+ for (NodePairs::iterator i = candidates.begin(); i != candidates.end();
i++) {
+ std::vector<Subsurface*> splittedA, splittedB;
+ if ((*i).first->m_isplanar || (*i).first->Split() != 0) {
+ splittedA.push_back((*i).first);
+ } else {
+ for (int j = 0; j < 4; j++)
+ splittedA.push_back((*i).first->m_children[j]);
}
- } else {
- tmp_pairs = nodepairs;
+ if ((*i).second->m_isplanar || (*i).second->Split() != 0) {
+ splittedB.push_back((*i).second);
+ } else {
+ for (int j = 0; j < 4; j++)
+ splittedB.push_back((*i).second->m_children[j]);
+ }
+ for (unsigned int j = 0; j < splittedA.size(); j++)
+ for (unsigned int k = 0; k < splittedB.size(); k++)
+ if (splittedB[k]->Intersect(*splittedA[j],
intersection_tolerance))
+ next_candidates.push_back(std::make_pair(splittedA[j],
splittedB[k]));
}
- nodepairs.clear();
- for (NodePairs::iterator i = tmp_pairs.begin(); i != tmp_pairs.end();
i++) {
- ON_BoundingBox box_intersect;
- if (i->first->Intersect(*(i->second), intersection_tolerance,
&box_intersect)) {
- if (h == MAX_SSI_DEPTH) {
- // We have arrived at the bottom of the trees.
- // Get an estimate of the intersection point lying on the
intersection curve
+ candidates = next_candidates;
+ }
+ bu_log("We get %d intersection bounding boxes.\n", candidates.size());
- // Get the corners of each surface sub-patch inside the
bounding-box.
- ON_3dPoint cornerA[4], cornerB[4];
- double u_min = (*i).first->m_u.Min(), u_max =
(*i).first->m_u.Max();
- double v_min = (*i).first->m_v.Min(), v_max =
(*i).first->m_v.Max();
- double s_min = (*i).second->m_u.Min(), s_max =
(*i).second->m_u.Max();
- double t_min = (*i).second->m_v.Min(), t_max =
(*i).second->m_v.Max();
- cornerA[0] = surfA->PointAt(u_min, v_min);
- cornerA[1] = surfA->PointAt(u_min, v_max);
- cornerA[2] = surfA->PointAt(u_max, v_min);
- cornerA[3] = surfA->PointAt(u_max, v_max);
- cornerB[0] = surfB->PointAt(s_min, t_min);
- cornerB[1] = surfB->PointAt(s_min, t_max);
- cornerB[2] = surfB->PointAt(s_max, t_min);
- cornerB[3] = surfB->PointAt(s_max, t_max);
+ /* Third step: get the intersection points using trangonal approximation.
*/
+ for (NodePairs::iterator i = candidates.begin(); i != candidates.end();
i++) {
+ // We have arrived at the bottom of the trees.
+ // Get an estimate of the intersection point lying on the intersection
curve
- /* We approximate each surface sub-patch inside the
bounding-box with two
- * triangles that share an edge.
- * The intersection of the surface sub-patches is
approximated as the
- * intersection of triangles.
- */
- struct Triangle triangle[4];
- triangle[0].CreateFromPoints(cornerA[0], cornerA[1],
cornerA[2]);
- triangle[1].CreateFromPoints(cornerA[1], cornerA[2],
cornerA[3]);
- triangle[2].CreateFromPoints(cornerB[0], cornerB[1],
cornerB[2]);
- triangle[3].CreateFromPoints(cornerB[1], cornerB[2],
cornerB[3]);
- bool is_intersect[4];
- ON_3dPoint intersect_center[4];
- is_intersect[0] = triangle_intersection(triangle[0],
triangle[2], intersect_center[0]);
- is_intersect[1] = triangle_intersection(triangle[0],
triangle[3], intersect_center[1]);
- is_intersect[2] = triangle_intersection(triangle[1],
triangle[2], intersect_center[2]);
- is_intersect[3] = triangle_intersection(triangle[1],
triangle[3], intersect_center[3]);
+ // Get the corners of each surface sub-patch inside the bounding-box.
+ ON_BoundingBox box_intersect;
+ i->first->Intersect(*(i->second), intersection_tolerance,
&box_intersect);
+ ON_3dPoint cornerA[4], cornerB[4];
+ double u_min = (*i).first->m_u.Min(), u_max = (*i).first->m_u.Max();
+ double v_min = (*i).first->m_v.Min(), v_max = (*i).first->m_v.Max();
+ double s_min = (*i).second->m_u.Min(), s_max = (*i).second->m_u.Max();
+ double t_min = (*i).second->m_v.Min(), t_max = (*i).second->m_v.Max();
+ cornerA[0] = surfA->PointAt(u_min, v_min);
+ cornerA[1] = surfA->PointAt(u_min, v_max);
+ cornerA[2] = surfA->PointAt(u_max, v_min);
+ cornerA[3] = surfA->PointAt(u_max, v_max);
+ cornerB[0] = surfB->PointAt(s_min, t_min);
+ cornerB[1] = surfB->PointAt(s_min, t_max);
+ cornerB[2] = surfB->PointAt(s_max, t_min);
+ cornerB[3] = surfB->PointAt(s_max, t_max);
- // Calculate the intersection centers' uv (st) coordinates.
- ON_3dPoint bcoor[8];
- ON_2dPoint uv[4]/*surfA*/, st[4]/*surfB*/;
- if (is_intersect[0]) {
- bcoor[0] =
triangle[0].BarycentricCoordinate(intersect_center[0]);
- bcoor[1] =
triangle[2].BarycentricCoordinate(intersect_center[0]);
- uv[0].x = bcoor[0].x*u_min + bcoor[0].y*u_min +
bcoor[0].z*u_max;
- uv[0].y = bcoor[0].x*v_min + bcoor[0].y*v_max +
bcoor[0].z*v_min;
- st[0].x = bcoor[1].x*s_min + bcoor[1].y*s_min +
bcoor[1].z*s_max;
- st[0].y = bcoor[1].x*t_min + bcoor[1].y*t_max +
bcoor[1].z*t_min;
- }
- if (is_intersect[1]) {
- bcoor[2] =
triangle[0].BarycentricCoordinate(intersect_center[1]);
- bcoor[3] =
triangle[3].BarycentricCoordinate(intersect_center[1]);
- uv[1].x = bcoor[2].x*u_min + bcoor[2].y*u_min +
bcoor[2].z*u_max;
- uv[1].y = bcoor[2].x*v_min + bcoor[2].y*v_max +
bcoor[2].z*v_min;
- st[1].x = bcoor[3].x*s_min + bcoor[3].y*s_max +
bcoor[3].z*s_max;
- st[1].y = bcoor[3].x*t_max + bcoor[3].y*t_min +
bcoor[3].z*t_max;
- }
- if (is_intersect[2]) {
- bcoor[4] =
triangle[1].BarycentricCoordinate(intersect_center[2]);
- bcoor[5] =
triangle[2].BarycentricCoordinate(intersect_center[2]);
- uv[2].x = bcoor[4].x*u_min + bcoor[4].y*u_max +
bcoor[4].z*u_max;
- uv[2].y = bcoor[4].x*v_max + bcoor[4].y*v_min +
bcoor[4].z*v_max;
- st[2].x = bcoor[5].x*s_min + bcoor[5].y*s_min +
bcoor[5].z*s_max;
- st[2].y = bcoor[5].x*t_min + bcoor[5].y*t_max +
bcoor[5].z*t_min;
- }
- if (is_intersect[3]) {
- bcoor[6] =
triangle[1].BarycentricCoordinate(intersect_center[3]);
- bcoor[7] =
triangle[3].BarycentricCoordinate(intersect_center[3]);
- uv[3].x = bcoor[6].x*u_min + bcoor[6].y*u_max +
bcoor[6].z*u_max;
- uv[3].y = bcoor[6].x*v_max + bcoor[6].y*v_min +
bcoor[6].z*v_max;
- st[3].x = bcoor[7].x*s_min + bcoor[7].y*s_max +
bcoor[7].z*s_max;
- st[3].y = bcoor[7].x*t_max + bcoor[7].y*t_min +
bcoor[7].z*t_max;
- }
+ /* We approximate each surface sub-patch inside the bounding-box with
two
+ * triangles that share an edge.
+ * The intersection of the surface sub-patches is approximated as the
+ * intersection of triangles.
+ */
+ struct Triangle triangle[4];
+ triangle[0].CreateFromPoints(cornerA[0], cornerA[1], cornerA[2]);
+ triangle[1].CreateFromPoints(cornerA[1], cornerA[2], cornerA[3]);
+ triangle[2].CreateFromPoints(cornerB[0], cornerB[1], cornerB[2]);
+ triangle[3].CreateFromPoints(cornerB[1], cornerB[2], cornerB[3]);
+ bool is_intersect[4];
+ ON_3dPoint intersect_center[4];
+ is_intersect[0] = triangle_intersection(triangle[0], triangle[2],
intersect_center[0]);
+ is_intersect[1] = triangle_intersection(triangle[0], triangle[3],
intersect_center[1]);
+ is_intersect[2] = triangle_intersection(triangle[1], triangle[2],
intersect_center[2]);
+ is_intersect[3] = triangle_intersection(triangle[1], triangle[3],
intersect_center[3]);
- // The centroid of these intersection centers is the
- // intersection point we want.
- int num_intersects = 0;
- ON_3dPoint average(0.0, 0.0, 0.0);
- ON_2dPoint avguv(0.0, 0.0), avgst(0.0, 0.0);
- for (int j = 0; j < 4; j++) {
- if (is_intersect[j]) {
- average += intersect_center[j];
- avguv += uv[j];
- avgst += st[j];
- num_intersects++;
- }
- }
- if (num_intersects) {
- average /= num_intersects;
- avguv /= num_intersects;
- avgst /= num_intersects;
- if (box_intersect.IsPointIn(average)) {
- curvept.Append(average);
- curveuv.Append(avguv);
- curvest.Append(avgst);
- }
- }
- bbox_count++;
- } else {
- nodepairs.push_back(*i);
- }
+ // Calculate the intersection centers' uv (st) coordinates.
+ ON_3dPoint bcoor[8];
+ ON_2dPoint uv[4]/*surfA*/, st[4]/*surfB*/;
+ if (is_intersect[0]) {
+ bcoor[0] = triangle[0].BarycentricCoordinate(intersect_center[0]);
+ bcoor[1] = triangle[2].BarycentricCoordinate(intersect_center[0]);
+ uv[0].x = bcoor[0].x*u_min + bcoor[0].y*u_min + bcoor[0].z*u_max;
+ uv[0].y = bcoor[0].x*v_min + bcoor[0].y*v_max + bcoor[0].z*v_min;
+ st[0].x = bcoor[1].x*s_min + bcoor[1].y*s_min + bcoor[1].z*s_max;
+ st[0].y = bcoor[1].x*t_min + bcoor[1].y*t_max + bcoor[1].z*t_min;
+ }
+ if (is_intersect[1]) {
+ bcoor[2] = triangle[0].BarycentricCoordinate(intersect_center[1]);
+ bcoor[3] = triangle[3].BarycentricCoordinate(intersect_center[1]);
+ uv[1].x = bcoor[2].x*u_min + bcoor[2].y*u_min + bcoor[2].z*u_max;
+ uv[1].y = bcoor[2].x*v_min + bcoor[2].y*v_max + bcoor[2].z*v_min;
+ st[1].x = bcoor[3].x*s_min + bcoor[3].y*s_max + bcoor[3].z*s_max;
+ st[1].y = bcoor[3].x*t_max + bcoor[3].y*t_min + bcoor[3].z*t_max;
+ }
+ if (is_intersect[2]) {
+ bcoor[4] = triangle[1].BarycentricCoordinate(intersect_center[2]);
+ bcoor[5] = triangle[2].BarycentricCoordinate(intersect_center[2]);
+ uv[2].x = bcoor[4].x*u_min + bcoor[4].y*u_max + bcoor[4].z*u_max;
+ uv[2].y = bcoor[4].x*v_max + bcoor[4].y*v_min + bcoor[4].z*v_max;
+ st[2].x = bcoor[5].x*s_min + bcoor[5].y*s_min + bcoor[5].z*s_max;
+ st[2].y = bcoor[5].x*t_min + bcoor[5].y*t_max + bcoor[5].z*t_min;
+ }
+ if (is_intersect[3]) {
+ bcoor[6] = triangle[1].BarycentricCoordinate(intersect_center[3]);
+ bcoor[7] = triangle[3].BarycentricCoordinate(intersect_center[3]);
+ uv[3].x = bcoor[6].x*u_min + bcoor[6].y*u_max + bcoor[6].z*u_max;
+ uv[3].y = bcoor[6].x*v_max + bcoor[6].y*v_min + bcoor[6].z*v_max;
+ st[3].x = bcoor[7].x*s_min + bcoor[7].y*s_max + bcoor[7].z*s_max;
+ st[3].y = bcoor[7].x*t_max + bcoor[7].y*t_min + bcoor[7].z*t_max;
+ }
+
+ // The centroid of these intersection centers is the
+ // intersection point we want.
+ int num_intersects = 0;
+ ON_3dPoint average(0.0, 0.0, 0.0);
+ ON_2dPoint avguv(0.0, 0.0), avgst(0.0, 0.0);
+ for (int j = 0; j < 4; j++) {
+ if (is_intersect[j]) {
+ average += intersect_center[j];
+ avguv += uv[j];
+ avgst += st[j];
+ num_intersects++;
}
}
+ if (num_intersects) {
+ average /= num_intersects;
+ avguv /= num_intersects;
+ avgst /= num_intersects;
+ if (box_intersect.IsPointIn(average)) {
+ curvept.Append(average);
+ curveuv.Append(avguv);
+ curvest.Append(avgst);
+ }
+ }
}
- bu_log("We get %d intersection bounding boxes.\n", bbox_count);
bu_log("%d points on the intersection curves.\n", curvept.Count());
if (!curvept.Count()) {
- delete rootA;
- delete rootB;
return 0;
}
- // Third step: Fit the points in curvept into NURBS curves.
+ // Fourth step: Fit the points in curvept into NURBS curves.
// Here we use polyline approximation.
// TODO: Find a better fitting algorithm unless this is good enough.
@@ -2081,8 +2071,6 @@
bu_free(index, "int");
bu_free(startpt, "int");
bu_free(endpt, "int");
- delete rootA;
- delete rootB;
// Generate ON_SSX_EVENTs
if (intersect3d.Count()) {
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:
Build for Windows Store.
http://p.sf.net/sfu/windows-dev2dev
_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits