RH_C_FUNCTION ON_MassProperties* ON_Curve_AreaMassProperties(const ON_Curve* pCurve, double rel_tol, double abs_tol, double curve_planar_tol) { ON_MassProperties* rc = NULL; if( pCurve ) { ON_Plane plane; if( pCurve->IsPlanar(&plane, curve_planar_tol) && pCurve->IsClosed() ) { ON_BoundingBox bbox = pCurve->BoundingBox(); ON_3dPoint basepoint = bbox.Center(); basepoint = plane.ClosestPointTo(basepoint); rc = new ON_MassProperties(); bool getresult = pCurve->AreaMassProperties(basepoint, plane.Normal(), *rc, true, true, true, true, rel_tol, abs_tol); if( getresult ) { rc->m_mass = fabs(rc->m_mass); } else { delete rc; rc = NULL; } } } return rc; }
bool ON_Circle::Create( const ON_3dPoint& C, double r ) { ON_Plane p = ON_xy_plane; p.origin = C; p.UpdateEquation(); return Create( p, r ); }
bool ON_Arc::Create( // arc is parallel to XY plane const ON_3dPoint& center, // center double r, // radius double angle_radians // angle in radians ) { ON_Plane p; p.CreateFromNormal( center, ON_zaxis ); return Create( ON_Circle(p,r), ON_Interval( 0.0, angle_radians ) ); }
bool ON_PlaneSurface::CreatePseudoInfinitePlane( const ON_Plane& plane, int point_count, const ON_3dPoint* point_list, double padding ) { if ( !plane.IsValid() ) return false; if ( point_count < 1 ) return false; if ( 0 == point_list ) return false; if ( !ON_IsValid(padding) || padding < 0.0 ) return false; ON_Interval plane_domain[2]; double s, t; s = ON_UNSET_VALUE; t = ON_UNSET_VALUE; if ( !plane.ClosestPointTo( point_list[0], &s, &t ) || !ON_IsValid(s) || !ON_IsValid(t) ) return 0; plane_domain[0].m_t[1] = plane_domain[0].m_t[0] = s; plane_domain[1].m_t[1] = plane_domain[1].m_t[0] = t; for ( int i = 1; i < point_count; i++ ) { s = ON_UNSET_VALUE; t = ON_UNSET_VALUE; if ( !plane.ClosestPointTo( point_list[i], &s, &t ) || !ON_IsValid(s) || !ON_IsValid(t) ) return 0; if ( s < plane_domain[0].m_t[0] ) plane_domain[0].m_t[0] = s; else if ( s > plane_domain[0].m_t[1] ) plane_domain[0].m_t[1] = s; if ( t < plane_domain[1].m_t[0] ) plane_domain[1].m_t[0] = t; else if ( t > plane_domain[1].m_t[1] ) plane_domain[1].m_t[1] = t; } s = padding*plane_domain[0].Length() + padding; if ( !(s > 0.0) && !plane_domain[0].IsIncreasing() ) s = 1.0; plane_domain[0].m_t[0] -= s; plane_domain[0].m_t[1] += s; t = padding*plane_domain[1].Length() + padding; if ( !(t > 0.0) && !plane_domain[1].IsIncreasing() ) t = 1.0; plane_domain[1].m_t[0] -= t; plane_domain[1].m_t[1] += t; m_plane = plane; m_domain[0] = plane_domain[0]; m_domain[1] = plane_domain[1]; m_extents[0] = plane_domain[0]; m_extents[1] = plane_domain[1]; return IsValid()?true:false; }
RH_C_FUNCTION ON_MassProperties* ON_Geometry_AreaMassProperties(const ON_SimpleArray<const ON_Geometry*>* pConstGeometryArray, double relativeTolerance, double absoluteTolerance) { ON_MassProperties* rc = NULL; if( pConstGeometryArray && pConstGeometryArray->Count() > 0 ) { ON_BoundingBox bbox; for( int i = 0; i < pConstGeometryArray->Count(); i++ ) { const ON_Geometry* geo = (*pConstGeometryArray)[i]; if( NULL==geo ) continue; geo->GetBoundingBox(bbox,TRUE); } ON_3dPoint basepoint = bbox.Center(); // Aggregate all mass properties for( int i = 0; i < pConstGeometryArray->Count(); i++ ) { const ON_Geometry* geo = (*pConstGeometryArray)[i]; if( NULL==geo ) continue; bool success = false; ON_MassProperties mp; const ON_Brep* pBrep = ON_Brep::Cast(geo); if( pBrep ) success = pBrep->AreaMassProperties(mp, true, true, true, true, relativeTolerance, absoluteTolerance); const ON_Surface* pSurface = success?0:ON_Surface::Cast(geo); if( pSurface ) success = pSurface->AreaMassProperties(mp, true, true, true, true, relativeTolerance, absoluteTolerance); const ON_Mesh* pMesh = success?0:ON_Mesh::Cast(geo); if( pMesh ) success = pMesh->AreaMassProperties(mp, true, true, true, true); const ON_Curve* pCurve = success?0:ON_Curve::Cast(geo); ON_Plane plane; if( pCurve && pCurve->IsPlanar(&plane, absoluteTolerance) && pCurve->IsClosed() ) success = pCurve->AreaMassProperties(basepoint, plane.Normal(), mp, true, true, true, true, relativeTolerance, absoluteTolerance); if( success ) { if( NULL==rc ) rc = new ON_MassProperties(mp); else rc->Sum(1, &mp, true); } } } return rc; }
bool ON_Arc::Create( // arc parallel to a plane const ON_Plane& pl, // circle will be parallel to this plane const ON_3dPoint& center, // center double r, // radius double angle_radians // angle in radians ) { ON_Plane p = pl; p.origin = center; p.UpdateEquation(); return Create( ON_Circle( p, r), ON_Interval( 0.0, angle_radians ) ); }
ON_BOOL32 ON_LineCurve::IsInPlane( const ON_Plane& plane, // plane to test double tolerance // tolerance to use when checking linearity ) const { ON_BOOL32 rc = false; double d = fabs( plane.DistanceTo( PointAtStart() )); if ( d <= tolerance ) { d = fabs( plane.DistanceTo( PointAtEnd() )); if ( d <= tolerance ) rc = true; } return rc; }
ON_BOOL32 ON_Surface::FrameAt( double u, double v, ON_Plane& frame) const { ON_BOOL32 rc = false; ON_3dPoint origin; ON_3dVector udir, vdir, normal; if( EvNormal( u, v, origin, udir, vdir, normal)) { if ( udir.Unitize() ) vdir = ON_CrossProduct( normal, udir); else if ( vdir.Unitize() ) udir = ON_CrossProduct( vdir, normal); frame.CreateFromFrame( origin, udir, vdir); rc = frame.IsValid(); } return rc; }
void COrientOnCrvXform::MakeNormalPlane( const ON_3dPoint origin, const ON_3dVector& normal, ON_Plane& plane ) { plane.origin = origin; ON_3dVector up( normal.x, normal.y, normal.z + 1.0 ); plane.xaxis = ON_CrossProduct( up, normal ); if( plane.xaxis.IsTiny() ) { if( normal.z < 0.0 ) { plane.xaxis = ON_3dVector( 1.0, 0.0, 0.0 ); plane.yaxis = ON_3dVector( 0.0, -1.0, 0.0 ); } else { plane.xaxis = ON_3dVector( 1.0, 0.0, 0.0 ); plane.yaxis = ON_3dVector( 0.0, 1.0, 0.0 ); } } else { plane.xaxis.Unitize(); plane.yaxis = ON_CrossProduct( normal, plane.xaxis ); plane.yaxis.Unitize(); } plane.UpdateEquation(); }
CRhinoCommand::result CCommandSampleOrientOnCrv::GetBasePlane( ON_Plane& base_plane ) { CRhinoGetPoint get; get.SetCommandPrompt( L"Base point" ); get.AcceptNothing(); get.GetPoint(); CRhinoCommand::result rc = get.CommandResult(); if( rc == CRhinoCommand::success ) { base_plane = get.View()->Viewport().ConstructionPlane().m_plane; base_plane.origin = get.Point(); base_plane.UpdateEquation(); if( !base_plane.IsValid() ) rc = CRhinoCommand::cancel; } return rc; }
bool ON_Quaternion::GetRotation(ON_Plane& plane) const { plane.xaxis.x = a*a + b*b - c*c - d*d; plane.xaxis.y = 2.0*(a*d + b*c); plane.xaxis.z = 2.0*(b*d - a*c); plane.yaxis.x = 2.0*(b*c - a*d); plane.yaxis.y = a*a - b*b + c*c - d*d; plane.yaxis.z = 2.0*(a*b + c*d); plane.zaxis.x = 2.0*(a*c + b*d); plane.zaxis.y = 2.0*(c*d - a*b); plane.zaxis.z = a*a - b*b - c*c + d*d; plane.xaxis.Unitize(); plane.yaxis.Unitize(); plane.zaxis.Unitize(); plane.origin.Set(0.0,0.0,0.0); plane.UpdateEquation(); return plane.IsValid(); }
void CTestPreviewDialog::OnBnClickedPreview() { UpdateData( TRUE ); ON_3dPoint point( m_center_x, m_center_y, m_center_z ); ON_Plane plane = ON_xy_plane; plane.SetOrigin( point ); ON_Circle circle( plane, m_radius ); if( circle.IsValid() ) { m_preview.m_circle = circle; if( !m_preview.IsEnabled() ) m_preview.Enable(); CRhinoDoc* doc = RhinoApp().ActiveDoc(); if( doc ) doc->Regen(); } }
int ON_Intersect( // returns 0 = no intersections, // 1 = intersection = single point, // 2 = intersection = circle // If 0 is returned, returned circle has radius=0 // and center = point on sphere closest to plane. // If 1 is returned, intersection is a single // point and returned circle has radius=0 // and center = intersection point on sphere. const ON_Plane& plane, const ON_Sphere& sphere, ON_Circle& circle ) { int rc = 0; const ON_3dPoint sphere_center = sphere.plane.origin; const double sphere_radius = fabs(sphere.radius); double tol = sphere_radius*ON_SQRT_EPSILON; if ( tol < ON_ZERO_TOLERANCE ) tol = ON_ZERO_TOLERANCE; circle.plane = plane; ON_3dPoint plane_center = plane.ClosestPointTo(sphere_center); double d = plane_center.DistanceTo(sphere_center); if ( d >= sphere_radius-tol ) { rc = ( d <= sphere_radius-tol ) ? 1 : 0; circle.plane.origin = sphere.ClosestPointTo(plane_center); circle.plane.UpdateEquation(); circle.radius = 0.0; } else { d /= sphere_radius; circle.radius = sphere_radius*sqrt(1.0 - d*d); if ( circle.radius <= ON_ZERO_TOLERANCE ) { circle.radius = 0.0; rc = 1; } else rc = 2; } //circle.UpdatePoints(); return rc; }
bool ON_Line::InPlane( ON_Plane& plane, double tolerance ) const { const ON_3dVector v = to-from; const bool bTinyX = fabs(v.x) <= tolerance; const bool bTinyY = fabs(v.y) <= tolerance; const bool bTinyZ = fabs(v.z) <= tolerance; bool rc = true; ON_3dVector X; ON_3dVector Y; if ( bTinyZ && ( !bTinyX || !bTinyY ) ) { X = ON_xaxis; Y = ON_yaxis; } else if ( bTinyX && ( !bTinyY || !bTinyZ ) ) { X = ON_yaxis; Y = ON_zaxis; } else if ( bTinyY && ( !bTinyZ || !bTinyX ) ) { X = ON_zaxis; Y = ON_xaxis; } else { X = v; X.Unitize(); Y.PerpendicularTo(X); if ( bTinyX && bTinyY && bTinyZ ) { rc = false; if ( X.IsZero() ) { X = ON_xaxis; Y = ON_yaxis; } } } plane.CreateFromFrame( from, X, Y ); return rc; }
bool ON_Plane::Morph( const ON_SpaceMorph& morph ) { ON_Plane mp; double s = sqrt( fabs(origin.MaximumCoordinate())*ON_SQRT_EPSILON + ON_ZERO_TOLERANCE ); mp.xaxis = morph.MorphVector(origin,s*xaxis); mp.yaxis = morph.MorphVector(origin,s*yaxis); mp.zaxis = morph.MorphVector(origin,s*zaxis); origin = morph.MorphPoint(origin); UpdateEquation(); bool bx = mp.xaxis.Unitize(); bool by = mp.yaxis.Unitize(); bool bz = mp.zaxis.Unitize(); if (!bx) { mp.xaxis = ON_CrossProduct(mp.yaxis,mp.zaxis); bx = mp.xaxis.Unitize(); } if (!by) { mp.yaxis = ON_CrossProduct(mp.zaxis,mp.xaxis); by = mp.yaxis.Unitize(); } if (!bz) { mp.zaxis = ON_CrossProduct(mp.xaxis,mp.yaxis); bz = mp.zaxis.Unitize(); } mp.origin.Set(0.0,0.0,0.0); mp.UpdateEquation(); bool rc = mp.IsValid(); ON_3dVector x, y, z; if ( rc ) { x = mp.xaxis; y = mp.yaxis; z = mp.zaxis; } else { x = ON_CrossProduct(mp.yaxis,mp.zaxis); y = ON_CrossProduct(mp.zaxis,mp.xaxis); z = ON_CrossProduct(mp.xaxis,mp.yaxis); x.Unitize(); y.Unitize(); z.Unitize(); x = mp.xaxis + x; y = mp.yaxis + y; z = mp.zaxis + z; x.Unitize(); y.Unitize(); z.Unitize(); rc = mp.CreateFromFrame(ON_origin,x,y); if (rc) { x = mp.xaxis; y = mp.yaxis; z = mp.zaxis; } else { rc = mp.CreateFromFrame(ON_origin,y,z); if ( rc ) { y = mp.xaxis; z = mp.yaxis; x = mp.zaxis; } else { rc = mp.CreateFromFrame(ON_origin,z,x); if (rc) { z = mp.xaxis; x = mp.yaxis; y = mp.zaxis; } else { rc = mp.CreateFromNormal(ON_origin,z); if (rc) { x = mp.xaxis; y = mp.yaxis; z = mp.zaxis; } } } } } if (rc) { xaxis = x; yaxis = y; zaxis = z; UpdateEquation(); } return rc; }
int ON_ArePointsOnPlane( // returns 0=no, 1 = yes, 2 = pointset is (to tolerance) a single point on the line int dim, // 2 or 3 int is_rat, int count, int stride, const double* point, const ON_BoundingBox& bbox, // if needed, use ON_GetBoundingBox(dim,is_rat,count,stride,point) const ON_Plane& plane, // line to test double tolerance ) { double w; int i, j, k; if ( count < 1 ) return 0; if ( !plane.IsValid() ) { ON_ERROR("plane parameter is not valid"); return 0; } if ( !bbox.IsValid() ) { ON_ERROR("bbox parameter is not valid"); return 0; } if ( !ON_IsValid(tolerance) || tolerance < 0.0 ) { ON_ERROR("tolerance must be >= 0.0"); return 0; } if ( dim < 2 || dim > 3 ) { ON_ERROR("dim must be 2 or 3"); return 0; } if ( stride < (is_rat?(dim+1):dim) ) { ON_ERROR("stride parameter is too small"); return 0; } if ( 0 == point ) { ON_ERROR("point parameter is null"); return 0; } int rc = 0; if ( tolerance == 0.0 ) { tolerance = bbox.Tolerance(); } ON_3dPoint Q; // test bounding box to quickly detect the common coordinate axis cases rc = (count == 1 || bbox.Diagonal().Length() <= tolerance) ? 2 : 1; for ( i = 0; rc && i < 2; i++ ) { Q.x = bbox[i].x; for ( j = 0; rc && j < 2; j++) { Q.y = bbox[j].y; for ( k = 0; rc && k < 2; k++) { Q.z = bbox[k].z; if ( Q.DistanceTo( plane.ClosestPointTo( Q ) ) > tolerance ) rc = 0; } } } if ( !rc ) { // test points one by one Q.Zero(); rc = (count == 1 || bbox.Diagonal().Length() <= tolerance) ? 2 : 1; if ( is_rat ) { for ( i = 0; i < count; i++ ) { w = point[dim]; if ( w == 0.0 ) { ON_ERROR("rational point has zero weight"); return 0; } ON_ArrayScale( dim, 1.0/w, point, &Q.x ); if ( Q.DistanceTo( plane.ClosestPointTo( Q ) ) > tolerance ) { rc = 0; break; } point += stride; } } else { for ( i = 0; i < count; i++ ) { memcpy( &Q.x, point, dim*sizeof(Q.x) ); if ( Q.DistanceTo( plane.ClosestPointTo( Q ) ) > tolerance ) { rc = 0; break; } point += stride; } } } return rc; }
int negative_polygon(struct subbrep_object_data *data) { int io_state = 0; int all_faces_cnt = 0; std::vector<int> all_faces; int *final_faces = NULL; std::set<int> fol_faces; /* This will get reused for all faces, so make it once */ point_t *all_verts = (point_t *)bu_calloc(data->brep->m_V.Count(), sizeof(point_t), "bot verts"); for (int vi = 0; vi < data->brep->m_V.Count(); vi++) { VMOVE(all_verts[vi], data->brep->m_V[vi].Point()); } array_to_set(&fol_faces, data->fol, data->fol_cnt); // Check each face to see if it is fil or fol - the first fol face, stash its // normal - don't even need the triangle face normal, we can just use the face's normal and // a point from the center of one of the fol triangles on that particular face. ON_3dPoint origin_pnt; ON_3dVector triangle_normal; int have_hit_pnt = 0; /* Get triangles from the faces */ ON_BoundingBox vert_bbox; ON_MinMaxInit(&vert_bbox.m_min, &vert_bbox.m_max); for (int i = 0; i < data->loops_cnt; i++) { const ON_BrepLoop *b_loop = &(data->brep->m_L[data->loops[i]]); int *ffaces = NULL; int num_faces = subbrep_polygon_tri(data->brep, all_verts, (int *)&(b_loop->m_loop_index), 1, &ffaces); if (!num_faces) { bu_log("Error - triangulation failed for loop %d!\n", b_loop->m_loop_index); return 0; } if (!have_hit_pnt) { const ON_BrepFace *b_face = b_loop->Face(); if (fol_faces.find(b_face->m_face_index) != fol_faces.end()) { ON_3dPoint p1 = data->brep->m_V[ffaces[0]].Point(); ON_3dPoint p2 = data->brep->m_V[ffaces[1]].Point(); ON_3dPoint p3 = data->brep->m_V[ffaces[2]].Point(); ON_Plane fp; ON_Surface *ts = b_face->SurfaceOf()->Duplicate(); (void)ts->IsPlanar(&fp, BREP_PLANAR_TOL); delete ts; triangle_normal = fp.Normal(); if (b_face->m_bRev) triangle_normal = triangle_normal * -1; origin_pnt = (p1 + p2 + p3) / 3; have_hit_pnt = 1; } } for (int f_ind = 0; f_ind < num_faces*3; f_ind++) { all_faces.push_back(ffaces[f_ind]); vert_bbox.Set(data->brep->m_V[ffaces[f_ind]].Point(), true); } if (ffaces) bu_free(ffaces, "free polygon face array"); all_faces_cnt += num_faces; } /* Now we can build the final faces array */ final_faces = (int *)bu_calloc(all_faces_cnt * 3, sizeof(int), "final bot verts"); for (int i = 0; i < all_faces_cnt*3; i++) { final_faces[i] = all_faces[i]; } // Scale bounding box to make sure corners are away from the volume vert_bbox.m_min = vert_bbox.m_min * 1.1; vert_bbox.m_max = vert_bbox.m_max * 1.1; // Pick a ray direction ON_3dVector rdir; ON_3dPoint box_corners[8]; vert_bbox.GetCorners(box_corners); int have_dir = 0; int corner = 0; double dotp; while (!have_dir && corner < 8) { rdir = box_corners[corner] - origin_pnt; dotp = ON_DotProduct(triangle_normal, rdir); (NEAR_ZERO(dotp, 0.01)) ? corner++ : have_dir = 1; } if (!have_dir) { bu_log("Error: NONE of the corners worked??\n"); return 0; } point_t origin, dir; VMOVE(origin, origin_pnt); VMOVE(dir, rdir); #if 0 std::cout << "working: " << bu_vls_addr(data->key) << "\n"; bu_log("in origin.s sph %f %f %f 1\n", origin[0], origin[1], origin[2]); bu_log("in triangle_normal.s rcc %f %f %f %f %f %f 1 \n", origin_pnt.x, origin_pnt.y, origin_pnt.z, triangle_normal.x, triangle_normal.y, triangle_normal.z); bu_log("in ray.s rcc %f %f %f %f %f %f 1 \n", origin[0], origin[1], origin[2], dir[0], dir[1], dir[2]); #endif // Test the ray against the triangle set int hit_cnt = 0; point_t p1, p2, p3, isect; ON_3dPointArray hit_pnts; for (int i = 0; i < all_faces_cnt; i++) { ON_3dPoint onp1, onp2, onp3, hit_pnt; VMOVE(p1, all_verts[all_faces[i*3+0]]); VMOVE(p2, all_verts[all_faces[i*3+1]]); VMOVE(p3, all_verts[all_faces[i*3+2]]); onp1.x = p1[0]; onp1.y = p1[1]; onp1.z = p1[2]; onp2.x = p2[0]; onp2.y = p2[1]; onp2.z = p2[2]; onp3.x = p3[0]; onp3.y = p3[1]; onp3.z = p3[2]; ON_Plane fplane(onp1, onp2, onp3); int is_hit = bg_isect_tri_ray(origin, dir, p1, p2, p3, &isect); VMOVE(hit_pnt, isect); // Don't count the point on the ray origin if (hit_pnt.DistanceTo(origin_pnt) < 0.0001) is_hit = 0; if (is_hit) { // No double-counting for (int j = 0; j < hit_pnts.Count(); j++) { if (hit_pnts[j].DistanceTo(hit_pnt) < 0.001) is_hit = 0; } if (is_hit) { //bu_log("in hit_cnt%d.s sph %f %f %f 0.1\n", hit_pnts.Count()+1, isect[0], isect[1], isect[2]); hit_pnts.Append(hit_pnt); } } } hit_cnt = hit_pnts.Count(); //bu_log("hit count: %d\n", hit_cnt); //bu_log("dotp : %f\n", dotp); // Final inside/outside determination if (hit_cnt % 2) { io_state = (dotp > 0) ? -1 : 1; } else { io_state = (dotp < 0) ? -1 : 1; } //bu_log("inside out state: %d\n", io_state); bu_free(all_verts, "free top level vertex array"); bu_free(final_faces, "free face array"); return io_state; }
extern "C" void rt_sketch_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *UNUSED(tol)) { struct rt_sketch_internal *eip; RT_CK_DB_INTERNAL(ip); eip = (struct rt_sketch_internal *)ip->idb_ptr; RT_SKETCH_CK_MAGIC(eip); ON_3dPoint plane_origin; ON_3dVector plane_x_dir, plane_y_dir; // Find plane in 3 space corresponding to the sketch. plane_origin = ON_3dPoint(eip->V); plane_x_dir = ON_3dVector(eip->u_vec); plane_y_dir = ON_3dVector(eip->v_vec); const ON_Plane sketch_plane = ON_Plane(plane_origin, plane_x_dir, plane_y_dir); // For the brep, need the list of 3D vertex points. In sketch, they // are stored as 2D coordinates, so use the sketch_plane to define 3 space // points for the vertices. for (size_t i = 0; i < eip->vert_count; i++) { (*b)->NewVertex(sketch_plane.PointAt(eip->verts[i][0], eip->verts[i][1]), 0.0); } // Create the brep elements corresponding to the sketch lines, curves // and bezier segments. Create 2d, 3d and BrepEdge elements for each segment. // Will need to use the bboxes of each element to // build the overall bounding box for the face. Use bGrowBox to expand // a single box. struct line_seg *lsg; struct carc_seg *csg; struct bezier_seg *bsg; uint32_t *lng; for (size_t i = 0; i < (&eip->curve)->count; i++) { lng = (uint32_t *)(&eip->curve)->segment[i]; switch (*lng) { case CURVE_LSEG_MAGIC: { lsg = (struct line_seg *)lng; ON_Curve* lsg3d = new ON_LineCurve((*b)->m_V[lsg->start].Point(), (*b)->m_V[lsg->end].Point()); lsg3d->SetDomain(0.0, 1.0); (*b)->m_C3.Append(lsg3d); } break; case CURVE_CARC_MAGIC: csg = (struct carc_seg *)lng; if (csg->radius < 0) { ON_3dPoint cntrpt = (*b)->m_V[csg->end].Point(); ON_3dPoint edgept = (*b)->m_V[csg->start].Point(); ON_Plane cplane = ON_Plane(cntrpt, plane_x_dir, plane_y_dir); ON_Circle c3dcirc = ON_Circle(cplane, cntrpt.DistanceTo(edgept)); ON_Curve* c3d = new ON_ArcCurve((const ON_Circle)c3dcirc); c3d->SetDomain(0.0, 1.0); (*b)->m_C3.Append(c3d); } else { // need to calculated 3rd point on arc - look to sketch.c around line 581 for // logic } break; case CURVE_BEZIER_MAGIC: bsg = (struct bezier_seg *)lng; { ON_3dPointArray bezpoints(bsg->degree + 1); for (int j = 0; j < bsg->degree + 1; j++) { bezpoints.Append((*b)->m_V[bsg->ctl_points[j]].Point()); } ON_BezierCurve bez3d = ON_BezierCurve((const ON_3dPointArray)bezpoints); ON_NurbsCurve* beznurb3d = ON_NurbsCurve::New(); bez3d.GetNurbForm(*beznurb3d); beznurb3d->SetDomain(0.0, 1.0); (*b)->m_C3.Append(beznurb3d); } break; default: bu_log("Unhandled sketch object\n"); break; } } // Create the plane surface and brep face. ON_PlaneSurface *sketch_surf = new ON_PlaneSurface(sketch_plane); (*b)->m_S.Append(sketch_surf); int surfindex = (*b)->m_S.Count(); ON_BrepFace& face = (*b)->NewFace(surfindex - 1); // For the purposes of BREP creation, it is necessary to identify // loops created by sketch segments. This information is not stored // in the sketch data structures themselves, and thus must be deduced FindLoops(b); const ON_BrepLoop* tloop = (*b)->m_L.First(); sketch_surf->SetDomain(0, tloop->m_pbox.m_min.x, tloop->m_pbox.m_max.x); sketch_surf->SetDomain(1, tloop->m_pbox.m_min.y, tloop->m_pbox.m_max.y); sketch_surf->SetExtents(0, sketch_surf->Domain(0)); sketch_surf->SetExtents(1, sketch_surf->Domain(1)); (*b)->SetTrimIsoFlags(face); (*b)->FlipFace(face); (*b)->Compact(); }
RH_C_FUNCTION ON_MassProperties* ON_GeometryMassProperties(bool bArea, ON_SimpleArray<const ON_Geometry*>* pGeometry, double relativeTolerance, double absoluteTolerance) { ON_MassProperties* rc = NULL; if( pGeometry && pGeometry->Count() > 0 ) { // Compute base-point of all geometry boundingboxes ON_3dPoint basePoint(0,0,0); if( !bArea ) { for( int i = 0; i < pGeometry->Count(); i++ ) { const ON_Geometry* geo = pGeometry->Array()[i]; ON_BoundingBox box = geo->BoundingBox(); basePoint += box.Center(); } basePoint /= pGeometry->Count(); } // Aggregate all mass properties rc = new ON_MassProperties(); for( int i = 0; i < pGeometry->Count(); i++ ) { const ON_Geometry* geo = pGeometry->Array()[i]; bool success = false; ON_MassProperties mp; ON::object_type type = pGeometry->Array()[i]->ObjectType(); const ON_Brep* pBrep; const ON_Surface* pSurface; const ON_Mesh* pMesh; const ON_Curve* pCurve; switch (type) { case ON::brep_object: pBrep = ON_Brep::Cast(geo); if( bArea ) success = pBrep->AreaMassProperties(mp, true, true, true, true, relativeTolerance, absoluteTolerance); else success = pBrep->VolumeMassProperties(mp, true, true, true, true, basePoint, relativeTolerance, absoluteTolerance); break; case ON::surface_object: pSurface = ON_Surface::Cast(geo); if( bArea ) success = pSurface->AreaMassProperties(mp, true, true, true, true, relativeTolerance, absoluteTolerance); else success = pSurface->VolumeMassProperties(mp, true, true, true, true, basePoint, relativeTolerance, absoluteTolerance); break; case ON::mesh_object: pMesh = ON_Mesh::Cast(geo); if( bArea ) success = pMesh->AreaMassProperties(mp, true, true, true, true); else success = pMesh->VolumeMassProperties(mp, true, true, true, true, basePoint); break; case ON::curve_object: if (bArea) { pCurve = ON_Curve::Cast(geo); ON_Plane plane; if( pCurve->IsPlanar(&plane, absoluteTolerance) && pCurve->IsClosed() ) { success = pCurve->AreaMassProperties(basePoint, plane.Normal(), mp, true, true, true, true, relativeTolerance, absoluteTolerance); if (success ) { mp.m_mass = fabs(mp.m_mass); } } } break; } if( success ) { rc->Sum(1, &mp, true); } } } return rc; }
CRhinoCommand::result CTraslRuota::RunCommand( const CRhinoCommandContext& context ) { Cscript1PlugIn& plugin = script1PlugIn(); if( !plugin.IsDlgVisible() ) { return CRhinoCommand::nothing; } /*GET A REFERENCE TO THE LAYER TABLE*/ CRhinoLayerTable& layer_table = context.m_doc.m_layer_table; ON_Layer currentLayer; int numLayers = layer_table.LayerCount(); for(int i = 0; i < numLayers; i++) { currentLayer = layer_table[i]; const CRhinoLayer& layer = layer_table[i]; currentLayer.SetVisible(true); layer_table.ModifyLayer(currentLayer, i); layer_table.SetCurrentLayerIndex(i); const CRhinoLayer& current_layer = layer_table.CurrentLayer(); int layer_index = layer_table.CurrentLayerIndex(); const CRhinoLayer& layer2 = layer_table[layer_index]; ON_SimpleArray<CRhinoObject*> obj_list; int j, obj_count = context.m_doc.LookupObject( layer2, obj_list ); for( j = 0; j < obj_count; j++ ) { CRhinoObject* obj = obj_list[j]; if( obj && obj->IsSelectable() ) obj->Select(); if( obj_count ) context.m_doc.Redraw(); } } context.m_doc.Redraw(); //inizio rotazione double m_angle=(_wtof(plugin.m_dialog->ValoreRotazione)); ON_Plane plane = RhinoActiveCPlane(); CRhinoGetObject go1; go1.GetObjects( 1, 0 ); int numero1 = go1.ObjectCount(); for( int k = 0; k < go1.ObjectCount(); k++ ) { // Get an object reference const CRhinoObjRef& ref = go1.Object(k); // Get the real object const CRhinoObject* obj = ref.Object(); if( !obj ) continue; ON_Xform xform; xform.Rotation( m_angle * ON_PI / 180.0, plane.zaxis, plane.Origin() ); context.m_doc.TransformObject( obj, xform, true, true, true ); context.m_doc.Redraw(); } //fine rotazione //inizio traslazione CRhinoGetObject go; int numero = go.ObjectCount(); go.GetObjects( 1, 0 ); for( int i = 0; i < go.ObjectCount(); i++ ) { // Get an object reference const CRhinoObjRef& ref = go.Object(i); // Get the real object const CRhinoObject* obj = ref.Object(); if( !obj ) continue; ON_Xform xform; xform.Rotation( m_angle * ON_PI / 180.0, plane.zaxis, plane.Origin() ); //context.m_doc.TransformObject( obj, xform, true, true, true ); context.m_doc.Redraw(); xform.Translation((_wtof(plugin.m_dialog->ValoreTraslazione)),0,0); context.m_doc.TransformObject( obj, xform, true, true, true ); context.m_doc.Redraw(); } // fine traslazione context.m_doc.Redraw(); return CRhinoCommand::success; }
CRhinoCommand::result CGenPianoVis::RunCommand( const CRhinoCommandContext& context ) { Cscript1PlugIn& plugin = script1PlugIn(); if( !plugin.IsDlgVisible() ) { return CRhinoCommand::nothing; } /*GET THE LAYER NAME*/ CRhinoGetString gs; gs.SetCommandPrompt( L"NAME OF LAYER WHICH CONTAINS VISIONAL PLANE : " ); gs.GetString(); if( gs.CommandResult() != CRhinoCommand::success ) { return gs.CommandResult(); } /*VALIDATE THE STRING*/ ON_wString layer_name = gs.String(); layer_name.TrimLeftAndRight(); if( layer_name.IsEmpty() ) { return CRhinoCommand::cancel; } /*GET A REFERENCE TO THE LAYER TABLE*/ CRhinoLayerTable& layer_table = context.m_doc.m_layer_table; /*FIND THE LAYER*/ int layer_index = layer_table.FindLayer(layer_name ); if( layer_index < 0 ) { RhinoApp().Print( L"LAYER \"%s\" DOES NOT EXIST.\n", layer_name ); } else { ON_Layer currentLayer; int numLayers = layer_table.LayerCount(); layer_table.SetCurrentLayerIndex(layer_index); for(int i = 0; i < numLayers; i++) { if(i != layer_index) { currentLayer = layer_table[i]; currentLayer.SetVisible(false); layer_table.ModifyLayer(currentLayer, i); } } context.m_doc.Redraw(); const CRhinoLayer& layer = context.m_doc.m_layer_table[layer_index]; ON_SimpleArray<CRhinoObject*> obj_list; int object_count = context.m_doc.LookupObject( layer, obj_list ); if( object_count > 0 ) { /********************************************************************/ //CRhinoObject* obj = obj_list[0]; //if( obj && obj->IsSelectable() ) //{ // obj->Select(true); // obj->Highlight(true); // m_doc.Redraw(); //} /********************************************************************/ //aniello gegin // Disable redrawing //CRhinoView::EnableDrawing( FALSE ); meglio tenerlo disabilitato altrimenti la schermata non si aggiorna. // Get the next runtime object serial number before scripting unsigned int first_sn = CRhinoObject::NextRuntimeObjectSerialNumber(); //aniello end ///////////////////// CRhinoGetObject gc; gc.SetCommandPrompt( L"SELECT LINE TO EXTEND" ); gc.SetGeometryFilter( CRhinoGetObject::curve_object ); gc.GetObjects( 1, 1 ); if(gc.CommandResult() == CRhinoCommand::success ) { const CRhinoObjRef& objref = gc.Object(0); const ON_Curve* pC = ON_Curve::Cast( objref.Geometry() ); ON_Curve* crv0 = pC->DuplicateCurve(); bool rc0 = RhinoExtendCurve(crv0, CRhinoExtend::Line, 1, 5); bool rc1 = RhinoExtendCurve(crv0, CRhinoExtend::Line, 0, 15); context.m_doc.ReplaceObject(objref, *crv0 ); context.m_doc.Redraw(); ///// begin prova memorizzazione id o name linea pv ////ON_UUID uuid1 = gc->Attributes().m_uuid; //// ON_UUID uuid1 = objref.ObjectUuid(); // //ON_UuidToString( uuid1, cvrPrima ); // const CRhinoObject* obj5 = objref.Object(); // ON_UUID uuid1 = obj5->Attributes().m_uuid; // pvcurva = uuid1; // ON_3dmObjectAttributes obj_attribs = obj5->Attributes(); // CRhinoGetString gs; //gs.SetCommandPrompt( L"New object name" ); //gs.SetDefaultString( obj_attribs.m_name ); //gs.AcceptNothing( TRUE ); //gs.GetString(); //if( gs.CommandResult() != CRhinoCommand::success ) // return gs.CommandResult(); //// Get the string entered by the user //ON_wString obj_name = gs.String(); //obj_name.TrimLeftAndRight(); //// Is name the same? //if( obj_name.Compare(obj_attribs.m_name) == 0 ) // return CRhinoCommand::nothing; // //ON_wString obj_name = (L"stringanome"); // obj_attribs.m_name = obj_name; // context.m_doc.ModifyObjectAttributes( objref, obj_attribs ); ///// end prova memorizzazione id o name linea pv ON_3dPoint p0 = crv0->PointAtStart(); ON_3dPoint p1 = crv0->PointAtEnd(); CRhinoGetNumber gn; //double default_value = 30; gn.SetCommandPrompt( L"ENTER ANTERIOR ANGLE FOR EXTENSION in grad: " ); gn.SetCommandPromptDefault(L"30"); gn.SetDefaultNumber(30); //gn.AcceptNothing(true); gn.GetNumber(); double alphaAngle = gn.Number(); gn.SetCommandPrompt( L"ENTER ANTERIOR LENGTH FOR EXTENSION in mm: " ); gn.SetCommandPromptDefault(L"80"); gn.SetDefaultNumber(80); gn.GetNumber(); double antLen = gn.Number(); gn.SetCommandPrompt( L"ENTER ANTERIOR FILLET RADIUS in mm: " ); gn.SetCommandPromptDefault(L"6"); gn.SetDefaultNumber(6); gn.GetNumber(); double antRad = gn.Number(); gn.SetCommandPrompt( L"ENTER POSTERIOR ANGLE FOR EXTENSION default <ALPHA + 10°= 40°> : " ); gn.SetCommandPromptDefault(L"40"); gn.SetDefaultNumber(40); gn.GetNumber(); double betaAngle = gn.Number(); gn.SetCommandPrompt( L"ENTER POSTERIOR LENGTH FOR EXTENSION in mm: " ); gn.SetCommandPromptDefault(L"80"); gn.SetDefaultNumber(80); gn.GetNumber(); double posLen = gn.Number(); gn.SetCommandPrompt( L"ENTER POSTERIOR FILLET RADIUS in mm: " ); gn.SetCommandPromptDefault(L"13"); gn.SetDefaultNumber(13); gn.GetNumber(); double posRad = gn.Number(); ON_3dPoint pointStart; ON_3dPoint pointEnd; //// Fillet radius //double radius = 1.0; // Do the fillet calculation double t0 = 0.0, t1 = 0.0; ON_Plane plane; plane.plane_equation.y = 1.0; pointStart = crv0->PointAtStart(); pointEnd = crv0->PointAtEnd(); ON_3dPoint point0((pointStart.x - posLen*cos(betaAngle*acos(-1.0)/180.0)), 0.0, (pointStart.z + posLen*sin(betaAngle*acos(-1.0)/180.0))); ON_3dPoint point1((pointEnd.x + antLen*cos(alphaAngle*acos(-1.0)/180.0)), 0.0, (pointEnd.z - antLen*sin(alphaAngle*acos(-1.0)/180.0))); /**********************************/ /*CREATE THE LINE CURVES TO FILLET*/ /**********************************/ ON_LineCurve curve0( pointStart, point0 ); //LINEA A SINISTRA IN FRONT VIEW ON_LineCurve curve1( point1, pointEnd ); //LINEA A DESTRA IN FRONT VIEW /***************************************************/ /*FILLET AT THE END/START POINTS OF THE LINE CURVES*/ /***************************************************/ double curve0_t = crv0->Domain().Max(); double curve1_t = curve1.Domain().Min(); ON_3dPoint PuntoAltezzaTacco = curve1.m_line.to; AltezzaTacco = PuntoAltezzaTacco; if( RhinoGetFilletPoints(curve1, *crv0, antRad, curve1_t, curve0_t, t1, t0, plane) ) { /*******************************/ /*TRIM BACK THE TWO LINE CURVES*/ /*******************************/ ON_Interval domain1( curve1.Domain().Min(), t1 ); curve1.Trim( domain1 ); ON_Interval domain0( crv0->Domain().Min(), t0 ); crv0->Trim( domain0 ); /**************************/ /*COMPUTE THE FILLET CURVE*/ /**************************/ ON_3dVector radial0 = curve1.PointAt(t1) - plane.Origin(); radial0.Unitize(); ON_3dVector radial1 = crv0->PointAt(t0) - plane.Origin(); radial1.Unitize(); double angle = acos( radial0 * radial1 ); ON_Plane fillet_plane( plane.Origin(), radial0, radial1 ); ON_Arc fillet( fillet_plane, plane.Origin(), antRad, angle ); /******************/ /*ADD THE GEOMETRY*/ /******************/ context.m_doc.AddCurveObject( curve1 ); context.m_doc.ReplaceObject(objref, *crv0 ); context.m_doc.AddCurveObject( fillet ); context.m_doc.Redraw(); } t0 = 0.0, t1 = 0.0; /*FILLET AT THE START POINTS OF THE LINE CURVES*/ curve0_t = crv0->Domain().Min(); curve1_t = curve0.Domain().Min(); if( RhinoGetFilletPoints(curve0, *crv0, posRad, curve1_t, curve0_t, t1, t0, plane) ) { // Trim back the two line curves ON_Interval domain0( t1, curve0.Domain().Max() ); curve0.Trim( domain0 ); ON_Interval domain1( t0, crv0->Domain().Max() ); crv0->Trim( domain1 ); /*COMPUTE THE FILLET CURVE*/ ON_3dVector radial0 = curve0.PointAt(t1) - plane.Origin(); radial0.Unitize(); ON_3dVector radial1 = crv0->PointAt(t0) - plane.Origin(); radial1.Unitize(); double angle = acos( radial0 * radial1 ); ON_Plane fillet_plane( plane.Origin(), radial0, radial1 ); ON_Arc fillet( fillet_plane, plane.Origin(), posRad, angle ); /*ADD THE GEOMETRY*/ context.m_doc.AddCurveObject( curve0 ); context.m_doc.ReplaceObject(objref, *crv0 ); context.m_doc.AddCurveObject( fillet ); context.m_doc.Redraw(); } /******************/ /*CLEAN UP OR LEAK*/ /******************/ delete crv0; crv0 = 0; // code temp // aniello begin // Get the next runtime object serial number after scripting unsigned int next_sn = CRhinoObject::NextRuntimeObjectSerialNumber(); // Enable redrawing //CRhinoView::EnableDrawing( TRUE ); // if the two are the same, then nothing happened /* if( first_sn == next_sn ) //return CRhinoCommand::nothing; return; */ //commento questo per far compilare :-) // The the pointers of all of the objects that were added during scripting ON_SimpleArray<const CRhinoObject*> objects; for( unsigned int sn = first_sn; sn < next_sn; sn++ ) { const CRhinoObject* obj = context.m_doc.LookupObjectByRuntimeSerialNumber( sn ); if( obj && !obj->IsDeleted() ) objects.Append( obj ); } /* // Sort and cull the list, as there may be duplicates if( objects.Count() > 1 ) { objects.HeapSort( CompareObjectPtr ); const CRhinoObject* last_obj = objects[objects.Count()-1]; for( int i = objects.Count()-2; i >= 0; i-- ) { const CRhinoObject* prev_obj = objects[i]; if( last_obj == prev_obj ) objects.Remove(i); else last_obj = prev_obj; } } */ // Do something with the list... for( int i = 0; i < objects.Count(); i++ ) { const CRhinoObject* obj = objects[i]; if( obj->IsSelectable(true) ) obj->Select( true ); } //aniello end //end code temp /*********************/ /*JOIN LINES TOGETHER*/ /*********************/ ON_SimpleArray<const ON_Curve*> lines; ON_SimpleArray<CRhinoObject*> objectsLine; ON_SimpleArray<ON_Curve*> output; double tolerance = context.m_doc.AbsoluteTolerance(); int LinesCount = context.m_doc.LookupObject( layer, objectsLine); if( LinesCount > 0 ) { for(int i = 0; i < LinesCount; i++) { const CRhinoCurveObject* curve_obj = CRhinoCurveObject::Cast( objectsLine[i] ); if( curve_obj ) { lines.Append(curve_obj->Curve()); } } } if( RhinoMergeCurves(lines, output, tolerance) ) { for(int i = 0; i < output.Count(); i++ ) { CRhinoCurveObject* crv = new CRhinoCurveObject; crv->SetCurve( output[i] ); if( context.m_doc.AddObject(crv) ) { crv->Select(); } else { delete crv; } } } /************************/ /*DELETE CHILDREN CURVES*/ /************************/ for(int i = 0; i < LinesCount; i++ ) { context.m_doc.DeleteObject(objectsLine[i]); } context.m_doc.Redraw(); /*************************/ /*END JOIN LINES TOGETHER*/ /*************************/ } }/*CHIUSURA IF( OBJECT_COUNT > 0 )*/ }/*CHIUSURA ELSE*/ return CRhinoCommand::success; }
extern "C" void rt_revolve_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *tol) { struct rt_db_internal *tmp_internal; struct rt_revolve_internal *rip; struct rt_sketch_internal *eip; BU_ALLOC(tmp_internal, struct rt_db_internal); RT_DB_INTERNAL_INIT(tmp_internal); rip = (struct rt_revolve_internal *)ip->idb_ptr; RT_REVOLVE_CK_MAGIC(rip); eip = rip->skt; RT_SKETCH_CK_MAGIC(eip); ON_3dPoint plane_origin; ON_3dVector plane_x_dir, plane_y_dir; bool full_revolve = true; if (rip->ang < 2*ON_PI && rip->ang > 0) full_revolve = false; // Find plane in 3 space corresponding to the sketch. vect_t startpoint; VADD2(startpoint, rip->v3d, rip->r); plane_origin = ON_3dPoint(startpoint); plane_x_dir = ON_3dVector(eip->u_vec); plane_y_dir = ON_3dVector(eip->v_vec); const ON_Plane sketch_plane = ON_Plane(plane_origin, plane_x_dir, plane_y_dir); // For the brep, need the list of 3D vertex points. In sketch, they // are stored as 2D coordinates, so use the sketch_plane to define 3 space // points for the vertices. for (size_t i = 0; i < eip->vert_count; i++) { (*b)->NewVertex(sketch_plane.PointAt(eip->verts[i][0], eip->verts[i][1]), 0.0); } // Create the brep elements corresponding to the sketch lines, curves // and bezier segments. Create 2d, 3d and BrepEdge elements for each segment. // Will need to use the bboxes of each element to // build the overall bounding box for the face. Use bGrowBox to expand // a single box. struct line_seg *lsg; struct carc_seg *csg; struct bezier_seg *bsg; uint32_t *lng; for (size_t i = 0; i < (&eip->curve)->count; i++) { lng = (uint32_t *)(&eip->curve)->segment[i]; switch (*lng) { case CURVE_LSEG_MAGIC: { lsg = (struct line_seg *)lng; ON_Curve* lsg3d = new ON_LineCurve((*b)->m_V[lsg->start].Point(), (*b)->m_V[lsg->end].Point()); lsg3d->SetDomain(0.0, 1.0); (*b)->m_C3.Append(lsg3d); } break; case CURVE_CARC_MAGIC: csg = (struct carc_seg *)lng; if (csg->radius < 0) { { ON_3dPoint cntrpt = (*b)->m_V[csg->end].Point(); ON_3dPoint edgept = (*b)->m_V[csg->start].Point(); ON_Plane cplane = ON_Plane(cntrpt, plane_x_dir, plane_y_dir); ON_Circle c3dcirc = ON_Circle(cplane, cntrpt.DistanceTo(edgept)); ON_Curve* c3d = new ON_ArcCurve((const ON_Circle)c3dcirc); c3d->SetDomain(0.0, 1.0); (*b)->m_C3.Append(c3d); } } else { // need to calculated 3rd point on arc - look to sketch.c around line 581 for // logic } break; case CURVE_BEZIER_MAGIC: bsg = (struct bezier_seg *)lng; { ON_3dPointArray bezpoints = ON_3dPointArray(bsg->degree + 1); for (int j = 0; j < bsg->degree + 1; j++) { bezpoints.Append((*b)->m_V[bsg->ctl_points[j]].Point()); } ON_BezierCurve bez3d = ON_BezierCurve((const ON_3dPointArray)bezpoints); ON_NurbsCurve* beznurb3d = ON_NurbsCurve::New(); bez3d.GetNurbForm(*beznurb3d); beznurb3d->SetDomain(0.0, 1.0); (*b)->m_C3.Append(beznurb3d); } break; default: bu_log("Unhandled sketch object\n"); break; } } vect_t endpoint; VADD2(endpoint, rip->v3d, rip->axis3d); const ON_Line& revaxis = ON_Line(ON_3dPoint(rip->v3d), ON_3dPoint(endpoint)); FindLoops(b, &revaxis, rip->ang); // Create the two boundary surfaces, if it's not a full revolution if (!full_revolve) { // First, deduce the transformation matrices to calculate the position of the end surface // The transformation matrices are to rotate an arbitrary point around an arbitrary axis // Let the point A = (x, y, z), the rotation axis is p1p2 = (x2,y2,z2)-(x1,y1,z1) = (a,b,c) // Then T1 is to translate p1 to the origin // Rx is to rotate p1p2 around the X axis to the plane XOZ // Ry is to rotate p1p2 around the Y axis to be coincident to Z axis // Rz is to rotate A with the angle around Z axis (the new p1p2) // RxInv, RyInv, T1Inv are the inverse transformation of Rx, Ry, T1, respectively. // The whole transformation is A' = A*T1*Rx*Ry*Rz*Ry*Inv*Rx*Inv = A*R vect_t end_plane_origin, end_plane_x_dir, end_plane_y_dir; mat_t R; MAT_IDN(R); mat_t T1, Rx, Ry, Rz, RxInv, RyInv, T1Inv; MAT_IDN(T1); VSET(&T1[12], -rip->v3d[0], -rip->v3d[1], -rip->v3d[2]); MAT_IDN(Rx); fastf_t v = sqrt(rip->axis3d[1]*rip->axis3d[1]+rip->axis3d[2]*rip->axis3d[2]); VSET(&Rx[4], 0, rip->axis3d[2]/v, rip->axis3d[1]/v); VSET(&Rx[8], 0, -rip->axis3d[1]/v, rip->axis3d[2]/v); MAT_IDN(Ry); fastf_t u = MAGNITUDE(rip->axis3d); VSET(&Ry[0], v/u, 0, -rip->axis3d[0]/u); VSET(&Ry[8], rip->axis3d[0]/u, 0, v/u); MAT_IDN(Rz); fastf_t C, S; C = cos(rip->ang); S = sin(rip->ang); VSET(&Rz[0], C, S, 0); VSET(&Rz[4], -S, C, 0); bn_mat_inv(RxInv, Rx); bn_mat_inv(RyInv, Ry); bn_mat_inv(T1Inv, T1); mat_t temp; bn_mat_mul4(temp, T1, Rx, Ry, Rz); bn_mat_mul4(R, temp, RyInv, RxInv, T1Inv); VEC3X3MAT(end_plane_origin, plane_origin, R); VADD2(end_plane_origin, end_plane_origin, &R[12]); VEC3X3MAT(end_plane_x_dir, plane_x_dir, R); VEC3X3MAT(end_plane_y_dir, plane_y_dir, R); // Create the start and end surface with rt_sketch_brep() struct rt_sketch_internal sketch; sketch = *(rip->skt); ON_Brep *b1 = ON_Brep::New(); VMOVE(sketch.V, plane_origin); VMOVE(sketch.u_vec, plane_x_dir); VMOVE(sketch.v_vec, plane_y_dir); tmp_internal->idb_ptr = (void *)(&sketch); rt_sketch_brep(&b1, tmp_internal, tol); (*b)->Append(*b1->Duplicate()); ON_Brep *b2 = ON_Brep::New(); VMOVE(sketch.V, end_plane_origin); VMOVE(sketch.u_vec, end_plane_x_dir); VMOVE(sketch.v_vec, end_plane_y_dir); tmp_internal->idb_ptr = (void *)(&sketch); rt_sketch_brep(&b2, tmp_internal, tol); (*b)->Append(*b2->Duplicate()); (*b)->FlipFace((*b)->m_F[(*b)->m_F.Count()-1]); } bu_free(tmp_internal, "free temporary rt_db_internal"); }
// Copied from opennurbs_intersect.cpp but with a bug fix. // We can remove it once the bug is fixed in OpenNurbs and once // Grasshopper has dropped Rhino4 support. int PS_Intersect( const ON_Plane& plane, const ON_Sphere& sphere, ON_Circle& circle ) { // 16 April 2011 Dale Lear // Prior to this date, this function did not return the correct answer. int rc = 0; const double sphere_radius = fabs(sphere.radius); double tol = sphere_radius*ON_SQRT_EPSILON; if ( !(tol >= ON_ZERO_TOLERANCE) ) tol = ON_ZERO_TOLERANCE; const ON_3dPoint sphere_center = sphere.Center(); ON_3dPoint circle_center = plane.ClosestPointTo(sphere_center); double d = circle_center.DistanceTo(sphere_center); circle.radius = 0.0; if ( ON_IsValid(sphere_radius) && ON_IsValid(d) && d <= sphere_radius + tol ) { if ( sphere_radius > 0.0 ) { d /= sphere_radius; d = 1.0 - d*d; // The d > 4.0*ON_EPSILON was picked by testing spheres with // radius = 1 and center = (0,0,0). Do not make 4.0*ON_EPSILON // any smaller and please discuss changes with Dale Lear. circle.radius = (d > 4.0*ON_EPSILON) ? sphere_radius*sqrt(d) : 0.0; } else circle.radius = 0.0; if ( circle.radius <= ON_ZERO_TOLERANCE ) { // return a single point rc = 1; circle.radius = 0.0; // When tolerance is in play, put the point on the sphere. // If the caller prefers the plane, then they can adjust the // returned answer to get the plane. ON_3dVector R = circle_center - sphere_center; double r0 = R.Length(); if ( r0 > 0.0 ) { R.Unitize(); ON_3dPoint C1 = sphere_center + sphere_radius*R; double r1 = C1.DistanceTo(sphere_center); if ( fabs(sphere.radius-r1) < fabs(sphere.radius-r0) ) circle_center = C1; } } else { // return a circle rc = 2; } } // Update circle's plane here in case the input plane // is the circle's plane member. circle.plane = plane; circle.plane.origin = circle_center; circle.plane.UpdateEquation(); return rc; }