예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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;
}
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;
}