示例#1
0
/// utility non-class member functions
//! Returns the centroid of shape, as viewed according to direction and xAxis
gp_Pnt TechDrawGeometry::findCentroid(const TopoDS_Shape &shape,
                                      const Base::Vector3d &direction,
                                      const Base::Vector3d &xAxis)
{
    gp_Ax2 viewAxis;
    viewAxis = gp_Ax2(gp_Pnt(0, 0, 0),
                      gp_Dir(direction.x, -direction.y, direction.z),
                      gp_Dir(xAxis.x, -xAxis.y, xAxis.z)); // Y invert warning!

    gp_Trsf tempTransform;
    tempTransform.SetTransformation(viewAxis);
    BRepBuilderAPI_Transform builder(shape, tempTransform);

    Bnd_Box tBounds;
    BRepBndLib::Add(builder.Shape(), tBounds);

    tBounds.SetGap(0.0);
    Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
    tBounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);

    Standard_Real x = (xMin + xMax) / 2.0,
                  y = (yMin + yMax) / 2.0,
                  z = (zMin + zMax) / 2.0;

    // Get centroid back into object space
    tempTransform.Inverted().Transforms(x, y, z);

    return gp_Pnt(x, y, z);
}
bool CTiglAbstractGeometricComponent::GetIsOn(const gp_Pnt& pnt) 
{
    const TopoDS_Shape& segmentShape = GetLoft()->Shape();

    // fast check with bounding box
    Bnd_Box boundingBox;
    BRepBndLib::Add(segmentShape, boundingBox);

    Standard_Real xmin, xmax, ymin, ymax, zmin, zmax;
    boundingBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);

    if (pnt.X() < xmin || pnt.X() > xmax ||
        pnt.Y() < ymin || pnt.Y() > ymax ||
        pnt.Z() < zmin || pnt.Z() > zmax) {

        return false;
    }

    double tolerance = 0.03; // 3cm

    BRepClass3d_SolidClassifier classifier;
    classifier.Load(segmentShape);
    classifier.Perform(pnt, tolerance);
    if ((classifier.State() == TopAbs_IN) || (classifier.State() == TopAbs_ON)) {
        return true;
    }
    else {
        return false;
    }
}
//! Returns the centroid of shape, as viewed according to direction
gp_Pnt TechDrawGeometry::findCentroid(const TopoDS_Shape &shape,
                                    const Base::Vector3d &direction)
{
    Base::Vector3d origin(0.0,0.0,0.0);
    gp_Ax2 viewAxis = getViewAxis(origin,direction);

    gp_Trsf tempTransform;
    tempTransform.SetTransformation(viewAxis);
    BRepBuilderAPI_Transform builder(shape, tempTransform);

    Bnd_Box tBounds;
    BRepBndLib::Add(builder.Shape(), tBounds);

    tBounds.SetGap(0.0);
    Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
    tBounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);

    Standard_Real x = (xMin + xMax) / 2.0,
                  y = (yMin + yMax) / 2.0,
                  z = (zMin + zMax) / 2.0;

    // Get centroid back into object space
    tempTransform.Inverted().Transforms(x, y, z);

    return gp_Pnt(x, y, z);
}
Base::BoundBox3d PropertyPartShape::getBoundingBox() const
{
    Base::BoundBox3d box;
    if (_Shape._Shape.IsNull())
        return box;
    try {
        // If the shape is empty an exception may be thrown
        Bnd_Box bounds;
        BRepBndLib::Add(_Shape._Shape, bounds);
        bounds.SetGap(0.0);
        Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
        bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);

        box.MinX = xMin;
        box.MaxX = xMax;
        box.MinY = yMin;
        box.MaxY = yMax;
        box.MinZ = zMin;
        box.MaxZ = zMax;
    }
    catch (Standard_Failure) {
    }

    return box;
}
示例#5
0
void InventorShape::computeShape() {
    Bnd_Box bounds;
    BRepBndLib::Add(shape->getShape(), bounds);
    bounds.SetGap(0.0);
    Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
    bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);
    Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * 0.2;
    BRepMesh::Mesh(shape->getShape(), deflection);

    SoGroup* faces = new SoGroup();

    computeFaces(faces, shape->getShape());

    separator->addChild(faces);

    SoGroup* edges = new SoGroup();
    computeEdges(edges, shape->getShape());

    separator->addChild(edges);

    SoGroup* vertices = new SoGroup();
    computeVertices(vertices, shape->getShape());

    separator->addChild(vertices);
}
示例#6
0
// Returns the coordinates of the bounding box of the shape
void GetShapeExtension(const TopoDS_Shape& shape,
                       double& minx, double& maxx,
                       double& miny, double& maxy,
                       double& minz, double& maxz)
{
    Bnd_Box boundingBox;
    BRepBndLib::Add(shape, boundingBox);
    boundingBox.Get(minx, miny, minz, maxx, maxy, maxz);
}
示例#7
0
SBoundingBox3d OCCEdge::bounds() const
{
  Bnd_Box b;
  BRepBndLib::Add(c, b);
  double xmin, ymin, zmin, xmax, ymax, zmax;
  b.Get(xmin, ymin, zmin, xmax, ymax, zmax);
  SBoundingBox3d bbox(xmin, ymin, zmin, xmax, ymax, zmax);
  return bbox;
}
示例#8
0
//-------------------------------------------------------------------------
// Purpose       : Get the bounding box of the object.
//
// Special Notes :
//
//-------------------------------------------------------------------------
CubitBox OCCSurface::bounding_box() const 
{
  TopoDS_Face face = *myTopoDSFace;
  BRepAdaptor_Surface asurface(face);
  Bnd_Box aBox;
  BndLib_AddSurface::Add(asurface, Precision::Approximation(), aBox);
  double min[3], max[3];
  aBox.Get( min[0], min[1], min[2], max[0], max[1], max[2]);
  return CubitBox(min, max);
}
TopoDS_Shape ProjectionAlgos::invertY(const TopoDS_Shape& shape)
{
    // make sure to have the y coordinates inverted
    gp_Trsf mat;
    Bnd_Box bounds;
    BRepBndLib::Add(shape, bounds);
    bounds.SetGap(0.0);
    Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
    bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);
    mat.SetMirror(gp_Ax2(gp_Pnt((xMin+xMax)/2,(yMin+yMax)/2,(zMin+zMax)/2), gp_Dir(0,1,0)));
    BRepBuilderAPI_Transform mkTrf(shape, mat);
    return mkTrf.Shape();
}
Base::BoundBox3d GeometryObject::calcBoundingBox() const
{
    Bnd_Box testBox;
    testBox.SetGap(0.0);
    for (std::vector<BaseGeom *>::const_iterator it( edgeGeom.begin() );
            it != edgeGeom.end(); ++it) {
         BRepBndLib::Add((*it)->occEdge, testBox);
    }
    if (testBox.IsVoid()) {
        Base::Console().Log("INFO - GO::calcBoundingBox - testBox is void\n");
    }
    double xMin,xMax,yMin,yMax,zMin,zMax;
    testBox.Get(xMin,yMin,zMin,xMax,yMax,zMax);

    Base::BoundBox3d bbox(xMin,yMin,zMin,xMax,yMax,zMax);
    return bbox;
}
示例#11
0
//=======================================================================
//function : CheckTriangulation
//purpose  :
//=======================================================================
bool GEOMUtils::CheckTriangulation (const TopoDS_Shape& aShape)
{
  bool isTriangulation = true;

  TopExp_Explorer exp (aShape, TopAbs_FACE);
  if (exp.More())
  {
    TopLoc_Location aTopLoc;
    Handle(Poly_Triangulation) aTRF;
    aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc);
    if (aTRF.IsNull()) {
      isTriangulation = false;
    }
  }
  else // no faces, try edges
  {
    TopExp_Explorer expe (aShape, TopAbs_EDGE);
    if (!expe.More()) {
      return false;
    }
    TopLoc_Location aLoc;
    Handle(Poly_Polygon3D) aPE = BRep_Tool::Polygon3D(TopoDS::Edge(expe.Current()), aLoc);
    if (aPE.IsNull()) {
      isTriangulation = false;
    }
  }

  if (!isTriangulation) {
    // calculate deflection
    Standard_Real aDeviationCoefficient = 0.001;

    Bnd_Box B;
    BRepBndLib::Add(aShape, B);
    Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
    B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);

    Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin;
    Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4;
    Standard_Real aHLRAngle = 0.349066;

    BRepMesh_IncrementalMesh Inc (aShape, aDeflection, Standard_False, aHLRAngle);
  }

  return true;
}
示例#12
0
OCCMesh *OCCFace::createMesh(double factor, double angle, bool qualityNormals = true)
{
    OCCMesh *mesh = new OCCMesh();
    
    try {
        Bnd_Box aBox;
        BRepBndLib::Add(this->getShape(), aBox);
        
        Standard_Real aXmin, aYmin, aZmin;
        Standard_Real aXmax, aYmax, aZmax;
        aBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
        
        Standard_Real maxd = fabs(aXmax - aXmin);
        maxd = std::max(maxd, fabs(aYmax - aYmin));
        maxd = std::max(maxd, fabs(aZmax - aZmin));
        
        BRepMesh_FastDiscret MSH(factor*maxd, angle, aBox, Standard_False, Standard_False, 
                                 Standard_True, Standard_True);
        
        MSH.Perform(this->getShape());
        
        BRepMesh_IncrementalMesh(this->getShape(),factor*maxd);
        
        if (this->getShape().ShapeType() != TopAbs_FACE) {
            TopExp_Explorer exFace;
            for (exFace.Init(this->getShape(), TopAbs_FACE); exFace.More(); exFace.Next()) {
                const TopoDS_Face& faceref = static_cast<const TopoDS_Face &>(exFace.Current());
                mesh->extractFaceMesh(faceref, qualityNormals);
            }
        } else {
            mesh->extractFaceMesh(this->getFace(), qualityNormals);
        }
    } catch(Standard_Failure &err) {
        Handle_Standard_Failure e = Standard_Failure::Caught();
        const Standard_CString msg = e->GetMessageString();
        if (msg != NULL && strlen(msg) > 1) {
            setErrorMessage(msg);
        } else {
            setErrorMessage("Failed to create mesh");
        }
        return NULL;
    }
    return mesh;
}
示例#13
0
//----------------------------------------------------------------
// Function: update_bounding_box
// Description: calculate for bounding box of this OCCBody
//
// Author: janehu
//----------------------------------------------------------------
void OCCBody::update_bounding_box() 
{
  Bnd_Box box;
  TopoDS_Shape shape;
    
  for (int i = 0; i <  myLumps.size(); i++)
  {
     OCCLump *lump = CAST_TO(myLumps.get_and_step(), OCCLump);
     shape = *lump->get_TopoDS_Solid();
     BRepBndLib::Add(shape, box);
  }

  for(int i = 0; i < mySheetSurfaces.size(); i++)
  {
    OCCSurface* surface = mySheetSurfaces.get_and_step();
    shape = *surface->get_TopoDS_Face();
    BRepBndLib::Add(shape, box);
  }

  for(int i = 0; i <myShells.size() ; i++)
  {
    OCCShell* occ_shell = myShells.get_and_step();
    shape = *occ_shell->get_TopoDS_Shell();
    BRepBndLib::Add(shape, box);
  }
 
  //calculate the bounding box
  if(myLumps.size() + mySheetSurfaces.size() + myShells.size() == 0)
  {
    if(!myTopoDSShape)
      return;
    TopoDS_Shape shape = *myTopoDSShape;
    BRepBndLib::Add(shape, box);
  }
  
  double min[3], max[3];

  //get values
  box.Get(min[0], min[1], min[2], max[0], max[1], max[2]);

  //update boundingbox.
  boundingbox.reset(min, max);
}
void SetupResultBoundingBox::go(ResultEntry *entry)
{
    entry->boxSep = new SoSeparator();
    entry->viewProvider->getRoot()->addChild(entry->boxSep);
    entry->boxSwitch = new SoSwitch();
    entry->boxSep->addChild(entry->boxSwitch);
    SoGroup *group = new SoGroup();
    entry->boxSwitch->addChild(group);
    entry->boxSwitch->whichChild.setValue(SO_SWITCH_NONE);
    SoDrawStyle *dStyle = new SoDrawStyle();
    dStyle->style.setValue(SoDrawStyle::LINES);
    dStyle->linePattern.setValue(0xc0c0);
    group->addChild(dStyle);
    SoMaterial *material = new SoMaterial();
    material->diffuseColor.setValue(255.0, 255.0, 255.0);
    material->ambientColor.setValue(255.0, 255.0, 255.0);
    group->addChild(material);

    Bnd_Box boundingBox;
    BRepBndLib::Add(entry->shape, boundingBox);
    Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
    boundingBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);

    double xCenter, yCenter, zCenter;
    xCenter = (xmax - xmin)/2 + xmin;
    yCenter = (ymax - ymin)/2 + ymin;
    zCenter = (zmax - zmin)/2 + zmin;

    SbVec3f boundCenter(xCenter, yCenter, zCenter);
    Standard_Real x, y, z;
    entry->shape.Location().Transformation().TranslationPart().Coord(x, y, z);
    boundCenter -= SbVec3f(x, y, z);

    SoTransform *position = new SoTransform();
    position->translation.setValue(boundCenter);
    group->addChild(position);

    SoCube *cube = new SoCube();
    cube->width.setValue(xmax - xmin);
    cube->height.setValue(ymax - ymin);
    cube->depth.setValue(zmax - zmin);
    group->addChild(cube);
}
示例#15
0
void PartGui::goSetupResultBoundingBox(ResultEntry *entry)
{
    //empty compound throws bounding box error. Mantis #0001426
    try
    {
      Bnd_Box boundingBox;
      BRepBndLib::Add(entry->shape, boundingBox);
      Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
      boundingBox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
      SbVec3f boundCenter((xmax - xmin)/2 + xmin, (ymax - ymin)/2 + ymin, (zmax - zmin)/2 + zmin);
  
      entry->boxSep = new SoSeparator();
      entry->viewProviderRoot->addChild(entry->boxSep);
      entry->boxSwitch = new SoSwitch();
      entry->boxSep->addChild(entry->boxSwitch);
      SoGroup *group = new SoGroup();
      entry->boxSwitch->addChild(group);
      entry->boxSwitch->whichChild.setValue(SO_SWITCH_NONE);
      SoDrawStyle *dStyle = new SoDrawStyle();
      dStyle->style.setValue(SoDrawStyle::LINES);
      dStyle->linePattern.setValue(0xc0c0);
      group->addChild(dStyle);
      SoMaterial *material = new SoMaterial();
      material->diffuseColor.setValue(255.0, 255.0, 255.0);
      material->ambientColor.setValue(255.0, 255.0, 255.0);
      group->addChild(material);

      SoResetTransform *reset = new SoResetTransform();
      group->addChild(reset);
      
      SoTransform *position = new SoTransform();
      position->translation.setValue(boundCenter);
      group->addChild(position);

      SoCube *cube = new SoCube();
      cube->width.setValue(xmax - xmin);
      cube->height.setValue(ymax - ymin);
      cube->depth.setValue(zmax - zmin);
      group->addChild(cube);
    }
    catch (const Standard_Failure &){}
}
示例#16
0
文件: vsocc.cpp 项目: 11235813/netgen
   void VisualSceneOCCGeometry :: BuildScene (int zoomall)
   {
     if (occgeometry -> changed == OCCGEOMETRYVISUALIZATIONFULLCHANGE)
       {
         occgeometry -> BuildVisualizationMesh (vispar.occdeflection);

         center = occgeometry -> Center();
         rad = occgeometry -> GetBoundingBox().Diam() / 2;

         if (vispar.occzoomtohighlightedentity)
         {
            bool hilite = false;
            bool hiliteonepoint = false;
            Bnd_Box bb;

            for (int i = 1; i <= occgeometry->fmap.Extent(); i++)
            if (occgeometry->fvispar[i-1].IsHighlighted())
            {
               hilite = true;
               BRepBndLib::Add (occgeometry->fmap(i), bb);
            }

            for (int i = 1; i <= occgeometry->emap.Extent(); i++)
            if (occgeometry->evispar[i-1].IsHighlighted())
            {
               hilite = true;
               BRepBndLib::Add (occgeometry->emap(i), bb);
            }

            for (int i = 1; i <= occgeometry->vmap.Extent(); i++)
            if (occgeometry->vvispar[i-1].IsHighlighted())
            {
               hiliteonepoint = true;
               BRepBndLib::Add (occgeometry->vmap(i), bb);
            }

            if (hilite || hiliteonepoint)
            {
               double x1,y1,z1,x2,y2,z2;
               bb.Get (x1,y1,z1,x2,y2,z2);
               Point<3> p1 = Point<3> (x1,y1,z1);
               Point<3> p2 = Point<3> (x2,y2,z2);
               Box<3> boundingbox(p1,p2);

               center = boundingbox.Center();
               if (hiliteonepoint)
               rad = occgeometry -> GetBoundingBox().Diam() / 100;
               else
               rad = boundingbox.Diam() / 2;
            }
         }

         CalcTransformationMatrices();
      }

      // Clear lists

      for (int i = 1; i <= linelists.Size(); i++)
      glDeleteLists (linelists.Elem(i), 1);
      linelists.SetSize(0);

      for (int i = 1; i <= trilists.Size(); i++)
      glDeleteLists (trilists.Elem(i), 1);
      trilists.SetSize(0);

      // Total wireframe

      linelists.Append (glGenLists (1));
      glNewList (linelists.Last(), GL_COMPILE);

      for (int i = 1; i <= occgeometry->emap.Extent(); i++)
      {
         TopoDS_Edge edge = TopoDS::Edge(occgeometry->emap(i));
         if (BRep_Tool::Degenerated(edge)) continue;
         if (occgeometry->evispar[i-1].IsHighlighted()) continue;

         Handle(Poly_PolygonOnTriangulation) aEdgePoly;
         Handle(Poly_Triangulation) T;
         TopLoc_Location aEdgeLoc;
         BRep_Tool::PolygonOnTriangulation(edge, aEdgePoly, T, aEdgeLoc);

         if(aEdgePoly.IsNull())
         {
            (*testout) << "visualizing edge " << occgeometry->emap.FindIndex (edge)
            << " without using the occ visualization triangulation" << endl;

            double s0, s1;
            Handle(Geom_Curve) c = BRep_Tool::Curve(edge, s0, s1);

            glBegin (GL_LINE_STRIP);
            for (int i = 0; i<=50; i++)
            {
               gp_Pnt p = c->Value (s0 + i*(s1-s0)/50.0);
               glVertex3f (p.X(),p.Y(),p.Z());
            }
            glEnd ();

            continue;
         }

         int nbnodes = aEdgePoly -> NbNodes();
         glBegin (GL_LINE_STRIP);
         for (int j = 1; j <= nbnodes; j++)
         {
            gp_Pnt p = (T -> Nodes())(aEdgePoly->Nodes()(j)).Transformed(aEdgeLoc);
            glVertex3f (p.X(), p.Y(), p.Z());
         }
         glEnd ();
      }

      glEndList ();

      // Highlighted edge list

      linelists.Append (glGenLists (1));
      glNewList (linelists.Last(), GL_COMPILE);

      for (int i = 1; i <= occgeometry->emap.Extent(); i++)
      if (occgeometry->evispar[i-1].IsHighlighted())
      {
         TopoDS_Edge edge = TopoDS::Edge(occgeometry->emap(i));
         if (BRep_Tool::Degenerated(edge)) continue;

         Handle(Poly_PolygonOnTriangulation) aEdgePoly;
         Handle(Poly_Triangulation) T;
         TopLoc_Location aEdgeLoc;
         BRep_Tool::PolygonOnTriangulation(edge, aEdgePoly, T, aEdgeLoc);

         if(aEdgePoly.IsNull())
         {
            (*testout) << "visualizing edge " << occgeometry->emap.FindIndex (edge)
            << " without using the occ visualization triangulation" << endl;

            double s0, s1;
            Handle(Geom_Curve) c = BRep_Tool::Curve(edge, s0, s1);

            glBegin (GL_LINE_STRIP);
            for (int i = 0; i<=50; i++)
            {
               gp_Pnt p = c->Value (s0 + i*(s1-s0)/50.0);
               glVertex3f (p.X(),p.Y(),p.Z());
            }
            glEnd ();

            continue;
         }

         int nbnodes = aEdgePoly -> NbNodes();
         glBegin (GL_LINE_STRIP);
         for (int j = 1; j <= nbnodes; j++)
         {
            gp_Pnt p = (T -> Nodes())(aEdgePoly->Nodes()(j)).Transformed(aEdgeLoc);
            glVertex3f (p.X(), p.Y(), p.Z());
         }
         glEnd ();
      }

      glEndList ();

      // display faces

      trilists.Append (glGenLists (1));
      glNewList (trilists.Last(), GL_COMPILE);

      for (int i = 1; i <= occgeometry->fmap.Extent(); i++)
      {
         if (!occgeometry->fvispar[i-1].IsVisible()) continue;

         glLoadName (i);
         float mat_col[4];
         mat_col[3] = 1;

         TopoDS_Face face = TopoDS::Face(occgeometry->fmap(i));

         if (!occgeometry->fvispar[i-1].IsHighlighted())
         {
            // Philippose - 30/01/2009
            // OpenCascade XDE Support
            Quantity_Color face_colour;
            // Philippose - 23/02/2009
            // Check to see if colours have been extracted first!!
            // Forum bug-fox (Jean-Yves - 23/02/2009)
            if(!(occgeometry->face_colours.IsNull())
               && (occgeometry->face_colours->GetColor(face,XCAFDoc_ColorSurf,face_colour)))
            {
               mat_col[0] = face_colour.Red();
               mat_col[1] = face_colour.Green();
               mat_col[2] = face_colour.Blue();
            }
            else
            {
               mat_col[0] = 0.0;
               mat_col[1] = 1.0;
               mat_col[2] = 0.0;
            }
         }
         else
         {
            mat_col[0] = 0.8;
            mat_col[1] = 0.2;
            mat_col[2] = 0.2;
         }

         glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col);

         TopLoc_Location loc;
         Handle(Geom_Surface) surf = BRep_Tool::Surface (face);
         BRepAdaptor_Surface sf(face, Standard_False);
         BRepLProp_SLProps prop(sf, 1, 1e-5);
         Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc);

         if (triangulation.IsNull())
         {
            cout << "cannot visualize face " << i << endl;
            occgeometry->fvispar[i-1].SetNotDrawable();
            continue;
         }

         gp_Pnt2d uv;
         gp_Pnt pnt;
         gp_Vec n;

         glBegin (GL_TRIANGLES);

         int ntriangles = triangulation -> NbTriangles();
         for (int j = 1; j <= ntriangles; j++)
         {
            Poly_Triangle triangle = (triangulation -> Triangles())(j);
            gp_Pnt p[3];
            for (int k = 1; k <= 3; k++)
            p[k-1] = (triangulation -> Nodes())(triangle(k)).Transformed(loc);

            for (int k = 1; k <= 3; k++)
            {
               uv = (triangulation -> UVNodes())(triangle(k));
               prop.SetParameters (uv.X(), uv.Y());

               //	      surf->D0 (uv.X(), uv.Y(), pnt);

               if (prop.IsNormalDefined())
               n = prop.Normal();
               else
               {
                  (*testout) << "Visualization of face " << i
                  << ": Normal vector not defined" << endl;
                  //		  n = gp_Vec (0,0,0);
                  gp_Vec a(p[0],p[1]);
                  gp_Vec b(p[0],p[2]);
                  n = b^a;
               }

               if (face.Orientation() == TopAbs_REVERSED) n *= -1;
               glNormal3f (n.X(), n.Y(), n.Z());
               glVertex3f (p[k-1].X(), p[k-1].Y(), p[k-1].Z());
            }
         }
         glEnd ();

      }
      glEndList ();

   }
//=======================================================================
//function : Execute
//purpose  :
//======================================================================= 
Standard_Integer GEOMImpl_MeasureDriver::Execute(TFunction_Logbook& log) const
{
  if (Label().IsNull()) return 0;    
  Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());

  GEOMImpl_IMeasure aCI (aFunction);
  Standard_Integer aType = aFunction->GetType();

  TopoDS_Shape aShape;

  if (aType == CDG_MEASURE)
  {
    Handle(GEOM_Function) aRefBase = aCI.GetBase();
    TopoDS_Shape aShapeBase = aRefBase->GetValue();
    if (aShapeBase.IsNull()) {
      Standard_NullObject::Raise("Shape for centre of mass calculation is null");
    }

    gp_Ax3 aPos = GEOMImpl_IMeasureOperations::GetPosition(aShapeBase);
    gp_Pnt aCenterMass = aPos.Location();
    aShape = BRepBuilderAPI_MakeVertex(aCenterMass).Shape();
  }
  else if (aType == VERTEX_BY_INDEX)
  {
    Handle(GEOM_Function) aRefBase = aCI.GetBase();
    TopoDS_Shape aShapeBase = aRefBase->GetValue();
    if (aShapeBase.IsNull()) {
      Standard_NullObject::Raise("Shape for centre of mass calculation is null");
    }

    int index = aCI.GetIndex();
    gp_Pnt aVertex;

    if (aShapeBase.ShapeType() == TopAbs_VERTEX) {
      if ( index != 1 )
        Standard_NullObject::Raise("Vertex index is out of range");
      else
        aVertex = BRep_Tool::Pnt(TopoDS::Vertex(aShapeBase));
    } else if (aShapeBase.ShapeType() == TopAbs_EDGE) {
      TopoDS_Vertex aV1, aV2;
      TopoDS_Edge anEdgeE = TopoDS::Edge(aShapeBase);
      
      TopExp::Vertices(anEdgeE, aV1, aV2);
      gp_Pnt aP1 = BRep_Tool::Pnt(aV1);
      gp_Pnt aP2 = BRep_Tool::Pnt(aV2);

      if (index < 0 || index > 1)
        Standard_NullObject::Raise("Vertex index is out of range");

      if ( ( anEdgeE.Orientation() == TopAbs_FORWARD && index == 0 ) ||
           ( anEdgeE.Orientation() == TopAbs_REVERSED && index == 1 ) )
        aVertex = aP1;
      else
      aVertex = aP2;
    } else if (aShapeBase.ShapeType() == TopAbs_WIRE) {
      TopTools_IndexedMapOfShape anEdgeShapes;
      TopTools_IndexedMapOfShape aVertexShapes;
      TopoDS_Vertex aV1, aV2;
      TopoDS_Wire aWire = TopoDS::Wire(aShapeBase);
      TopExp_Explorer exp (aWire, TopAbs_EDGE);
      for (; exp.More(); exp.Next()) {
        anEdgeShapes.Add(exp.Current());
        TopoDS_Edge E = TopoDS::Edge(exp.Current());
        TopExp::Vertices(E, aV1, aV2);
        if ( aVertexShapes.Extent() == 0)
          aVertexShapes.Add(aV1);
        if ( !aV1.IsSame( aVertexShapes(aVertexShapes.Extent()) ) )
          aVertexShapes.Add(aV1);
        if ( !aV2.IsSame( aVertexShapes(aVertexShapes.Extent()) ) )
          aVertexShapes.Add(aV2);
      }

      if (index < 0 || index > aVertexShapes.Extent())
        Standard_NullObject::Raise("Vertex index is out of range");

      if (aWire.Orientation() == TopAbs_FORWARD)
        aVertex = BRep_Tool::Pnt(TopoDS::Vertex(aVertexShapes(index+1)));
      else
        aVertex = BRep_Tool::Pnt(TopoDS::Vertex(aVertexShapes(aVertexShapes.Extent() - index)));
    } else {
      Standard_NullObject::Raise("Shape for vertex calculation is not an edge or wire");
    }

    aShape = BRepBuilderAPI_MakeVertex(aVertex).Shape();
  }
  else if (aType == VECTOR_FACE_NORMALE)
  {
    // Face
    Handle(GEOM_Function) aRefBase = aCI.GetBase();
    TopoDS_Shape aShapeBase = aRefBase->GetValue();
    if (aShapeBase.IsNull()) {
      Standard_NullObject::Raise("Face for normale calculation is null");
    }
    if (aShapeBase.ShapeType() != TopAbs_FACE) {
      Standard_NullObject::Raise("Shape for normale calculation is not a face");
    }
    TopoDS_Face aFace = TopoDS::Face(aShapeBase);

    // Point
    gp_Pnt p1 (0,0,0);

    Handle(GEOM_Function) aPntFunc = aCI.GetPoint();
    if (!aPntFunc.IsNull())
    {
      TopoDS_Shape anOptPnt = aPntFunc->GetValue();
      if (anOptPnt.IsNull())
        Standard_NullObject::Raise("Invalid shape given for point argument");
      p1 = BRep_Tool::Pnt(TopoDS::Vertex(anOptPnt));
    }
    else
    {
      gp_Ax3 aPos = GEOMImpl_IMeasureOperations::GetPosition(aFace);
      p1 = aPos.Location();
    }

    // Point parameters on surface
    Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
    Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
    gp_Pnt2d pUV = aSurfAna->ValueOfUV(p1, Precision::Confusion());

    // Normal direction
    gp_Vec Vec1,Vec2;
    BRepAdaptor_Surface SF (aFace);
    SF.D1(pUV.X(), pUV.Y(), p1, Vec1, Vec2);
    if (Vec1.Magnitude() < Precision::Confusion()) {
      gp_Vec tmpV;
      gp_Pnt tmpP;
      SF.D1(pUV.X(), pUV.Y()-0.1, tmpP, Vec1, tmpV);
    }
    else if (Vec2.Magnitude() < Precision::Confusion()) {
      gp_Vec tmpV;
      gp_Pnt tmpP;
      SF.D1(pUV.X()-0.1, pUV.Y(), tmpP, tmpV, Vec2);
    }

    gp_Vec V = Vec1.Crossed(Vec2);
    Standard_Real mod = V.Magnitude();
    if (mod < Precision::Confusion())
      Standard_NullObject::Raise("Normal vector of a face has null magnitude");

    // Set length of normal vector to average radius of curvature
    Standard_Real radius = 0.0;
    GeomLProp_SLProps aProperties (aSurf, pUV.X(), pUV.Y(), 2, Precision::Confusion());
    if (aProperties.IsCurvatureDefined()) {
      Standard_Real radius1 = Abs(aProperties.MinCurvature());
      Standard_Real radius2 = Abs(aProperties.MaxCurvature());
      if (Abs(radius1) > Precision::Confusion()) {
        radius = 1.0 / radius1;
        if (Abs(radius2) > Precision::Confusion()) {
          radius = (radius + 1.0 / radius2) / 2.0;
        }
      }
      else {
        if (Abs(radius2) > Precision::Confusion()) {
          radius = 1.0 / radius2;
        }
      }
    }

    // Set length of normal vector to average dimension of the face
    // (only if average radius of curvature is not appropriate)
    if (radius < Precision::Confusion()) {
        Bnd_Box B;
        Standard_Real Xmin, Xmax, Ymin, Ymax, Zmin, Zmax;
        BRepBndLib::Add(aFace, B);
        B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
        radius = ((Xmax - Xmin) + (Ymax - Ymin) + (Zmax - Zmin)) / 3.0;
    }

    if (radius < Precision::Confusion())
      radius = 1.0;

    V *= radius / mod;

    // consider the face orientation
    if (aFace.Orientation() == TopAbs_REVERSED ||
        aFace.Orientation() == TopAbs_INTERNAL) {
      V = - V;
    }

    // Edge
    gp_Pnt p2 = p1.Translated(V);
    BRepBuilderAPI_MakeEdge aBuilder (p1, p2);
    if (!aBuilder.IsDone())
      Standard_NullObject::Raise("Vector construction failed");
    aShape = aBuilder.Shape();
  }
  else {
  }

  if (aShape.IsNull()) return 0;

  aFunction->SetValue(aShape);

  log.SetTouched(Label()); 

  return 1;
}
bool RoomLayoutPillarController::PreRender3D()
{
	auto& imp_ = *ImpUPtr_;

	plane3df plan(0,0,0,0,1,0);
	auto line = GetRenderContextSPtr()->Smgr_->getSceneCollisionManager()->getRayFromScreenCoordinates(imp_.CursorIPos_);
	plan.getIntersectionWithLine(line.start, line.getVector(), imp_.CurrentPos_);
	imp_.CurrentPos_.Y = 0;
	gp_Pnt cursorPnt(imp_.CurrentPos_.X, imp_.CurrentPos_.Y, imp_.CurrentPos_.Z);

	switch (imp_.State_)
	{
	case EPilarState::EPS_SWEEPING:
		{
			if ( GetPickingODL().expired() )
			{
				break;
			}

			auto activePilar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock());

			activePilar->SetSweeping(true);

			if ( imp_.CtrllHolding_ )
			{
				imp_.State_ = EPilarState::EPS_MODIFY_INIT;
				break;
			}

			if ( imp_.LMousePressDown_ )
			{
				auto box = activePilar->GetBaseBndBox();
				auto pos = activePilar->GetTranslation();

				Standard_Real xMin,xMax,yMin,yMax,zMin,zMax;
				box.Get(xMin, yMin, zMin, xMax, yMax, zMax);

				imp_.EventInfo_ = SEventPillarInfo();
				imp_.EventInfo_->XLength_ = static_cast<float>(xMax-xMin);
				imp_.EventInfo_->YLength_ = static_cast<float>(yMax-yMin);
				imp_.EventInfo_->ZLength_ = static_cast<float>(zMax-zMin);
				imp_.EventInfo_->OffsetHeight_ = activePilar->GetOffsetHeight();

				imp_.SavePos_ = imp_.CurrentPos_;
				imp_.State_ = EPilarState::EPS_MOUSEHOLDING;
			}
		}
		break;
	case EPilarState::EPS_MODIFY_INIT:
		{
			auto activePilar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock());
			activePilar->SetSweeping(true);

			if ( !imp_.CtrllHolding_ )
			{
				GetRenderContextSPtr()->CursorControl_->setActiveIcon(gui::ECI_NORMAL);
				imp_.State_ = EPilarState::EPS_SWEEPING;
				imp_.CtrllHolding_ = false;
				break;
			}

			auto box = activePilar->GetBaseBndBox();

			Standard_Real xMin,xMax,yMin,yMax,zMin,zMax;
			box.Get(xMin, yMin, zMin, xMax, yMax, zMax);

			auto modifyAlign = 100;

			Bnd_Box smallBox,bigBox;
			smallBox.Update(xMin+modifyAlign < 0 ? xMin+modifyAlign : 0, yMin+modifyAlign < 0 ? yMin+modifyAlign : 0, zMin+modifyAlign < 0 ? zMin+modifyAlign : 0,
				xMax-modifyAlign > 0 ? xMax-modifyAlign : 0, yMax-modifyAlign > 0 ? yMax-modifyAlign : 0, zMax-modifyAlign > 0 ? zMax-modifyAlign : 0);
			bigBox.Update(xMin-modifyAlign, yMin-modifyAlign, zMin-modifyAlign, xMax+modifyAlign, yMax+modifyAlign, zMax+modifyAlign);

			auto relationCursorPnt = cursorPnt.Transformed(activePilar->GetAbsoluteTransform().Inverted());
			relationCursorPnt.SetY(0);

			if ( Standard_True == bigBox.IsOut(relationCursorPnt) )
			{
				GetRenderContextSPtr()->CursorControl_->setActiveIcon(gui::ECI_NORMAL);
				imp_.State_ = EPilarState::EPS_SWEEPING;
				imp_.CtrllHolding_ = false;
				break;
			}

			if ( Standard_False == smallBox.IsOut(relationCursorPnt) )
			{
				GetRenderContextSPtr()->CursorControl_->setActiveIcon(gui::ECI_NORMAL);
				break;
			}

			gp_Dir cursorDir = gp_Vec(gp::Origin(), relationCursorPnt);
			{
				auto rad = gp::DX().AngleWithRef(cursorDir, gp::DY());
				rad = rad < 0 ? M_PI * 2 + rad : rad;
				auto mod = std::fmod(rad, M_PI_2);
				if ( mod < M_PI_4 )
				{
					rad -= mod;
				}
				else
				{
					rad = rad - mod + M_PI_2;
				}

				cursorDir = gp::DX().Rotated(gp::OY(), rad);

				mod = std::fmod(rad, M_PI);
				if ( mod < Precision::Angular() )
				{
					GetRenderContextSPtr()->CursorControl_->setActiveIcon(gui::ECI_SIZEWE);
				}
				else
				{
					GetRenderContextSPtr()->CursorControl_->setActiveIcon(gui::ECI_SIZENS);
				}
			}

			if ( imp_.LMousePressDown_ )
			{
				auto edge = BRepBuilderAPI_MakeEdge(gp_Lin(gp::Origin().Transformed(activePilar->GetAbsoluteTransform()), cursorDir.Transformed(activePilar->GetAbsoluteTransform()))).Edge();
				BRepAdaptor_Curve moveBC(edge);

				GeomAPI_ProjectPointOnCurve ppc(relationCursorPnt.Transformed(activePilar->GetAbsoluteTransform()), moveBC.Curve().Curve());

				imp_.ModifyEdge_ = moveBC;
				imp_.ModifyPar_ = ppc.LowerDistanceParameter();

				imp_.State_ = EPilarState::EPS_MODIFY;
				break;
			}
		}
		break;
	case EPilarState::EPS_MODIFY:
		{
			auto activePilar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock());
			activePilar->SetPicking(true);

			if ( imp_.LMouseLeftUp_ )
			{
				activePilar->UpdateMesh();
				imp_.State_ = EPilarState::EPS_SWEEPING;
				break;
			}

			GeomAPI_ProjectPointOnCurve ppcCur(cursorPnt, imp_.ModifyEdge_.Curve().Curve());

			auto curPar = ppcCur.LowerDistanceParameter();
			if ( std::abs(curPar - imp_.ModifyPar_) < Precision::Confusion() )
			{
				break;
			}

			//偏移的起始点、终点(绝对)
			gp_Pnt fromPnt,toPnt;
			imp_.ModifyEdge_.D0(imp_.ModifyPar_, fromPnt);
			imp_.ModifyEdge_.D0(curPar, toPnt);

			gp_Vec moveOffset(fromPnt, toPnt);
			auto relationMoveOffset = moveOffset.Transformed(activePilar->GetAbsoluteTransform().Inverted());
			auto modifyDir = imp_.ModifyEdge_.Line().Direction().Transformed(activePilar->GetAbsoluteTransform().Inverted());
			auto modifyOffset = relationMoveOffset;
			{
				modifyOffset.SetX(modifyOffset.X() * modifyDir.X());
				modifyOffset.SetY(modifyOffset.Y() * modifyDir.Y());
				modifyOffset.SetZ(modifyOffset.Z() * modifyDir.Z());
			}
			auto curPillarSize = activePilar->GetSize();
			if ( Standard_False == imp_.ModifyEdge_.Line().Direction().IsEqual(gp_Dir(moveOffset), Precision::Angular()) )
			{//防止大小缩成0				
				auto testSize = curPillarSize + modifyOffset.XYZ();

				auto minSize = 100;
				auto alignSize = testSize - gp_XYZ(minSize,minSize,minSize);
				if ( alignSize.X() < Precision::Confusion() || alignSize.Y() < Precision::Confusion() || alignSize.Z() < Precision::Confusion() )
				{
					break;
				}
			}

			Bnd_Box pillarBox;
			auto pillarBoxSize = curPillarSize + modifyOffset.XYZ();
			gp_Trsf pillarTranslation,pillarRotation,pillarTransformation;
			{
				pillarBox.Update(-pillarBoxSize.X()/2, -pillarBoxSize.Y()/2, -pillarBoxSize.Z()/2, pillarBoxSize.X()/2, pillarBoxSize.Y()/2, pillarBoxSize.Z()/2);

				auto translation = activePilar->GetTranslation() + relationMoveOffset.XYZ()/2;
				pillarTranslation.SetTranslationPart(translation);
				pillarRotation.SetRotation(activePilar->GetRotation());
			}
			pillarTransformation = pillarTranslation * pillarRotation;

			auto offsetHeight = activePilar->GetOffsetHeight();

			//新的位置
			gp_Pnt newPnt = gp::Origin().Transformed(pillarTransformation);
			
			//吸附距离
			static auto alignDis = 200.0;

			//当前的吸附物体
			auto alignODLs = activePilar->GetAlignList();
			alignODLs.erase(std::remove_if(alignODLs.begin(), alignODLs.end(), [&pillarBox,&pillarTransformation](const BaseODLSPtr& alignODL)
			{
				if ( !alignODL )
				{
					return true;
				}

				return alignODL->GetBaseBndBox().Distance(pillarBox.Transformed(alignODL->GetAbsoluteTransform().Inverted() * pillarTransformation)) > alignDis;
			}), alignODLs.end());
			activePilar->SetAlignList(BaseODLList());

			std::multimap<double,BaseODLSPtr> disMap;
			for ( auto& curODL : RootODL_.lock()->GetChildrenList() )
			{
				if ( EODLT_PILLAR != curODL->GetType() && EODLT_WALL != curODL->GetType() )
				{
					continue;
				}

				if ( std::find(alignODLs.begin(), alignODLs.end(), curODL) != alignODLs.end() )
				{
					continue;
				}

				if ( EODLT_PILLAR == curODL->GetType() && curODL == activePilar )
				{
					continue;
				}

				auto dis = curODL->GetBaseBndBox().Distance(pillarBox.Transformed(curODL->GetAbsoluteTransform().Inverted() * pillarTransformation));
				if ( dis > alignDis )
				{
					continue;
				}

				disMap.emplace(dis, curODL);
			}

			for ( auto& curODL : disMap )
			{
				alignODLs.push_back(curODL.second);
			}

			for ( auto& curODL : alignODLs )
			{
				auto alignTransformation = curODL->GetAbsoluteTransform();

				//调整柱box的旋转
				auto activeRotationPillarBox = pillarBox;
				{
					gp_Trsf tfsODL;
					tfsODL.SetRotation(alignTransformation.GetRotation());

					activeRotationPillarBox = activeRotationPillarBox.Transformed(tfsODL.Inverted() * pillarRotation);
				}

				Bnd_Box movingBox,alignODLBox;
				{
					auto curBox = curODL->GetBaseBndBox();

					Standard_Real xAlignMin,yAlignMin,zAlignMin,xAlignMax,yAlignMax,zAlignMax;
					curBox.Get(xAlignMin, yAlignMin, zAlignMin, xAlignMax, yAlignMax, zAlignMax);

					Standard_Real xPillarMin,yPillarMin,zPillarMin,xPillarMax,yPillarMax,zPillarMax;
					activeRotationPillarBox.Get(xPillarMin, yPillarMin, zPillarMin, xPillarMax, yPillarMax, zPillarMax);

					movingBox.Update(xAlignMin+xPillarMin, yAlignMin+yPillarMin, zAlignMin+zPillarMin,
						xAlignMax+xPillarMax, yAlignMax+yPillarMax, zAlignMax+zPillarMax);

					alignODLBox.Update(xAlignMin+xPillarMin-alignDis, yAlignMin+yPillarMin-alignDis, zAlignMin+zPillarMin-alignDis,
						xAlignMax+xPillarMax+alignDis, yAlignMax+yPillarMax+alignDis, zAlignMax+zPillarMax+alignDis);
				}

				auto inODLPnt = newPnt.Transformed(curODL->GetAbsoluteTransform().Inverted());

				if ( Standard_True == alignODLBox.IsOut(inODLPnt) )
				{
					continue;
				}

				//当前被停靠物体的box shape
				Standard_Real xMin,yMin,zMin,xMax,yMax,zMax;
				movingBox.Get(xMin, yMin, zMin, xMax, yMax, zMax);
				auto alignBoxShape = BRepPrimAPI_MakeBox(gp_Pnt(xMin, yMin, zMin), gp_Pnt(xMax, yMax, zMax)).Shape();
				TopExp_Explorer exp(alignBoxShape, TopAbs_SHELL);

				BRepExtrema_DistShapeShape dss(imp_.ModifyEdge_.Edge().Moved(curODL->GetAbsoluteTransform().Inverted()), exp.Current());

				auto needContinue = false;
				std::map<double, gp_Pnt> tmp;
				for ( auto index=1; index<=dss.NbSolution(); ++index )
				{
					if ( dss.SupportTypeShape2(index) == BRepExtrema_IsOnEdge )
					{
						activePilar->AddAlign(curODL);
						needContinue = true;
						break;
					}

					auto pntOnEdge = dss.PointOnShape1(index);
					auto pntOnBox = dss.PointOnShape2(index);

					if ( pntOnEdge.Distance(pntOnBox) > Precision::Confusion() )
					{
						continue;
					}

					tmp.emplace(pntOnEdge.Distance(inODLPnt), pntOnEdge);
				}

				if ( needContinue )
				{
					continue;
				}

				auto foundPnt = tmp.begin()->second.Transformed(curODL->GetAbsoluteTransform());
				if ( foundPnt.Distance(newPnt) < 1)
				{
					activePilar->AddAlign(curODL);
					continue;
				}
				else
				{
					newPnt = foundPnt;
					break;
				}
			}

 			auto finalOffset = gp_Vec(pillarTranslation.TranslationPart(), newPnt);
			auto finalRelationOffset = finalOffset.Transformed(pillarTransformation.Inverted());
			auto finalModifyOffset = finalRelationOffset;
			{
				finalModifyOffset.SetX(finalModifyOffset.X()*modifyDir.X());
				finalModifyOffset.SetY(finalModifyOffset.Y()*modifyDir.Y());
				finalModifyOffset.SetZ(finalModifyOffset.Z()*modifyDir.Z());
			}

			auto finalSize = pillarBoxSize + finalModifyOffset.XYZ();
			auto finalTranslation = pillarTranslation.TranslationPart() + finalRelationOffset.XYZ()/2;

			activePilar->SetSize(finalSize);
			activePilar->SetTranslation(finalTranslation);
			{
				vector3df newPos(static_cast<float>(finalTranslation.X()), static_cast<float>(finalTranslation.Y()), static_cast<float>(finalTranslation.Z()));
				activePilar->GetDataSceneNode()->setPosition(newPos);
			}
			activePilar->Update2DMesh();

			imp_.ModifyPar_ = curPar;
		}
		break;
	case EPilarState::EPS_MOUSEHOLDING:
		{
			auto activePillar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock());
			activePillar->SetPicking(true);

			if ( imp_.SavePos_.getDistanceFromSQ(imp_.CurrentPos_) > 100 * 100 )
			{
				imp_.State_ = EPilarState::EPS_MOVING;
				imp_.Valid_ = true;
			}
			else 
				if ( imp_.LMouseLeftUp_ )
				{
					imp_.PropertyCallBack_ = boost::none;
					imp_.State_ = EPilarState::EPS_PROPERTY;

					auto pointer = reinterpret_cast<int>(static_cast<void*>(&(*imp_.EventInfo_)));
					::PostMessage((HWND)GetRenderContextSPtr()->GetHandle(), WM_IRR_DLG_MSG, WM_USER_ROOMLAYOUT_PILLAR_PROPERTY, pointer);
				}
		}
		break;
	case EPilarState::EPS_PROPERTY:
		{
			if ( !imp_.PropertyCallBack_ )
			{
				break;
			}

			auto activePillar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock());

			switch (*(imp_.PropertyCallBack_))
			{
			case EUT_ROOMLAYOUT_PILLAR_NONE:
				{
					imp_.State_ = EPilarState::EPS_SWEEPING;
				}
				break;
			case EUT_ROOMLAYOUT_PILLAR_UPDATE:
				{
					activePillar->SetSize(imp_.EventInfo_->XLength_, imp_.EventInfo_->YLength_, imp_.EventInfo_->ZLength_);
					activePillar->SetOffsetHeight(imp_.EventInfo_->OffsetHeight_);

					{
						auto curTrans = activePillar->GetTranslation();
						curTrans.SetY(imp_.EventInfo_->YLength_/2 + imp_.EventInfo_->OffsetHeight_);
						activePillar->SetTranslation(curTrans);

						auto curPos = activePillar->GetDataSceneNode()->getPosition();
						curPos.Y = static_cast<float>(imp_.EventInfo_->YLength_/2 + imp_.EventInfo_->OffsetHeight_);
						activePillar->GetDataSceneNode()->setPosition(curPos);
					}

					activePillar->UpdateMesh();
					imp_.State_ = EPilarState::EPS_SWEEPING;
				}
				break;
			case EUT_ROOMLAYOUT_PILLAR_MOVE:
				{
					imp_.State_ = EPilarState::EPS_MOVING;
				}
				break;
			case EUT_ROOMLAYOUT_PILLAR_DELETE:
				{
					activePillar->RemoveFromParent();
					imp_.State_ = EPilarState::EPS_SWEEPING;
				}
				break;
			default:
				assert(0);
				break;
			}
		}
		break;
	case EPilarState::EPS_CREATING_INIT:
		{
			assert(imp_.EventInfo_);

			auto newPilar = PillarODL::Create<PillarODL>(GetRenderContextSPtr());
			newPilar->SetSize(imp_.EventInfo_->XLength_, imp_.EventInfo_->YLength_, imp_.EventInfo_->ZLength_);
			newPilar->SetOffsetHeight(imp_.EventInfo_->OffsetHeight_);
			newPilar->UpdateMesh();

			RootODL_.lock()->AddChild(newPilar);

			auto newPos = imp_.CurrentPos_;
			newPos.Y = imp_.EventInfo_->YLength_/2;

			newPilar->SetTranslation(gp_XYZ(newPos.X, newPos.Y, newPos.Z));
			newPilar->GetDataSceneNode()->setPosition(newPos);
			SetPickingODL(newPilar);

			imp_.State_ = EPilarState::EPS_MOVING;
		}
		break;
	case EPilarState::EPS_MOVING:
		{
			auto activePilar = std::static_pointer_cast<PillarODL>(GetPickingODL().lock());
			activePilar->SetPicking(true);
			activePilar->SetVaildPosition(imp_.Valid_);

			if ( imp_.LMouseLeftUp_ )
			{
				if ( imp_.Valid_ )
				{
					ImpUPtr_->Valid_ = false;
					ImpUPtr_->EventInfo_ = boost::none;

					imp_.State_ = EPilarState::EPS_SWEEPING;
					break;
				}
			}

			if ( imp_.EscapePressDown_ )
			{
				activePilar->RemoveFromParent();

				imp_.State_ = EPilarState::EPS_SWEEPING;
				break;
			}
			
			//当前柱的Box
			auto activeTransitionBox = activePilar->GetBaseBndBox();
			{
				gp_Trsf tfs;
				tfs.SetTranslationPart(activePilar->GetTranslation());
				activeTransitionBox = activeTransitionBox.Transformed(tfs);
			}

			activePilar->SetRotation(gp_Quaternion(gp::DZ(), gp::DZ()));
			activePilar->GetDataSceneNode()->setRotation(vector3df(0));

			auto size = activePilar->GetSize();
			auto offset = activePilar->GetOffsetHeight();

			//新的位置
			auto newPos = imp_.CurrentPos_;
			newPos.Y = static_cast<float>(size.Y()/2) + offset;
			gp_Pnt newPnt(newPos.X, newPos.Y, newPos.Z);

			//吸附距离
			static auto alignDis = 200.0;

			//当前的吸附物体
			auto alignODLs = activePilar->GetAlignList();
			alignODLs.erase(std::remove_if(alignODLs.begin(), alignODLs.end(), [&activePilar, &activeTransitionBox](const BaseODLSPtr& alignODL)
			{
				if ( !alignODL )
				{
					return true;
				}

				return alignODL->GetBaseBndBox().Distance(activeTransitionBox.Transformed(alignODL->GetAbsoluteTransform().Inverted())) > alignDis;
			}), alignODLs.end());
			activePilar->SetAlignList(BaseODLList());

			std::multimap<double,BaseODLSPtr> disMap;
			for ( auto& curODL : RootODL_.lock()->GetChildrenList() )
			{
				if ( EODLT_PILLAR != curODL->GetType() && EODLT_WALL != curODL->GetType() )
				{
					continue;
				}

				if ( std::find(alignODLs.begin(), alignODLs.end(), curODL) != alignODLs.end() )
				{
					continue;
				}

				if ( EODLT_PILLAR == curODL->GetType() && curODL == activePilar )
				{
					continue;
				}

				auto dis = curODL->GetBaseBndBox().Distance(activeTransitionBox.Transformed(curODL->GetAbsoluteTransform().Inverted()));
				if ( dis > alignDis )
				{
					continue;
				}

				disMap.emplace(dis, curODL);
			}

			for ( auto& curODL : disMap )
			{
				alignODLs.push_back(curODL.second);
			}

			//锁定旋转
			auto lockRotation = false;
			//锁定位置
			auto lockPosition = false;
			//移动方向
			TopoDS_Edge movingEdge;
			for ( auto& curODL : alignODLs )
			{
				auto alignTransformation = curODL->GetAbsoluteTransform();

				//如果锁定了旋转,则调整柱的box
				auto activeRotationPillarBox = activePilar->GetBaseBndBox();
				if ( lockRotation )
				{
					gp_Trsf tfsODL, tfsPillar;

					tfsODL.SetRotation(alignTransformation.GetRotation());
					tfsPillar.SetRotation(activePilar->GetRotation());

					activeRotationPillarBox = activeRotationPillarBox.Transformed(tfsODL.Inverted() * tfsPillar);
				}
				
				Bnd_Box movingBox;
				{
					auto curBox = curODL->GetBaseBndBox();

					Standard_Real xAlignMin,yAlignMin,zAlignMin,xAlignMax,yAlignMax,zAlignMax;
					curBox.Get(xAlignMin, yAlignMin, zAlignMin, xAlignMax, yAlignMax, zAlignMax);

					Standard_Real xPillarMin,yPillarMin,zPillarMin,xPillarMax,yPillarMax,zPillarMax;
					activeRotationPillarBox.Get(xPillarMin, yPillarMin, zPillarMin, xPillarMax, yPillarMax, zPillarMax);

					movingBox.Update(xAlignMin+xPillarMin, yAlignMin+yPillarMin, zAlignMin+zPillarMin,
						xAlignMax+xPillarMax, yAlignMax+yPillarMax, zAlignMax+zPillarMax);
				}
				
				auto inODLPnt = newPnt.Transformed(curODL->GetAbsoluteTransform().Inverted());

				//当位置锁定了以后,只需要判断是不是相交
				if ( lockPosition )
				{
					if ( Standard_True == movingBox.IsOut(inODLPnt) )
					{
						continue;
					}

					Bnd_Box pntBox;
					pntBox.Add(inODLPnt);

					if ( pntBox.Distance(movingBox) < Precision::Confusion() )
					{
						continue;
					}

					imp_.Valid_ = false;
					break;
				}

				Bnd_Box alignODLBox;
				{
					auto curBox = curODL->GetBaseBndBox();

					Standard_Real xAlignMin,yAlignMin,zAlignMin,xAlignMax,yAlignMax,zAlignMax;
					curBox.Get(xAlignMin, yAlignMin, zAlignMin, xAlignMax, yAlignMax, zAlignMax);

					Standard_Real xPillarMin,yPillarMin,zPillarMin,xPillarMax,yPillarMax,zPillarMax;
					activeRotationPillarBox.Get(xPillarMin, yPillarMin, zPillarMin, xPillarMax, yPillarMax, zPillarMax);

					alignODLBox.Update(xAlignMin+xPillarMin-alignDis, yAlignMin+yPillarMin-alignDis, zAlignMin+zPillarMin-alignDis,
						xAlignMax+xPillarMax+alignDis, yAlignMax+yPillarMax+alignDis, zAlignMax+zPillarMax+alignDis);
				}

				if ( Standard_True == alignODLBox.IsOut(inODLPnt) )
				{
					continue;
				}

				//当前被停靠物体的box shape
				Standard_Real xMin,yMin,zMin,xMax,yMax,zMax;
				movingBox.Get(xMin, yMin, zMin, xMax, yMax, zMax);
				auto alignBoxShape = BRepPrimAPI_MakeBox(gp_Pnt(xMin, yMin, zMin), gp_Pnt(xMax, yMax, zMax)).Shape();
				TopExp_Explorer exp(alignBoxShape, TopAbs_SHELL);

				if ( !lockRotation )
				{//找到第一个被停靠物体
					BRepExtrema_DistShapeShape dss(BRepBuilderAPI_MakeVertex(inODLPnt).Shape(), exp.Current());
					assert(0 != dss.NbSolution());
					inODLPnt = dss.PointOnShape2(1);

					newPnt = inODLPnt.Transformed(curODL->GetAbsoluteTransform()).XYZ();

					auto rot = curODL->GetAbsoluteTransform().GetRotation();
					Standard_Real rX,rY,rZ;
					rot.GetEulerAngles(gp_Extrinsic_XYZ, rX, rY, rZ);
					vector3df rotation(static_cast<float>(irr::core::radToDeg(rX)), static_cast<float>(irr::core::radToDeg(rY)), static_cast<float>(irr::core::radToDeg(rZ)));

					activePilar->GetDataSceneNode()->setRotation(rotation);
					activePilar->SetRotation(rot);

					gp_Dir movingDir;
					if ( std::abs(std::abs(inODLPnt.X()) - xMax) < Precision::Confusion() )
					{
						movingDir = gp::DZ();
					}
					else
					{
						movingDir = gp::DX();
					}
					auto curMovingEdge = BRepBuilderAPI_MakeEdge(gp_Lin(inODLPnt, movingDir)).Edge();

					movingEdge = TopoDS::Edge(curMovingEdge.Moved(curODL->GetAbsoluteTransform()));

					activePilar->AddAlign(curODL);
					imp_.Valid_ = true;
					lockRotation = true;
				}
				else
				{//第二个被停靠物体
					BRepExtrema_DistShapeShape dss(movingEdge.Moved(curODL->GetAbsoluteTransform().Inverted()), exp.Current());
					
					auto foundSecond = false;
					std::map<double, gp_Pnt> tmp;
					for ( auto index=1; index<=dss.NbSolution(); ++index )
					{
						auto pntOnEdge = dss.PointOnShape1(index);
						auto pntOnBox = dss.PointOnShape2(index);

						if ( pntOnEdge.Distance(pntOnBox) > Precision::Confusion() )
						{
							continue;
						}

						tmp.emplace(pntOnEdge.Distance(inODLPnt), pntOnEdge);
						foundSecond = true;
					}

					if ( !foundSecond )
					{
						imp_.Valid_ = false;
						break;
					}

					newPnt = tmp.begin()->second.Transformed(curODL->GetAbsoluteTransform());
					activePilar->AddAlign(curODL);
					lockPosition = true;
				}
			}

			if ( activePilar->GetAlignList().empty() )
			{
				imp_.Valid_ = true;
			}

			newPos.X = static_cast<float>(newPnt.X());
			newPos.Y = static_cast<float>(newPnt.Y());
			newPos.Z = static_cast<float>(newPnt.Z());
			activePilar->GetDataSceneNode()->setPosition(newPos);
			activePilar->SetTranslation(newPnt.XYZ());

			for ( auto& curAlign : activePilar->GetAlignList() )
			{
				curAlign->SetSweeping(true);
			}
		}
		break;
	default:
		break;
	}

	imp_.LMousePressDown_ = false;
	imp_.LMouseLeftUp_ = false;
	imp_.EscapePressDown_ = false;

	return false;
}
void NETGENPlugin_Mesher::PrepareOCCgeometry(netgen::OCCGeometry&     occgeo,
                                             const TopoDS_Shape&      shape,
                                             SMESH_Mesh&              mesh,
                                             list< SMESH_subMesh* > * meshedSM)
{
  BRepTools::Clean (shape);
  try {
#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
    OCC_CATCH_SIGNALS;
#endif
    BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh (shape, 0.01, true);
  } catch (Standard_Failure) {
  }
  Bnd_Box bb;
  BRepBndLib::Add (shape, bb);
  double x1,y1,z1,x2,y2,z2;
  bb.Get (x1,y1,z1,x2,y2,z2);
  MESSAGE("shape bounding box:\n" <<
          "(" << x1 << " " << y1 << " " << z1 << ") " <<
          "(" << x2 << " " << y2 << " " << z2 << ")");
  netgen::Point<3> p1 = netgen::Point<3> (x1,y1,z1);
  netgen::Point<3> p2 = netgen::Point<3> (x2,y2,z2);
  occgeo.boundingbox = netgen::Box<3> (p1,p2);

  occgeo.shape = shape;
  occgeo.changed = 1;
  //occgeo.BuildFMap();

  // fill maps of shapes of occgeo with not yet meshed subshapes

  // get root submeshes
  list< SMESH_subMesh* > rootSM;
  if ( SMESH_subMesh* sm = mesh.GetSubMeshContaining( shape )) {
    rootSM.push_back( sm );
  }
  else {
    for ( TopoDS_Iterator it( shape ); it.More(); it.Next() )
      rootSM.push_back( mesh.GetSubMesh( it.Value() ));
  }

  // add subshapes of empty submeshes
  list< SMESH_subMesh* >::iterator rootIt = rootSM.begin(), rootEnd = rootSM.end();
  for ( ; rootIt != rootEnd; ++rootIt ) {
    SMESH_subMesh * root = *rootIt;
    SMESH_subMeshIteratorPtr smIt = root->getDependsOnIterator(/*includeSelf=*/true,
                                                               /*complexShapeFirst=*/true);
    // to find a right orientation of subshapes (PAL20462)
    TopTools_IndexedMapOfShape subShapes;
    TopExp::MapShapes(root->GetSubShape(), subShapes);
    while ( smIt->more() ) {
      SMESH_subMesh* sm = smIt->next();
      if ( !meshedSM || sm->IsEmpty() ) {
        TopoDS_Shape shape = sm->GetSubShape();
        if ( shape.ShapeType() != TopAbs_VERTEX )
          shape = subShapes( subShapes.FindIndex( shape ));// - shape->index->oriented shape
        switch ( shape.ShapeType() ) {
        case TopAbs_FACE  : occgeo.fmap.Add( shape ); break;
        case TopAbs_EDGE  : occgeo.emap.Add( shape ); break;
        case TopAbs_VERTEX: occgeo.vmap.Add( shape ); break;
        case TopAbs_SOLID :occgeo.somap.Add( shape ); break;
        default:;
        }
      }
      // collect submeshes of meshed shapes
      else if (meshedSM) {
        meshedSM->push_back( sm );
      }
    }
  }
  occgeo.facemeshstatus.SetSize (occgeo.fmap.Extent());
  occgeo.facemeshstatus = 0;

}
示例#20
0
//=======================================================================
//function : PreciseBoundingBox
//purpose  : 
//=======================================================================
Standard_Boolean GEOMUtils::PreciseBoundingBox
                          (const TopoDS_Shape &theShape, Bnd_Box &theBox)
{
  if ( theBox.IsVoid() ) BRepBndLib::Add( theShape, theBox );
  if ( theBox.IsVoid() ) return Standard_False;

  Standard_Real aBound[6];
  theBox.Get(aBound[0], aBound[2], aBound[4], aBound[1], aBound[3], aBound[5]);

  Standard_Integer i;
  const gp_Pnt aMid(0.5*(aBound[1] + aBound[0]),  // XMid
                    0.5*(aBound[3] + aBound[2]),  // YMid
                    0.5*(aBound[5] + aBound[4])); // ZMid
  const gp_XYZ aSize(aBound[1] - aBound[0],       // DX
                     aBound[3] - aBound[2],       // DY
                     aBound[5] - aBound[4]);      // DZ
  const gp_Pnt aPnt[6] =
    {
      gp_Pnt(aBound[0] - (aBound[1] - aBound[0]), aMid.Y(), aMid.Z()), // XMin
      gp_Pnt(aBound[1] + (aBound[1] - aBound[0]), aMid.Y(), aMid.Z()), // XMax
      gp_Pnt(aMid.X(), aBound[2] - (aBound[3] - aBound[2]), aMid.Z()), // YMin
      gp_Pnt(aMid.X(), aBound[3] + (aBound[3] - aBound[2]), aMid.Z()), // YMax
      gp_Pnt(aMid.X(), aMid.Y(), aBound[4] - (aBound[5] - aBound[4])), // ZMin
      gp_Pnt(aMid.X(), aMid.Y(), aBound[5] + (aBound[5] - aBound[4]))  // ZMax
    };
  const gp_Dir aDir[3] = { gp::DX(), gp::DY(), gp::DZ() };
  const Standard_Real aPlnSize[3] =
    {
      0.5*Max(aSize.Y(), aSize.Z()), // XMin, XMax planes
      0.5*Max(aSize.X(), aSize.Z()), // YMin, YMax planes
      0.5*Max(aSize.X(), aSize.Y())  // ZMin, ZMax planes
    };
  gp_Pnt aPMin[2];

  for (i = 0; i < 6; i++) {
    const Standard_Integer iHalf = i/2;
    const gp_Pln aPln(aPnt[i], aDir[iHalf]);
    BRepBuilderAPI_MakeFace aMkFace(aPln, -aPlnSize[iHalf], aPlnSize[iHalf],
                                    -aPlnSize[iHalf], aPlnSize[iHalf]);

    if (!aMkFace.IsDone()) {
      return Standard_False;
    }

    TopoDS_Shape aFace = aMkFace.Shape();

    // Get minimal distance between planar face and shape.
    Standard_Real aMinDist =
      GEOMUtils::GetMinDistance(aFace, theShape, aPMin[0], aPMin[1]);

    if (aMinDist < 0.) {
      return Standard_False;
    }

    aBound[i] = aPMin[1].Coord(iHalf + 1);
  }

  // Update Bounding box with the new values.
  theBox.SetVoid();
  theBox.Update(aBound[0], aBound[2], aBound[4], aBound[1], aBound[3], aBound[5]);

  return Standard_True;
}
void ViewProviderTransformed::recomputeFeature(void)
{
    PartDesign::Transformed* pcTransformed = static_cast<PartDesign::Transformed*>(getObject());
    pcTransformed->getDocument()->recomputeFeature(pcTransformed);
    const std::vector<App::DocumentObjectExecReturn*> log = pcTransformed->getDocument()->getRecomputeLog();
    PartDesign::Transformed::rejectedMap rejected_trsf = pcTransformed->getRejectedTransformations();
    unsigned rejected = 0;
    for (PartDesign::Transformed::rejectedMap::const_iterator r = rejected_trsf.begin(); r != rejected_trsf.end(); r++)
        rejected += r->second.size();
    QString msg = QString::fromLatin1("%1");
    if (rejected > 0) {
        msg = QString::fromLatin1("<font color='orange'>%1<br/></font>\r\n%2");
        if (rejected == 1)
            msg = msg.arg(QObject::tr("One transformed shape does not intersect support"));
        else {
            msg = msg.arg(QObject::tr("%1 transformed shapes do not intersect support"));
            msg = msg.arg(rejected);
        }
    }
    if (log.size() > 0) {
        msg = msg.arg(QString::fromLatin1("<font color='red'>%1<br/></font>"));
        msg = msg.arg(QString::fromStdString(log.back()->Why));
    } else {
        msg = msg.arg(QString::fromLatin1("<font color='green'>%1<br/></font>"));
        msg = msg.arg(QObject::tr("Transformation succeeded"));
    }
    signalDiagnosis(msg);

    // Clear all the rejected stuff
    while (pcRejectedRoot->getNumChildren() > 7) {
        SoSeparator* sep = static_cast<SoSeparator*>(pcRejectedRoot->getChild(7));
        SoMultipleCopy* rejectedTrfms = static_cast<SoMultipleCopy*>(sep->getChild(2));
        rejectedTrfms   ->removeAllChildren();
        sep->removeChild(1);
        sep->removeChild(0);
        pcRejectedRoot  ->removeChild(7);
    }

    for (PartDesign::Transformed::rejectedMap::const_iterator o = rejected_trsf.begin(); o != rejected_trsf.end(); o++) {
        if (o->second.empty()) continue;

        TopoDS_Shape shape;
        if ((o->first)->getTypeId().isDerivedFrom(PartDesign::FeatureAddSub::getClassTypeId())) {
            PartDesign::FeatureAddSub* feature = static_cast<PartDesign::FeatureAddSub*>(o->first);
            shape = feature->AddSubShape.getShape().getShape();
        }

        if (shape.IsNull()) continue;

        // Display the rejected transformations in red
        TopoDS_Shape cShape(shape);

        try {
            // calculating the deflection value
            Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
            {
                Bnd_Box bounds;
                BRepBndLib::Add(cShape, bounds);
                bounds.SetGap(0.0);
                bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);
            }
            Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * Deviation.getValue();

            // create or use the mesh on the data structure
            // Note: This DOES have an effect on cShape
#if OCC_VERSION_HEX >= 0x060600
            Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * M_PI;
            BRepMesh_IncrementalMesh(cShape,deflection,Standard_False,
                                        AngDeflectionRads,Standard_True);
#else
            BRepMesh_IncrementalMesh(cShape,deflection);
#endif
            // We must reset the location here because the transformation data
            // are set in the placement property
            TopLoc_Location aLoc;
            cShape.Location(aLoc);

            // count triangles and nodes in the mesh
            int nbrTriangles=0, nbrNodes=0;
            TopExp_Explorer Ex;
            for (Ex.Init(cShape,TopAbs_FACE);Ex.More();Ex.Next()) {
                Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(Ex.Current()), aLoc);
                // Note: we must also count empty faces
                if (!mesh.IsNull()) {
                    nbrTriangles += mesh->NbTriangles();
                    nbrNodes     += mesh->NbNodes();
                }
            }

            // create memory for the nodes and indexes
            SoCoordinate3* rejectedCoords = new SoCoordinate3();
            rejectedCoords  ->point      .setNum(nbrNodes);
            SoNormal* rejectedNorms = new SoNormal();
            rejectedNorms   ->vector     .setNum(nbrNodes);
            SoIndexedFaceSet* rejectedFaceSet = new SoIndexedFaceSet();
            rejectedFaceSet ->coordIndex .setNum(nbrTriangles*4);

            // get the raw memory for fast fill up
            SbVec3f* verts = rejectedCoords  ->point      .startEditing();
            SbVec3f* norms = rejectedNorms   ->vector     .startEditing();
            int32_t* index = rejectedFaceSet ->coordIndex .startEditing();

            // preset the normal vector with null vector
            for (int i=0; i < nbrNodes; i++)
                norms[i]= SbVec3f(0.0,0.0,0.0);

            int ii = 0,FaceNodeOffset=0,FaceTriaOffset=0;
            for (Ex.Init(cShape, TopAbs_FACE); Ex.More(); Ex.Next(),ii++) {
                TopLoc_Location aLoc;
                const TopoDS_Face &actFace = TopoDS::Face(Ex.Current());
                // get the mesh of the shape
                Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace,aLoc);
                if (mesh.IsNull()) continue;

                // getting the transformation of the shape/face
                gp_Trsf myTransf;
                Standard_Boolean identity = true;
                if (!aLoc.IsIdentity()) {
                    identity = false;
                    myTransf = aLoc.Transformation();
                }

                // getting size of node and triangle array of this face
                int nbNodesInFace = mesh->NbNodes();
                int nbTriInFace   = mesh->NbTriangles();
                // check orientation
                TopAbs_Orientation orient = actFace.Orientation();

                // cycling through the poly mesh
                const Poly_Array1OfTriangle& Triangles = mesh->Triangles();
                const TColgp_Array1OfPnt& Nodes = mesh->Nodes();
                for (int g=1; g <= nbTriInFace; g++) {
                    // Get the triangle
                    Standard_Integer N1,N2,N3;
                    Triangles(g).Get(N1,N2,N3);

                    // change orientation of the triangle if the face is reversed
                    if ( orient != TopAbs_FORWARD ) {
                        Standard_Integer tmp = N1;
                        N1 = N2;
                        N2 = tmp;
                    }

                    // get the 3 points of this triangle
                    gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3));

                    // transform the vertices to the place of the face
                    if (!identity) {
                        V1.Transform(myTransf);
                        V2.Transform(myTransf);
                        V3.Transform(myTransf);
                    }

                    // calculating per vertex normals
                    // Calculate triangle normal
                    gp_Vec v1(V1.X(),V1.Y(),V1.Z()),v2(V2.X(),V2.Y(),V2.Z()),v3(V3.X(),V3.Y(),V3.Z());
                    gp_Vec Normal = (v2-v1)^(v3-v1);

                    // add the triangle normal to the vertex normal for all points of this triangle
                    norms[FaceNodeOffset+N1-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z());
                    norms[FaceNodeOffset+N2-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z());
                    norms[FaceNodeOffset+N3-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z());

                    // set the vertices
                    verts[FaceNodeOffset+N1-1].setValue((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z()));
                    verts[FaceNodeOffset+N2-1].setValue((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z()));
                    verts[FaceNodeOffset+N3-1].setValue((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z()));

                    // set the index vector with the 3 point indexes and the end delimiter
                    index[FaceTriaOffset*4+4*(g-1)]   = FaceNodeOffset+N1-1;
                    index[FaceTriaOffset*4+4*(g-1)+1] = FaceNodeOffset+N2-1;
                    index[FaceTriaOffset*4+4*(g-1)+2] = FaceNodeOffset+N3-1;
                    index[FaceTriaOffset*4+4*(g-1)+3] = SO_END_FACE_INDEX;
                }

                // counting up the per Face offsets
                FaceNodeOffset += nbNodesInFace;
                FaceTriaOffset += nbTriInFace;
            }

            // normalize all normals
            for (int i=0; i < nbrNodes; i++)
                norms[i].normalize();

            // end the editing of the nodes
            rejectedCoords  ->point      .finishEditing();
            rejectedNorms   ->vector     .finishEditing();
            rejectedFaceSet ->coordIndex .finishEditing();

            // fill in the transformation matrices
            SoMultipleCopy* rejectedTrfms = new SoMultipleCopy();
            rejectedTrfms->matrix.setNum((o->second).size());
            SbMatrix* mats = rejectedTrfms->matrix.startEditing();

            std::list<gp_Trsf>::const_iterator trsf = (o->second).begin();
            for (unsigned int i=0; i < (o->second).size(); i++,trsf++) {
                Base::Matrix4D mat;
                Part::TopoShape::convertToMatrix(*trsf,mat);
                mats[i] = convert(mat);
            }
            rejectedTrfms->matrix.finishEditing();
            rejectedTrfms->addChild(rejectedFaceSet);
            SoSeparator* sep = new SoSeparator();
            sep->addChild(rejectedCoords);
            sep->addChild(rejectedNorms);
            sep->addChild(rejectedTrfms);
            pcRejectedRoot->addChild(sep);
        }
        catch (...) {
            Base::Console().Error("Cannot compute Inventor representation for the rejected transformations of shape of %s.\n",
                                  pcTransformed->getNameInDocument());
        }
    }

}
示例#22
0
void ViewProviderPartExt::updateVisual(const TopoDS_Shape& inputShape)
{
    // Clear selection
    Gui::SoSelectionElementAction action(Gui::SoSelectionElementAction::None);
    action.apply(this->faceset);
    action.apply(this->lineset);
    action.apply(this->nodeset);

    TopoDS_Shape cShape(inputShape);
    if (cShape.IsNull()) {
        coords  ->point      .setNum(0);
        norm    ->vector     .setNum(0);
        faceset ->coordIndex .setNum(0);
        faceset ->partIndex  .setNum(0);
        lineset ->coordIndex .setNum(0);
        VisualTouched = false;
        return;
    }

    // time measurement and book keeping
    Base::TimeInfo start_time;
    int nbrTriangles=0,nbrNodes=0,nbrNorms=0,nbrFaces=0,nbrEdges=0,nbrLines=0;
    std::set<int> faceEdges;

    try {
        // calculating the deflection value
        Bnd_Box bounds;
        BRepBndLib::Add(cShape, bounds);
        bounds.SetGap(0.0);
        Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
        bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);
        Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 *
            Deviation.getValue();

        // create or use the mesh on the data structure
        BRepMesh_IncrementalMesh myMesh(cShape,deflection);
        // We must reset the location here because the transformation data
        // are set in the placement property
        TopLoc_Location aLoc;
        cShape.Location(aLoc);

        // count triangles and nodes in the mesh
        TopExp_Explorer Ex;
        for (Ex.Init(cShape,TopAbs_FACE);Ex.More();Ex.Next()) {
            Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(Ex.Current()), aLoc);
            // Note: we must also count empty faces
            if (!mesh.IsNull()) {
                nbrTriangles += mesh->NbTriangles();
                nbrNodes     += mesh->NbNodes();
                nbrNorms     += mesh->NbNodes();
            }

            TopExp_Explorer xp;
            for (xp.Init(Ex.Current(),TopAbs_EDGE);xp.More();xp.Next())
                faceEdges.insert(xp.Current().HashCode(INT_MAX));
            nbrFaces++;
        }

        // get an indexed map of edges
        TopTools_IndexedMapOfShape M;
        TopExp::MapShapes(cShape, TopAbs_EDGE, M);

        std::set<int>         edgeIdxSet;
        std::vector<int32_t>  indxVector;
        std::vector<int32_t>  edgeVector;

        // count and index the edges
        for (int i=1; i <= M.Extent(); i++) {
            edgeIdxSet.insert(i);
            nbrEdges++;

            const TopoDS_Edge& aEdge = TopoDS::Edge(M(i));
            TopLoc_Location aLoc;

            // handling of the free edge that are not associated to a face
            // Note: The assumption that if for an edge BRep_Tool::Polygon3D
            // returns a valid object is wrong. This e.g. happens for ruled
            // surfaces which gets created by two edges or wires.
            // So, we have to store the hashes of the edges associated to a face.
            // If the hash of a given edge is not in this list we know it's really
            // a free edge.
            int hash = aEdge.HashCode(INT_MAX);
            if (faceEdges.find(hash) == faceEdges.end()) {
                Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(aEdge, aLoc);
                if (!aPoly.IsNull()) {
                    int nbNodesInEdge = aPoly->NbNodes();
                    nbrNodes += nbNodesInEdge;
                }
            }
        }
        // reserve some memory
        indxVector.reserve(nbrEdges*8);

        // handling of the vertices
        TopTools_IndexedMapOfShape V;
        TopExp::MapShapes(cShape, TopAbs_VERTEX, V);
        nbrNodes += V.Extent();

        // create memory for the nodes and indexes
        coords  ->point      .setNum(nbrNodes);
        norm    ->vector     .setNum(nbrNorms);
        faceset ->coordIndex .setNum(nbrTriangles*4);
        faceset ->partIndex  .setNum(nbrFaces);
        // get the raw memory for fast fill up
        SbVec3f* verts = coords  ->point       .startEditing();
        SbVec3f* norms = norm    ->vector      .startEditing();
        int32_t* index = faceset ->coordIndex  .startEditing();
        int32_t* parts = faceset ->partIndex   .startEditing();

        // preset the normal vector with null vector
        for (int i=0;i < nbrNorms;i++) 
            norms[i]= SbVec3f(0.0,0.0,0.0);

        int ii = 0,FaceNodeOffset=0,FaceTriaOffset=0;
        for (Ex.Init(cShape, TopAbs_FACE); Ex.More(); Ex.Next(),ii++) {
            TopLoc_Location aLoc;
            const TopoDS_Face &actFace = TopoDS::Face(Ex.Current());
            // get the mesh of the shape
            Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace,aLoc);
            if (mesh.IsNull()) continue;

            // getting the transformation of the shape/face
            gp_Trsf myTransf;
            Standard_Boolean identity = true;
            if (!aLoc.IsIdentity()) {
                identity = false;
                myTransf = aLoc.Transformation();
            }

            // getting size of node and triangle array of this face
            int nbNodesInFace = mesh->NbNodes();
            int nbTriInFace   = mesh->NbTriangles();
            // check orientation
            TopAbs_Orientation orient = actFace.Orientation();


            // cycling through the poly mesh
            const Poly_Array1OfTriangle& Triangles = mesh->Triangles();
            const TColgp_Array1OfPnt& Nodes = mesh->Nodes();
            for (int g=1;g<=nbTriInFace;g++) {
                // Get the triangle
                Standard_Integer N1,N2,N3;
                Triangles(g).Get(N1,N2,N3);

                // change orientation of the triangle if the face is reversed
                if ( orient != TopAbs_FORWARD ) {
                    Standard_Integer tmp = N1;
                    N1 = N2;
                    N2 = tmp;
                }

                // get the 3 points of this triangle
                gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3));

                // transform the vertices to the place of the face
                if (!identity) {
                    V1.Transform(myTransf);
                    V2.Transform(myTransf);
                    V3.Transform(myTransf);
                }
                
                // calculating per vertex normals                    
                // Calculate triangle normal
                gp_Vec v1(V1.X(),V1.Y(),V1.Z()),v2(V2.X(),V2.Y(),V2.Z()),v3(V3.X(),V3.Y(),V3.Z());
                gp_Vec Normal = (v2-v1)^(v3-v1); 

                // add the triangle normal to the vertex normal for all points of this triangle
                norms[FaceNodeOffset+N1-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z());
                norms[FaceNodeOffset+N2-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z());
                norms[FaceNodeOffset+N3-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z());                 

                // set the vertices
                verts[FaceNodeOffset+N1-1].setValue((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z()));
                verts[FaceNodeOffset+N2-1].setValue((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z()));
                verts[FaceNodeOffset+N3-1].setValue((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z()));

                // set the index vector with the 3 point indexes and the end delimiter
                index[FaceTriaOffset*4+4*(g-1)]   = FaceNodeOffset+N1-1; 
                index[FaceTriaOffset*4+4*(g-1)+1] = FaceNodeOffset+N2-1; 
                index[FaceTriaOffset*4+4*(g-1)+2] = FaceNodeOffset+N3-1; 
                index[FaceTriaOffset*4+4*(g-1)+3] = SO_END_FACE_INDEX;
            }

            parts[ii] = nbTriInFace; // new part

            // handling the edges lying on this face
            TopExp_Explorer Exp;
            for(Exp.Init(actFace,TopAbs_EDGE);Exp.More();Exp.Next()) {
                const TopoDS_Edge &actEdge = TopoDS::Edge(Exp.Current());
                // get the overall index of this edge
                int idx = M.FindIndex(actEdge);
                edgeVector.push_back((int32_t)idx-1);
                // already processed this index ?
                if (edgeIdxSet.find(idx)!=edgeIdxSet.end()) {
                    
                    // this holds the indices of the edge's triangulation to the current polygon
                    Handle(Poly_PolygonOnTriangulation) aPoly = BRep_Tool::PolygonOnTriangulation(actEdge, mesh, aLoc);
                    if (aPoly.IsNull())
                        continue; // polygon does not exist
                    
                    // getting the indexes of the edge polygon
                    const TColStd_Array1OfInteger& indices = aPoly->Nodes();
                    for (Standard_Integer i=indices.Lower();i <= indices.Upper();i++) {
                        int inx = indices(i);
                        indxVector.push_back(FaceNodeOffset+inx-1);

                        // usually the coordinates for this edge are already set by the
                        // triangles of the face this edge belongs to. However, there are
                        // rare cases where some points are only referenced by the polygon
                        // but not by any triangle. Thus, we must apply the coordinates to
                        // make sure that everything is properly set.
                        gp_Pnt p(Nodes(inx));
                        if (!identity)
                            p.Transform(myTransf);
                        verts[FaceNodeOffset+inx-1].setValue((float)(p.X()),(float)(p.Y()),(float)(p.Z()));
                    }
                    indxVector.push_back(-1);

                    // remove the handled edge index from the set
                    edgeIdxSet.erase(idx);
                }
            }

            edgeVector.push_back(-1);
            
            // counting up the per Face offsets
            FaceNodeOffset += nbNodesInFace;
            FaceTriaOffset += nbTriInFace;
        }

        // handling of the free edges
        for (int i=1; i <= M.Extent(); i++) {
            const TopoDS_Edge& aEdge = TopoDS::Edge(M(i));
            Standard_Boolean identity = true;
            gp_Trsf myTransf;
            TopLoc_Location aLoc;

            // handling of the free edge that are not associated to a face
            int hash = aEdge.HashCode(INT_MAX);
            if (faceEdges.find(hash) == faceEdges.end()) {
                Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(aEdge, aLoc);
                if (!aPoly.IsNull()) {
                    if (!aLoc.IsIdentity()) {
                        identity = false;
                        myTransf = aLoc.Transformation();
                    }

                    const TColgp_Array1OfPnt& aNodes = aPoly->Nodes();
                    int nbNodesInEdge = aPoly->NbNodes();

                    gp_Pnt pnt;
                    for (Standard_Integer j=1;j <= nbNodesInEdge;j++) {
                        pnt = aNodes(j);
                        if (!identity)
                            pnt.Transform(myTransf);
                        verts[FaceNodeOffset+j-1].setValue((float)(pnt.X()),(float)(pnt.Y()),(float)(pnt.Z()));
                        indxVector.push_back(FaceNodeOffset+j-1);
                    }

                    indxVector.push_back(-1);
                    FaceNodeOffset += nbNodesInEdge;
                }
            }
        }

        nodeset->startIndex.setValue(FaceNodeOffset);
        for (int i=0; i<V.Extent(); i++) {
            const TopoDS_Vertex& aVertex = TopoDS::Vertex(V(i+1));
            gp_Pnt pnt = BRep_Tool::Pnt(aVertex);
            verts[FaceNodeOffset+i].setValue((float)(pnt.X()),(float)(pnt.Y()),(float)(pnt.Z()));
        }

        // normalize all normals 
        for (int i = 0; i< nbrNorms ;i++)
            norms[i].normalize();
        
        // preset the index vector size
        nbrLines =  indxVector.size();
        lineset ->coordIndex .setNum(nbrLines);
        int32_t* lines = lineset ->coordIndex  .startEditing();

        int l=0;
        for (std::vector<int32_t>::const_iterator it=indxVector.begin();it!=indxVector.end();++it,l++)
            lines[l] = *it;

        // end the editing of the nodes
        coords  ->point       .finishEditing();
        norm    ->vector      .finishEditing();
        faceset ->coordIndex  .finishEditing();
        faceset ->partIndex   .finishEditing();
        lineset ->coordIndex  .finishEditing();
    }
    catch (...) {
        Base::Console().Error("Cannot compute Inventor representation for the shape of %s.\n",pcObject->getNameInDocument());
    }

    // printing some informations
    Base::Console().Log("ViewProvider update time: %f s\n",Base::TimeInfo::diffTimeF(start_time,Base::TimeInfo()));
    Base::Console().Log("Shape tria info: Faces:%d Edges:%d Nodes:%d Triangles:%d IdxVec:%d\n",nbrFaces,nbrEdges,nbrNodes,nbrTriangles,nbrLines);

    VisualTouched = false;
}