[brlcad-commits] SF.net SVN: brlcad:[66403] brlcad/trunk/src/libbrep
Open Source Solid Modeling CAD
Brought to you by:
brlcad
From: <sta...@us...> - 2015-10-06 15:01:45
|
Revision: 66403 http://sourceforge.net/p/brlcad/code/66403 Author: starseeker Date: 2015-10-06 15:01:42 +0000 (Tue, 06 Oct 2015) Log Message: ----------- Turn on sphere logic - untested. Modified Paths: -------------- brlcad/trunk/src/libbrep/CMakeLists.txt brlcad/trunk/src/libbrep/shape_recognition.cpp brlcad/trunk/src/libbrep/shape_recognition.h brlcad/trunk/src/libbrep/shape_recognition_pipeline.cpp brlcad/trunk/src/libbrep/shape_recognition_sphere.cpp Modified: brlcad/trunk/src/libbrep/CMakeLists.txt =================================================================== --- brlcad/trunk/src/libbrep/CMakeLists.txt 2015-10-06 14:12:42 UTC (rev 66402) +++ brlcad/trunk/src/libbrep/CMakeLists.txt 2015-10-06 15:01:42 UTC (rev 66403) @@ -30,6 +30,7 @@ shape_recognition.cpp shape_recognition_cone.cpp shape_recognition_cylinder.cpp + shape_recognition_sphere.cpp shape_recognition_pipeline.cpp shape_recognition_planar.cpp shape_recognition_util.cpp @@ -45,7 +46,6 @@ opennurbs_fit.cpp PullbackCurve.h shape_recognition.h - shape_recognition_sphere.cpp shape_recognition_torus.cpp surface_tree_queue_tests.patch ) Modified: brlcad/trunk/src/libbrep/shape_recognition.cpp =================================================================== --- brlcad/trunk/src/libbrep/shape_recognition.cpp 2015-10-06 14:12:42 UTC (rev 66402) +++ brlcad/trunk/src/libbrep/shape_recognition.cpp 2015-10-06 15:01:42 UTC (rev 66403) @@ -215,6 +215,7 @@ case SURFACE_SPHERICAL_SECTION: case SURFACE_SPHERE: if (ctype != SURFACE_SPHERICAL_SECTION && ctype != SURFACE_SPHERE) return 0; + if (!sph_validate_face(forig, fcand)) return 0; break; default: if (otype != ctype) return 0; Modified: brlcad/trunk/src/libbrep/shape_recognition.h =================================================================== --- brlcad/trunk/src/libbrep/shape_recognition.h 2015-10-06 14:12:42 UTC (rev 66402) +++ brlcad/trunk/src/libbrep/shape_recognition.h 2015-10-06 15:01:42 UTC (rev 66403) @@ -99,9 +99,15 @@ int cone_implicit_plane(const ON_Brep *brep, int lc, int *le, ON_SimpleArray<ON_Plane> *cyl_planes); int cone_implicit_params(struct subbrep_shoal_data *data, ON_SimpleArray<ON_Plane> *cyl_planes, int implicit_plane_ind, int ndc, int *nde, int shoal_nonplanar_face, int nonlinear_edge); +// Sphere specific functionality +int sph_validate_face(const ON_BrepFace *forig, const ON_BrepFace *fcand); +int negative_sphere(const ON_Brep *brep, int face_index, double cyl_tol); +int sph_implicit_plane(const ON_Brep *brep, int ec, int *edges); +int sph_implicit_params(struct subbrep_shoal_data *data, ON_SimpleArray<ON_Plane> *sph_planes, int shoal_nonplanar_face); + #endif /* SHAPE_RECOGNITION_H */ // Local Variables: Modified: brlcad/trunk/src/libbrep/shape_recognition_pipeline.cpp =================================================================== --- brlcad/trunk/src/libbrep/shape_recognition_pipeline.cpp 2015-10-06 14:12:42 UTC (rev 66402) +++ brlcad/trunk/src/libbrep/shape_recognition_pipeline.cpp 2015-10-06 15:01:42 UTC (rev 66403) @@ -25,10 +25,6 @@ // If we hit something we don't handle yet, bail immediately. switch (surface_type) { - case SURFACE_SPHERICAL_SECTION: - case SURFACE_SPHERE: - return 0; - break; case SURFACE_TORUS: return 0; break; @@ -97,6 +93,7 @@ // any.) ON_SimpleArray<ON_Plane> non_linear_edge_planes; std::set<int> linear_edges; + std::set<int> nonlinear_edges; for (c_it = nondegen_edges.begin(); c_it != nondegen_edges.end(); c_it++) { const ON_BrepEdge *edge = &(brep->m_E[*c_it]); ON_Curve *ecv = edge->EdgeCurveOf()->Duplicate(); @@ -128,6 +125,7 @@ delete ecv2; } non_linear_edge_planes.Append(eplane); + nonlinear_edges.insert(*c_it); } else { linear_edges.insert(*c_it); } @@ -154,9 +152,11 @@ } // Find the implicit plane, if there is one - int lc; + int lc, nc; int *le = NULL; + int *ne = NULL; set_to_array(&le, &lc, &linear_edges); + set_to_array(&ne, &nc, &nonlinear_edges); switch (surface_type) { case SURFACE_CYLINDRICAL_SECTION: case SURFACE_CYLINDER: @@ -167,14 +167,15 @@ break; case SURFACE_SPHERICAL_SECTION: case SURFACE_SPHERE: - // TODO Spheres will need their own thing based on walking the non-degenerate - // edge loop and collecting unique planes from sequential coplanar points. + implicit_plane_ind = sph_implicit_plane(brep, nc, ne); break; case SURFACE_TORUS: break; default: break; } + bu_free(le, "nonlinear edges"); + bu_free(ne, "nonlinear edges"); // -1 means no implicit plane, -2 means an error if (implicit_plane_ind == -2) return 0; @@ -275,6 +276,7 @@ break; case SURFACE_SPHERICAL_SECTION: case SURFACE_SPHERE: + need_arbn = sph_implicit_params(data, &shoal_planes, *nonplanar_surfaces.begin()); break; case SURFACE_TORUS: break; Modified: brlcad/trunk/src/libbrep/shape_recognition_sphere.cpp =================================================================== --- brlcad/trunk/src/libbrep/shape_recognition_sphere.cpp 2015-10-06 14:12:42 UTC (rev 66402) +++ brlcad/trunk/src/libbrep/shape_recognition_sphere.cpp 2015-10-06 15:01:42 UTC (rev 66403) @@ -9,59 +9,37 @@ #include "shape_recognition.h" int -subbrep_is_sphere(struct subbrep_object_data *data, fastf_t) +sph_validate_face(const ON_BrepFace *forig, const ON_BrepFace *fcand) { - std::set<int>::iterator f_it; - std::set<int> spherical_surfaces; - // First, check surfaces. If a surface is anything other than a sphere, - // the verdict is no. - for (int i = 0; i < data->faces_cnt; i++) { - int f_ind = data->faces[i]; - int surface_type = (int)GetSurfaceType(data->brep->m_F[f_ind].SurfaceOf(), NULL); - switch (surface_type) { - case SURFACE_SPHERE: - case SURFACE_SPHERICAL_SECTION: - spherical_surfaces.insert(f_ind); - break; - default: - return 0; - break; - } - } + ON_Sphere sorig; + ON_Surface *ssorig = forig->SurfaceOf()->Duplicate(); + ssorig->IsSphere(&sorig, BREP_SPHERICAL_TOL); + delete ssorig; - // Second, check if all spherical surfaces share the same center and radius. - ON_Sphere sph; - ON_Surface *cs = data->brep->m_F[*spherical_surfaces.begin()].SurfaceOf()->Duplicate(); - cs->IsSphere(&sph, BREP_SPHERICAL_TOL); - delete cs; - for (f_it = spherical_surfaces.begin(); f_it != spherical_surfaces.end(); f_it++) { - ON_Sphere f_sph; - ON_Surface *fcs = data->brep->m_F[(*f_it)].SurfaceOf()->Duplicate(); - fcs->IsSphere(&sph, BREP_SPHERICAL_TOL); - delete fcs; - if (f_sph.Center().DistanceTo(sph.Center()) > BREP_SPHERICAL_TOL) return 0; - if (!NEAR_ZERO(f_sph.Radius() - sph.Radius(), BREP_SPHERICAL_TOL)) return 0; - } + ON_Sphere scand; + ON_Surface *sscand = fcand->SurfaceOf()->Duplicate(); + sscand->IsSphere(&scand, BREP_SPHERICAL_TOL); + delete sscand; - // TODO - devise other tests necessary to make sure we have a closed sphere, - // if any are needed. Maybe rule out anything with linear edges? + // Make sure the sphere centers match + if (sorig.Center().DistanceTo(scand.Center()) > VUNITIZE_TOL) return 0; - data->type = SPHERE; + // Make sure the radii match + if (!NEAR_ZERO(sorig.Radius() - scand.Radius(), VUNITIZE_TOL)) return 0; - data->params->bool_op= 'u'; // TODO - not always union - data->params->origin[0] = sph.Center().x; - data->params->origin[1] = sph.Center().y; - data->params->origin[2] = sph.Center().z; - data->params->radius = sph.Radius(); + // TODO - make sure negative/positive status for both faces is the same. return 1; } + /* Return -1 if the sphere face is pointing in toward the center, * 1 if it is pointing out, and 0 if there is some other problem */ int -negative_sphere(struct subbrep_object_data *data, int face_index, double sph_tol) { - const ON_Surface *surf = data->brep->m_F[face_index].SurfaceOf(); +negative_sphere(const ON_Brep *brep, int face_index, double sph_tol) +{ + int ret = 0; + const ON_Surface *surf = brep->m_F[face_index].SurfaceOf(); ON_Sphere sph; ON_Surface *cs = surf->Duplicate(); cs->IsSphere(&sph, sph_tol); @@ -76,270 +54,66 @@ ON_3dVector vect = pnt - sph.Center(); double dotp = ON_DotProduct(vect, normal); - if (NEAR_ZERO(dotp, 0.000001)) return 0; - if (dotp < 0) return -1; - return 1; + if (NEAR_ZERO(dotp, VUNITIZE_TOL)) return 0; + ret = (dotp < 0) ? -1 : 1; + if (brep->m_F[face_index].m_bRev) ret = -1 * ret; + return ret; } int -sphere_csg(struct subbrep_object_data *data, fastf_t sph_tol) +sph_implicit_plane(const ON_Brep *UNUSED(brep), int UNUSED(ec), int *UNUSED(edges)) { - std::set<int> planar_surfaces; - std::set<int> spherical_surfaces; - std::set<int>::iterator f_it; - for (int i = 0; i < data->faces_cnt; i++) { - int f_ind = data->faces[i]; - int surface_type = (int)GetSurfaceType(data->brep->m_F[f_ind].SurfaceOf(), NULL); - switch (surface_type) { - case SURFACE_PLANE: - planar_surfaces.insert(f_ind); - break; - case SURFACE_SPHERE: - case SURFACE_SPHERICAL_SECTION: - spherical_surfaces.insert(f_ind); - break; - default: - std::cout << "what???\n"; - return 0; - break; - } - } - data->params->bool_op = 'u'; // Initialize to union + return -1; +} - // Check for multiple spheres. +int +sph_implicit_params(struct subbrep_shoal_data *data, ON_SimpleArray<ON_Plane> *sph_planes, int shoal_nonplanar_face) +{ ON_Sphere sph; - ON_Surface *cs = data->brep->m_F[*spherical_surfaces.begin()].SurfaceOf()->Duplicate(); + ON_Surface *cs = data->i->brep->m_L[data->shoal_loops[0]].Face()->SurfaceOf()->Duplicate(); cs->IsSphere(&sph, BREP_SPHERICAL_TOL); delete cs; - for (f_it = spherical_surfaces.begin(); f_it != spherical_surfaces.end(); f_it++) { - ON_Sphere f_sph; - ON_Surface *fcs = data->brep->m_F[(*f_it)].SurfaceOf()->Duplicate(); - fcs->IsSphere(&f_sph, BREP_SPHERICAL_TOL); - delete fcs; - if (f_sph.Center().DistanceTo(sph.Center()) > BREP_SPHERICAL_TOL) return 0; - if (!NEAR_ZERO(f_sph.Radius() - sph.Radius(), BREP_SPHERICAL_TOL)) return 0; - } + int need_arbn = ((*sph_planes).Count() == 0) ? 0 : 1; - // Count the number of vertices associated with this subbrep. - std::set<int> verts; - std::set<int>::iterator v_it; - for (int i = 0; i < data->edges_cnt; i++) { - const ON_BrepEdge *edge = &(data->brep->m_E[data->edges[i]]); - verts.insert(edge->Vertex(0)->m_vertex_index); - verts.insert(edge->Vertex(1)->m_vertex_index); - } + // Populate the CSG implicit primitive data + data->params->csg_type = SPHERE; + // Flag the sphere according to the negative or positive status of the + // sphere surface. + data->params->negative = negative_sphere(data->i->brep, shoal_nonplanar_face, BREP_SPHERICAL_TOL); + data->params->bool_op = (data->params->negative == -1) ? '-' : 'u'; - if (verts.size() == 1) { - std::cout << "Only one vertex - probably a circular trim defining a planar face?\n"; - return 0; - } + ON_3dPoint origin = sph.Center(); + BN_VMOVE(data->params->origin, origin); + data->params->radius = sph.Radius(); - if (verts.size() == 2 && data->edges_cnt == 1) { - std::cout << "Two vertices, one edge - probably whole sphere\n"; - return 0; + if (need_arbn) { + ON_3dVector xplus = sph.PointAt(0,0) - sph.Center(); + ON_3dVector yplus = sph.PointAt(M_PI/2,0) - sph.Center(); + ON_3dVector zplus = sph.NorthPole() - sph.Center(); + ON_3dPoint xmax = sph.Center() + 1.01*xplus; + ON_3dPoint xmin = sph.Center() - 1.01*xplus; + ON_3dPoint ymax = sph.Center() + 1.01*yplus; + ON_3dPoint ymin = sph.Center() - 1.01*yplus; + ON_3dPoint zmax = sph.Center() + 1.01*zplus; + ON_3dPoint zmin = sph.Center() - 1.01*zplus; + xplus.Unitize(); + yplus.Unitize(); + zplus.Unitize(); + (*sph_planes).Append(ON_Plane(xmin, -1 * xplus)); + (*sph_planes).Append(ON_Plane(xmax, xplus)); + (*sph_planes).Append(ON_Plane(ymin, -1 * yplus)); + (*sph_planes).Append(ON_Plane(ymax, yplus)); + (*sph_planes).Append(ON_Plane(zmin, -1 * zplus)); + (*sph_planes).Append(ON_Plane(zmax, zplus)); } - if (verts.size() == 2 && data->edges_cnt >= 2) { - std::cout << "Two vertices, more than one edge. Either a two plane situation or two arcs forming a one plane situation\n"; - return 0; - } + return need_arbn; +} - if (verts.size() == 3) { - // Need the planes of any non-linear edges and the plane of the three verts. - ON_SimpleArray<const ON_BrepVertex *> sph_verts(3); - std::set<int> trims; - for (v_it = verts.begin(); v_it != verts.end(); v_it++) { - sph_verts.Append(&(data->brep->m_V[*v_it])); - } - ON_3dPoint p1 = sph_verts[0]->Point(); - ON_3dPoint p2 = sph_verts[1]->Point(); - ON_3dPoint p3 = sph_verts[2]->Point(); - ON_Plane back_plane(p1, p2, p3); - ON_3dPoint bpc = (p1 + p2 + p3)/3; - // In order to determine which part of the sphere is the "positive" - // part, assemble a second plane from the mid points of the edges. - // If any of these midpoints are on the plane of the vertices this - // degenerates into a one or two plane case, but if all three are - // off of the back plane the vector between them will give us the - // orientation we need. - ON_SimpleArray<ON_3dPoint> mid_pnts(3); - for (int i = 0; i < data->edges_cnt; i++) { - const ON_BrepEdge *edge = &(data->brep->m_E[data->edges[i]]); - const ON_Curve *curve = edge->EdgeCurveOf(); - ON_3dPoint mid_pnt = curve->PointAt(curve->Domain().Mid()); - mid_pnts.Append(mid_pnt); - } - ON_Plane front_plane(mid_pnts[0], mid_pnts[1], mid_pnts[2]); - ON_3dPoint fpc = (mid_pnts[0] + mid_pnts[1] + mid_pnts[2])/3; - // Using the above info, set the back_plane normal to the correct - // direction needed for defining a face in a B-Rep bounding the - // spherical sub-volume. - ON_3dVector pv = fpc - bpc; - if (ON_DotProduct(pv, back_plane.Normal()) > 0) back_plane.Flip(); - - // Then, construct planes for each arc from the three points. Use - // the vectors between the center point of the back plane - // and the midpoints of each edge to determine if the plane normal - // should be flipped - the plane normals of the edge planes shouldn't - // be pointing back towards the back face center point. - ON_SimpleArray<ON_Plane> edge_planes(3); - ON_SimpleArray<ON_3dPoint> edge_centers(3); - for (int i = 0; i < data->edges_cnt; i++) { - const ON_BrepEdge *edge = &(data->brep->m_E[data->edges[i]]); - const ON_Curve *curve = edge->EdgeCurveOf(); - ON_3dPoint start_pnt = curve->PointAtStart(); - ON_3dPoint mid_pnt = curve->PointAt(curve->Domain().Mid()); - ON_3dPoint end_pnt = curve->PointAtEnd(); - edge_centers[i] = (start_pnt + mid_pnt + end_pnt)/3; - ON_Plane new_plane(start_pnt, mid_pnt, end_pnt); - ON_3dVector guide = mid_pnt - bpc; - if (ON_DotProduct(guide, new_plane.Normal()) < 0) new_plane.Flip(); - edge_planes.Append(new_plane); - } - - - // Start building the local comb - data->type = COMB; - data->obj_cnt = data->parent->obj_cnt; - (*data->obj_cnt)++; - bu_vls_sprintf(data->id, "%s_%d_comb", bu_vls_addr(data->parent->id), *(data->obj_cnt)); - - - struct subbrep_object_data *sph_obj; - BU_GET(sph_obj, struct subbrep_object_data); - subbrep_object_init(sph_obj, data->brep); - std::string key = set_key(spherical_surfaces); - bu_vls_sprintf(sph_obj->key, "%s_sph", key.c_str()); - sph_obj->obj_cnt = data->parent->obj_cnt; - (*sph_obj->obj_cnt)++; - bu_vls_sprintf(sph_obj->id, "%s_%d_sph", bu_vls_addr(data->parent->id), *(sph_obj->obj_cnt)); - sph_obj->type = SPHERE; - - // Flag the sph/arb comb according to the negative or positive status of the - // sphere surface. Whether the comb is actually subtracted from the - // global object or unioned into a comb lower down the tree (or vice versa) - // is determined later. - data->negative_shape = negative_sphere(data, *spherical_surfaces.begin(), sph_tol); - data->params->bool_op = (data->negative_shape == -1) ? '-' : 'u'; - - // Add the sphere - unioned top level for this sub-comb - sph_obj->params->bool_op = 'u'; - sph_obj->params->origin[0] = sph.Center().x; - sph_obj->params->origin[1] = sph.Center().y; - sph_obj->params->origin[2] = sph.Center().z; - sph_obj->params->radius = sph.Radius(); - - bu_ptbl_ins(data->children, (long *)sph_obj); - - - // A planar face parallel to the back plane must also be added to - // the parent planer brep, if there is one. - if (!data->is_island && data->parent) { - if (!data->parent->planar_obj) { - subbrep_planar_init(data->parent); - } - subbrep_add_planar_face(data->parent, &back_plane, &sph_verts, data->negative_shape); - } - - // The planes each define an arb8 (4 all together) that carve the - // sub-sphere shape out of the parent sphere with subtractions. - // Using the normals, center points, edge and sphere information, - // construct the 4 arbs. - - // Construct the back face arb. - { - ON_SimpleArray<ON_3dPoint> arb1_points(8); - ON_3dVector x = back_plane.Xaxis(); - ON_3dVector y = back_plane.Yaxis(); - x.Unitize(); - y.Unitize(); - x = x * 1.5 * sph.Radius(); - y = y * 1.5 * sph.Radius(); - arb1_points[0] = bpc - x - y; - arb1_points[1] = bpc + x - y; - arb1_points[2] = bpc + x + y; - arb1_points[3] = bpc - x + y; - - ON_3dVector arb_side = back_plane.Normal() * 2*sph.Radius(); - - arb1_points[4] = arb1_points[0] + arb_side; - arb1_points[5] = arb1_points[1] + arb_side; - arb1_points[6] = arb1_points[2] + arb_side; - arb1_points[7] = arb1_points[3] + arb_side; - - struct subbrep_object_data *arb_obj; - BU_GET(arb_obj, struct subbrep_object_data); - subbrep_object_init(arb_obj, data->brep); - bu_vls_sprintf(arb_obj->key, "%s_arb8_b", key.c_str()); - arb_obj->obj_cnt = data->parent->obj_cnt; - (*arb_obj->obj_cnt)++; - bu_vls_sprintf(arb_obj->id, "%s_%d_arb8_b", bu_vls_addr(data->parent->id), *(arb_obj->obj_cnt)); - arb_obj->type = ARB8; - - arb_obj->params->bool_op = '-'; - arb_obj->params->arb_type = 8; - for (int j = 0; j < 8; j++) { - VMOVE(arb_obj->params->p[j], arb1_points[j]); - } - bu_ptbl_ins(data->children, (long *)arb_obj); - } - // Construct the edge face arbs. - // TODO - can tighten these using the dimensions of the - // arc bounding box, at least in theory - for (int i = 0; i < data->edges_cnt; i++) { - ON_SimpleArray<ON_3dPoint> arb_points(8); - ON_3dVector ex = edge_planes[i].Xaxis(); - ON_3dVector ey = edge_planes[i].Yaxis(); - ON_3dPoint ecenter = edge_centers[i]; - ex.Unitize(); - ey.Unitize(); - ex = ex * 1.5 * sph.Radius(); - ey = ey * 1.5 * sph.Radius(); - arb_points[0] = ecenter - ex - ey; - arb_points[1] = ecenter + ex - ey; - arb_points[2] = ecenter + ex + ey; - arb_points[3] = ecenter - ex + ey; - - ON_3dVector earb_side = edge_planes[i].Normal() * 2*sph.Radius(); - - arb_points[4] = arb_points[0] + earb_side; - arb_points[5] = arb_points[1] + earb_side; - arb_points[6] = arb_points[2] + earb_side; - arb_points[7] = arb_points[3] + earb_side; - - struct subbrep_object_data *earb_obj; - BU_GET(earb_obj, struct subbrep_object_data); - subbrep_object_init(earb_obj, data->brep); - bu_vls_sprintf(earb_obj->key, "%s_arb8_%d", key.c_str(), i); - earb_obj->obj_cnt = data->parent->obj_cnt; - (*earb_obj->obj_cnt)++; - bu_vls_sprintf(earb_obj->id, "%s_%d_arb8_%d", bu_vls_addr(data->parent->id), *(earb_obj->obj_cnt), i); - earb_obj->type = ARB8; - - earb_obj->params->bool_op = '-'; - earb_obj->params->arb_type = 8; - for (int j = 0; j < 8; j++) { - VMOVE(earb_obj->params->p[j], arb_points[j]); - } - bu_ptbl_ins(data->children, (long *)earb_obj); - - } - - return 1; - } - - if (verts.size() >= 3) { - bu_log("Complex sphere situation.\n"); - return 0; - } - - return -1; -} - // Local Variables: // tab-width: 8 // mode: C++ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |