Example #1
0
Ego::Math::Relation plane_intersects_aabb_max(const Plane3f& plane, const Vector3f& mins, const Vector3f& maxs)
{
    int   j;
    float dist, tmp;

	Ego::Math::Relation retval = Ego::Math::Relation::error;

    // find the point-plane distance for the most-positive points of the aabb
    dist = 0.0f;
    for (j = 0; j < 3; j++)
    {
        tmp = (plane.getNormal()[j] > 0.0f) ? maxs[j] : mins[j];
        dist += tmp * plane.getNormal()[j];
    }
    dist += plane.getDistance();

    if (dist > 0.0f)
    {
		retval = Ego::Math::Relation::inside;
    }
    else if (dist < 0.0f)
    {
		retval = Ego::Math::Relation::outside;
    }
    else
    {
		retval = Ego::Math::Relation::intersect;
    }

    return retval;
}
Example #2
0
int main( int argc, char **argv )
{
  if(argc<2)
  {
    printf("Usage trimesh_base <meshfilename.ply>\n");
    return -1;
  }

  MyMesh m,em,cm,full;

  if(tri::io::ImporterPLY<MyMesh>::Open(m,argv[1])!=0)
  {
    printf("Error reading file  %s\n",argv[1]);
    exit(0);
  }

  tri::UpdateFlags<MyMesh>::FaceBorderFromFF(m);
  tri::UpdateNormals<MyMesh>::PerVertexNormalized(m);
  tri::UpdateBounding<MyMesh>::Box(m);

  printf("Input mesh  vn:%i fn:%i\n",m.vn,m.fn);
  printf( "Mesh has %i vert and %i faces\n", m.vn, m.fn );
  srand(time(0));
  Plane3f slicingPlane;
  Point3f planeCenter = m.bbox.Center();

  for(int i=0;i<10;++i)
  {
    cm.Clear();
    em.Clear();
    Point3f planeDir = Point3f(-0.5f+float(rand())/RAND_MAX,-0.5f+float(rand())/RAND_MAX,-0.5f+float(rand())/RAND_MAX);
    planeDir.Normalize();
    printf("slicing dir %5.2f %5.2f %5.2f\n",planeDir[0],planeDir[1],planeDir[2]);

    slicingPlane.Init(planeCenter+planeDir*0.3f*m.bbox.Diag()*float(rand())/RAND_MAX,planeDir);

    vcg::IntersectionPlaneMesh<MyMesh, MyMesh, float>(m, slicingPlane, em );
    tri::Clean<MyMesh>::RemoveDuplicateVertex(em);
    vcg::tri::CapEdgeMesh(em,cm);

    printf("  edge mesh vn %5i en %5i fn %5i\n",em.vn,em.en,em.fn);
    printf("sliced mesh vn %5i en %5i fn %5i\n",cm.vn,cm.en,cm.fn);

    tri::Append<MyMesh,MyMesh>::Mesh(full,cm);
  }

  tri::io::ExporterPLY<MyMesh>::Save(full,"out.ply",false);

  return 0;
}
Example #3
0
void GetRandPlane(Box3f &bb, Plane3f &plane)
{
    Point3f planeCenter = bb.Center();
    Point3f planeDir = Point3f(-0.5f+float(rand())/RAND_MAX,-0.5f+float(rand())/RAND_MAX,-0.5f+float(rand())/RAND_MAX);
    planeDir.Normalize();

    plane.Init(planeCenter+planeDir*0.3f*bb.Diag()*float(rand())/RAND_MAX,planeDir);
}
//----------------------------------------------------------------------------
void BouncingTetrahedra::CalculateNormal (const Vector3f* vertices,
    const Vector3f& closest, Contact& contact)
{
    float diff = Mathf::MAX_REAL;
    for (int i = 0; i < 4; ++i)
    {
        Plane3f plane = Plane3f(vertices[mFaces[i][0]],
            vertices[mFaces[i][1]], vertices[mFaces[i][2]]);

        float temp = Mathf::FAbs(plane.DistanceTo(closest));
        if (temp < diff)
        {
            contact.N = plane.Normal;
            diff = temp;
        }
    }
}
Example #5
0
int main( int argc, char **argv )
{
    if(argc<2)
    {
        printf("Usage trimesh_base <meshfilename.ply>\n");
        return -1;
    }

    MyMesh m, // The loaded mesh
           em, // the 2D polyline representing the section
           slice, // the planar mesh resulting from the triangulation of the above
           sliced; // the 3D mesh resulting by the actual slicing of m into two capped sub pieces

    if(tri::io::ImporterPLY<MyMesh>::Open(m,argv[1])!=0)
    {
        printf("Error reading file  %s\n",argv[1]);
        exit(0);
    }
    tri::UpdateBounding<MyMesh>::Box(m);
    printf("Input mesh  vn:%i fn:%i\n",m.vn,m.fn);
    srand(time(0));

    Plane3f slicingPlane;
    GetRandPlane(m.bbox,slicingPlane);
    printf("slicing dir %5.2f %5.2f %5.2f\n",slicingPlane.Direction()[0],slicingPlane.Direction()[1],slicingPlane.Direction()[2]);
    vcg::IntersectionPlaneMesh<MyMesh, MyMesh, float>(m, slicingPlane, em );
    tri::Clean<MyMesh>::RemoveDuplicateVertex(em);
    vcg::tri::CapEdgeMesh(em,slice);
    printf("Slice  mesh has %i vert and %i faces\n", slice.vn, slice.fn );

    MyMesh A,B;
    bool ret=SplitMesh(m,A,B,slicingPlane);
    tri::UpdatePosition<MyMesh>::Translate(A, slicingPlane.Direction()*m.bbox.Diag()/80.0);
    tri::UpdatePosition<MyMesh>::Translate(B,-slicingPlane.Direction()*m.bbox.Diag()/80.0);
    tri::Append<MyMesh,MyMesh>::Mesh(sliced,A);
    tri::Append<MyMesh,MyMesh>::Mesh(sliced,B);
    printf("Sliced mesh has %i vert and %i faces\n", sliced.vn, sliced.fn );

    tri::io::ExporterPLY<MyMesh>::Save(slice,"slice.ply",false);
    tri::io::ExporterPLY<MyMesh>::Save(sliced,"sliced.ply",false);

    return 0;
}
Example #6
0
// static
bool GeometryUtils::rayPlaneIntersection( const Vector3f& rayOrigin,
                                         const Vector3f& rayDirection,
                                         const Plane3f& plane,
                                         float& t )
{
    // ray: P = O + tD
    // plane: P dot N + d = 0
    // (O + tD) dot N + d = 0
    // --> t = -(O dot N + d
    float den = Vector3f::dot( rayDirection, plane.normal() );

    // TODO: epsilon
    if( abs( den ) > EPSILON )
    {
        float num = -Vector3f::dot( rayOrigin, plane.normal() ) - plane.d;
        t = num / den;
        return ( t > 0 );
    }
    return false;
}
Example #7
0
bool two_plane_intersection(Vector3f& p, Vector3f& d, const Plane3f& p0, const Plane3f& p1)
{
    // Compute \f$\vec{d} = \hat{n}_0 \times \hat{n}_1\f$
    const Vector3f &n0 = p0.getNormal();
    const Vector3f &n1 = p1.getNormal();
    d = n0.cross(n1);
    
    // If \f$\vec{v}\f$ is the zero vector, then the planes do not intersect.
    if (0 == d.normalize()) {
        return false;
    }
    if (0.0f != d[kZ])
    {
        p[kX] = (n0[kY] * n1[kW] - n0[kW] * n1[kY]) / d[kZ];
        p[kY] = (n0[kW] * n1[kX] - n0[kX] * n1[kW]) / d[kZ];
        p[kZ] = 0.0f;
    }
    else
    {
        throw std::runtime_error("not yet supported");
    }
    return true;
}
Example #8
0
bool three_plane_intersection(Vector3f& dst_pos, const Plane3f& p0, const Plane3f& p1, const Plane3f& p2)
{
	Vector3f n0 = p0.getNormal(),
             n1 = p1.getNormal(),
             n2 = p2.getNormal();
    float d0 = p0.getDistance(),
          d1 = p1.getDistance(),
          d2 = p2.getDistance();
    // the determinant of the matrix
    float det =
        n0[kX] * (n1[kY] * n2[kZ] - n1[kZ] * n2[kY]) -
        n0[kY] * (n1[kX] * n2[kZ] - n2[kX] * n1[kZ]) +
        n0[kZ] * (n1[kX] * n2[kY] - n2[kX] * n1[kY]);

    // check for system that is too close to being degenerate
    if (std::abs(det) < 1e-6) return false;

    float tmp;

    // the x component
    tmp =
        d0 * (n1[kZ] * n2[kY] - n1[kY] * n2[kZ]) +
        d1 * (n0[kY] * n2[kZ] - n0[kZ] * n2[kY]) +
        d2 * (n0[kZ] * n1[kY] - n0[kY] * n1[kZ]);
    dst_pos[kX] = tmp / det;

    // the y component
    tmp =
        d0 * (n1[kX] * n2[kZ] - n1[kZ] * n2[kX]) +
        d1 * (n0[kZ] * n2[kX] - n0[kX] * n2[kZ]) +
        d2 * (n0[kX] * n1[kZ] - n0[kZ] * n1[kX]);
    dst_pos[kY] = tmp / det;

    // the z component
    tmp =
        d0 * (n1[kY] * n2[kX] - n1[kX] * n2[kY]) +
        d1 * (n0[kX] * n2[kY] - n0[kY] * n2[kX]) +
        d2 * (n0[kY] * n1[kX] - n0[kX] * n1[kY]);
    dst_pos[kZ] = tmp / det;

    return true;
}
Example #9
0
void Molecule3dConstraintsChecker::_cache (int idx)
{
   if (_cache_v.find(idx) || _cache_l.find(idx) || _cache_p.find(idx))
      return;

   const MC::Base &base = _constraints.at(idx);

   switch (base.type)
   {
      case MC::POINT_ATOM:
      {
         int atom_idx = ((const Molecule3dConstraints::PointByAtom &)base).atom_idx;

         _cache_v.insert(idx, _target->getAtomXyz(_mapping[atom_idx]));
         break;
      }
      case MC::POINT_DISTANCE:
      {
         const MC::PointByDistance &constr = (const MC::PointByDistance &)base;

         _cache(constr.beg_id);
         _cache(constr.end_id);

         const Vec3f &beg = _cache_v.at(constr.beg_id);
         const Vec3f &end = _cache_v.at(constr.end_id);
         Vec3f dir;

         dir.diff(end, beg);

         if (!dir.normalize())
            throw Error("point-by-distance: degenerate case");

         Vec3f res;

         res.lineCombin(beg, dir, constr.distance);

         _cache_v.insert(idx, res);
         break;
      }
      case MC::POINT_PERCENTAGE:
      {
         const MC::PointByPercentage &constr = (const MC::PointByPercentage &)base;

         _cache(constr.beg_id);
         _cache(constr.end_id);

         const Vec3f &beg = _cache_v.at(constr.beg_id);
         const Vec3f &end = _cache_v.at(constr.end_id);
         Vec3f dir;

         dir.diff(end, beg);

         if (!dir.normalize())
            throw Error("point-by-percentage: degenerate case");

         Vec3f res;

         res.lineCombin2(beg, 1.f - constr.percentage, end, constr.percentage);

         _cache_v.insert(idx, res);
         break;
      }
      case MC::POINT_NORMALE:
      {
         const MC::PointByNormale &constr = (const MC::PointByNormale &)base;

         _cache(constr.org_id);
         _cache(constr.norm_id);

         const Vec3f &org = _cache_v.at(constr.org_id);
         const Line3f &norm = _cache_l.at(constr.norm_id);

         Vec3f res;

         res.lineCombin(org, norm.dir, constr.distance);
         _cache_v.insert(idx, res);
         break;
      }
      case MC::POINT_CENTROID:
      {
         const MC::Centroid &constr = (const MC::Centroid &)base;

         Vec3f res;

         if (constr.point_ids.size() < 1)
            throw Error("centroid: have %d points", constr.point_ids.size());

         for (int i = 0; i < constr.point_ids.size(); i++)
         {
            _cache(constr.point_ids[i]);

            const Vec3f &pt = _cache_v.at(constr.point_ids[i]);

            res.add(pt);
         }
         
         res.scale(1.f / constr.point_ids.size());
         _cache_v.insert(idx, res);
         break;
      }
      case MC::LINE_NORMALE:
      {
         const MC::Normale &constr = (const MC::Normale &)base;

         _cache(constr.plane_id);
         _cache(constr.point_id);

         const Plane3f &plane = _cache_p.at(constr.plane_id);
         const Vec3f &point = _cache_v.at(constr.point_id);

         Vec3f projection;
         Line3f res;

         plane.projection(point, projection);

         res.dir.copy(plane.getNorm());
         res.org.copy(projection);

         _cache_l.insert(idx, res);
         break;
      }
      case MC::LINE_BEST_FIT:
      {
         const MC::BestFitLine &constr = (const MC::BestFitLine &)base;

         if (constr.point_ids.size() < 2)
            throw Error("best fit line: only %d points", constr.point_ids.size());

         QS_DEF(Array<Vec3f>, points);

         points.clear();
         for (int i = 0; i < constr.point_ids.size(); i++)
         {
            _cache(constr.point_ids[i]);
            points.push(_cache_v.at(constr.point_ids[i]));
         }

         Line3f res;

         res.bestFit(points.size(), points.ptr(), 0);

         _cache_l.insert(idx, res);
         break;
      }
      case MC::PLANE_BEST_FIT:
      {
         const MC::BestFitPlane &constr = (const MC::BestFitPlane &)base;

         if (constr.point_ids.size() < 3)
            throw Error("best fit line: only %d points", constr.point_ids.size());

         QS_DEF(Array<Vec3f>, points);

         points.clear();
         for (int i = 0; i < constr.point_ids.size(); i++)
         {
            _cache(constr.point_ids[i]);
            points.push(_cache_v.at(constr.point_ids[i]));
         }

         Plane3f res;

         res.bestFit(points.size(), points.ptr(), 0);

         _cache_p.insert(idx, res);
         break;
      }
      case MC::PLANE_POINT_LINE:
      {
         const MC::PlaneByPoint &constr = (const MC::PlaneByPoint &)base;

         _cache(constr.point_id);
         _cache(constr.line_id);

         const Vec3f &point = _cache_v.at(constr.point_id);
         const Line3f &line = _cache_l.at(constr.line_id);

         Plane3f res;

         res.byPointAndLine(point, line);

         _cache_p.insert(idx, res);
         break;
      }
      default:
         throw Error("unknown constraint type %d", base.type);
   }
}
Example #10
0
bool ExtraFilter_SlicePlugin::applyFilter(QAction *filter, MeshDocument &m, RichParameterSet &parlst, vcg::CallBackPos *cb)
{
    vcg::tri::UpdateBounding<CMeshO>::Box(m.mm()->cm);

    switch(ID(filter))
    {
        case FP_WAFFLE_SLICE :
        {
            MeshModel* base = m.mm();
            CMeshO &cmBase = base->cm;
            Box3f &bbox = m.mm()->cm.bbox;

            if (tri::Clean<CMeshO>::CountNonManifoldEdgeFF(cmBase)>0 || (tri::Clean<CMeshO>::CountNonManifoldVertexFF(cmBase,false) != 0))
            {
                Log("Mesh is not two manifold, cannot apply filter");
                return false;
            }
            if(parlst.getFloat("spacing") >= 1)
            {
                Log("the selected distance between the planes is greater than 1. The filter had no effect");
                return false;
            }

            Point3f planeAxis(0,0,0);
            Axis axis = (Axis) parlst.getEnum("planeAxis");
            planeAxis[axis] = 1.0f;

            float length = parlst.getFloat("length");

            bool hideBase = parlst.getBool("hideBase");
            bool hideEdge = parlst.getBool("hideEdge");
            bool hidePlanes = parlst.getBool("hidePlanes");
            bool hideExtrudes = parlst.getBool("hideExtrudes");

            // set common SVG Properties
            const float maxdim=m.mm()->cm.bbox.Dim()[m.mm()->cm.bbox.MaxDim()];

            Point3f sizeCm=m.mm()->cm.bbox.Dim()*(length/maxdim);
            // to check for dimensions with custom axis
            Axis axisOrthog, axisJoint;
            Point2f sizeCmOrth;
            switch(axis)
            {
            case X:
                {
                    axisOrthog = (Axis) Succ<X>::value;
                    axisJoint = (Axis) Succ<Succ<X>::value>::value;
                    pr.sizeCm = Point2f(sizeCm[1],sizeCm[2]);
                    sizeCmOrth.X()=sizeCm[0];
                    sizeCmOrth.Y()=sizeCm[2];
                }
                break;
            case Y:
                {
                    axisOrthog = (Axis) Succ<Y>::value;
                    axisJoint = (Axis) Succ<Succ<Y>::value>::value;
                    pr.sizeCm = Point2f(sizeCm[0],sizeCm[2]);
                    sizeCmOrth.X()=sizeCm[0];
                    sizeCmOrth.Y()=sizeCm[1];
                }
                break;
            case Z:
                {
                    axisOrthog = (Axis) Succ<Z>::value;
                    axisJoint = (Axis) Succ<Succ<Z>::value>::value;
                    pr.sizeCm = Point2f(sizeCm[0],sizeCm[1]);
                    sizeCmOrth.X()=sizeCm[1];
                    sizeCmOrth.Y()=sizeCm[2];
                }
                break;
            }

            Log("sizecm %fx%f",pr.sizeCm[0],pr.sizeCm[1]);

            vector<CMeshO*> ev;

            const float planeDist = maxdim * parlst.getFloat("spacing");
            const int planeNum = (planeDist == 0) ? 1 : ( ((bbox.Dim()*planeAxis)/planeDist)+1 ); //evito la divisione per 0
            const float lengthDiag = bbox.Diag()/2.0;

            Segment2f lati[3]; //the rectangle is made up of three segments, the fourth side is ignored, so I never use it

            const float eps =planeDist*parlst.getFloat("eps");
            float epsTmp;
            float start;
            int rectNum;
            if(parlst.getFloat("eps") < 1)
            {
                start = - (planeNum/2) * planeDist;   //I have to go back from the center of half the length
                epsTmp = eps/2.0;
                generateRectSeg(0, epsTmp, bbox.Diag()*2, lati);
                rectNum = planeNum;
            }
            else
            {
                start = 0;
                epsTmp = bbox.Diag();
                generateRectSeg(0, bbox.Diag()*2, bbox.Diag()*2, lati);
                rectNum = 1;
                Log("thickness is greater than 1: the extrusions will overlap");
            }

            float planeOffset = parlst.getFloat("planeOffset");

            pr.lineWidthPt=200;
            pr.scale=2/maxdim;
            pr.numCol=(int)(max((int)sqrt(planeNum*1.0f),2)+1);
            pr.numRow=(int)(planeNum*1.0f/pr.numCol)+1;
            pr.projDir = planeAxis;
            pr.projCenter =  m.mm()->cm.bbox.Center();
            pr.enumeration = true;

            MeshModel* cap, *cap2, *extr;
            QString layername;


            for(int pl = 0; pl < 2; ++pl)
            {
//                Log("################## PLANE %i", pl);
                Plane3f slicingPlane;
                Point3f planeCenter = bbox.Center() + planeAxis*planeOffset*lengthDiag;
                int numAdd = 0;

//                int i=4;  //if I want to apply only the plan number i I decomment this variable and comment the cycle
                for(int i = 0; i < planeNum; ++i)   //cropping the plans
                {
//                    Log("######## LAYER %i", i);
                    planeCenter[axis] = start + planeDist*i;;

                    slicingPlane.Init(planeCenter,planeAxis);

                    layername.sprintf("EdgeMesh_%d_%d",pl,numAdd);
                    cap= m.addNewMesh("",qPrintable(layername));
                    vcg::IntersectionPlaneMesh<CMeshO, CMeshO, float>(base->cm, slicingPlane, cap->cm );

                    tri::Clean<CMeshO>::RemoveDuplicateVertex(cap->cm);
                    if(cap->cm.edge.size()>= 3)
                    {
                        Incastri temp;

//                        int j=1;      //if I want to apply only the rectangle number j I decomment this variable and comment the cycle
                        for(int j = 0; j <rectNum ; ++j)   //clipping the rectangles
                        {
//                            Log("#### RECTANGLE %i", j);
                            float newDist = start + planeDist*j;
                            modifyOnY(lati, newDist+epsTmp, newDist-epsTmp);

                            temp = subtraction(cap->cm, lati, axis, axisOrthog, axisJoint, planeCenter[axis]);

                            if(temp == NOT_PLANE) {Log("ATTENTION! The IntersectionPlaneMesh did not return a plane silhouette in the current plane!"); m.delMesh(cap); break;}
                            if(temp== NOT_SAGOME) {Log("ATTENTION! The IntersectionPlaneMesh did not return a simple closed silhouette for the plane %i, on axis %i",i, pl); m.delMesh(cap); break;}
                        }
                        if(temp > NOT_SAGOME)
                        {
                            ev.push_back(&(cap->cm));   //add the silhouette to those for export to SVG

                            layername.sprintf("CappedSlice_%d_%d",pl,numAdd);   //add the silhouettes converted in mesh
                            cap2= m.addNewMesh("",qPrintable(layername));
                            tri::CapEdgeMesh(cap->cm, cap2->cm);

                            layername.sprintf("Extruded_%d_%d",pl,numAdd++);      //add the mesh extruded
                            extr= m.addNewMesh("",qPrintable(layername));
                            cap2->updateDataMask(MeshModel::MM_FACEFACETOPO);
                            extr->updateDataMask(MeshModel::MM_FACEFACETOPO);
                            tri::UpdateTopology<CMeshO>::FaceFace(cap2->cm);
                            tri::ExtrudeBoundary<CMeshO>(cap2->cm,extr->cm,eps,planeAxis);

                            if(hideEdge) cap->visible =false;
                            if(hidePlanes) cap2->visible =false;
                            if(hideExtrudes) extr->visible =false;
                        }
                    }else m.delMesh(cap);   //if the intersection does not exist I reject the result
                }

                QString fname;//= parlst.getSaveFileName("filename");
                if(fname=="") fname.sprintf("Slice_%d.svg",pl);
                if (!fname.endsWith(".svg")) fname+=".svg";
                tri::io::ExporterSVG<CMeshO>::Save(ev, fname.toStdString().c_str(), pr);

                ev.clear();

                planeAxis[axis] = 0.0f;
                planeAxis[axisOrthog] = 1.0f;

                flipOnX(lati);

                pr.sizeCm = sizeCmOrth;
                pr.projDir = planeAxis;

                Axis aSwap = axis;
                axis = axisOrthog;
                axisOrthog = aSwap;
            }


            if(hideEdge) cap->visible =false;
            if(hidePlanes) cap2->visible =false;
            if(hideExtrudes) extr->visible =false;

            if(hideBase) base->visible =false;
            if(hideBase) base->visible =false;

        }
        break;
    }
    return true;
}
Example #11
0
// static
float Plane3f::cosineDihedralAngle( const Plane3f& p0, const Plane3f& p1 )
{
    return Vector3f::dot( p0.unitNormal(), p1.unitNormal() );
}