X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGeomAlgoAPI%2FGeomAlgoAPI_Placement.cpp;h=fb139dd8e78a1f86683936089901aaacae1a7d58;hb=530f5aff42069e844c4a4ef164088ea23ba0e2dd;hp=e5714a22e789ff59934315f5f9f0fa09b32c5bea;hpb=57cf6e2ea021fe95dcc0caa5d19bffd2cde4223f;p=modules%2Fshaper.git diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Placement.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Placement.cpp index e5714a22e..fb139dd8e 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Placement.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Placement.cpp @@ -4,154 +4,219 @@ // Created: 2 Dec 2014 // Author: Artem ZHIDKOV -#include +#include "GeomAlgoAPI_Placement.h" + #include +#include +#include +#include +#include #include #include +#include +#include #include +#include #include #include -#include -#include -#include -#include -#include #include -#define DEB_PLACEMENT 1 -GeomAlgoAPI_Placement::GeomAlgoAPI_Placement( - std::shared_ptr theSourceShape, - std::shared_ptr theDestShape, - std::shared_ptr theSourcePlane, - std::shared_ptr theDestPlane, - bool theIsReverse, - bool theIsCentering) - : myDone(false), - myShape(new GeomAPI_Shape()) +GeomAlgoAPI_Placement::GeomAlgoAPI_Placement(const std::shared_ptr theSourceSolid, + const std::shared_ptr theDestSolid, + const std::shared_ptr theSourceShape, + const std::shared_ptr theDestShape, + const bool theIsReverse, + const bool theIsCentering, + const bool theSimpleTransform) { - build(theSourceShape, theDestShape, theSourcePlane, theDestPlane, theIsReverse, theIsCentering); + build(theSourceSolid, theDestSolid, theSourceShape, theDestShape, + theIsReverse, theIsCentering, theSimpleTransform); } -void GeomAlgoAPI_Placement::build( - const std::shared_ptr& theSourceShape, - const std::shared_ptr& theDestShape, - const std::shared_ptr& theSourcePlane, - const std::shared_ptr& theDestPlane, - bool theIsReverse, - bool theIsCentering) +void GeomAlgoAPI_Placement::build(const std::shared_ptr& theSourceSolid, + const std::shared_ptr& theDestSolid, + const std::shared_ptr& theSourceShape, + const std::shared_ptr& theDestShape, + const bool theIsReverse, + const bool theIsCentering, + const bool theSimpleTransform) { - std::shared_ptr aSourcePlane = theSourcePlane->getPlane(); - std::shared_ptr aDestPlane = theDestPlane->getPlane(); - std::shared_ptr aSourceDir = aSourcePlane->direction(); - std::shared_ptr aSourceLoc = aSourcePlane->location(); - std::shared_ptr aDestDir = aDestPlane->direction(); - std::shared_ptr aDestLoc = aDestPlane->location(); + // Filling the parameters of the objects + static const int aNbObjects = 2; + gp_Pnt aSrcDstPoints[aNbObjects]; // points on the selected objects (0 - source, 1 - destination) + gp_Vec aSrcDstNormals[aNbObjects]; // normal vectors, if planar faces are selected + gp_Vec aSrcDstDirections[aNbObjects]; // directions of linear edges + bool hasNormal[aNbObjects]; + bool hasDirection[aNbObjects]; + std::shared_ptr aShapes[aNbObjects] = {theSourceShape, theDestShape}; + + for (int i = 0; i < aNbObjects; i++) { + if (aShapes[i]->isFace()) { + std::shared_ptr aFace(new GeomAPI_Face(aShapes[i])); + std::shared_ptr aPlane = aFace->getPlane(); + std::shared_ptr aDir = aPlane->direction(); + std::shared_ptr aLoc = aPlane->location(); + aSrcDstPoints[i].SetCoord(aLoc->x(), aLoc->y(), aLoc->z()); + aSrcDstNormals[i].SetCoord(aDir->x(), aDir->y(), aDir->z()); + } else if (aShapes[i]->isEdge()) { + std::shared_ptr anEdge(new GeomAPI_Edge(aShapes[i])); + std::shared_ptr aLine = anEdge->line(); + std::shared_ptr aDir = aLine->direction(); + std::shared_ptr aFirstPnt = anEdge->firstPoint(); + std::shared_ptr aLastPnt = anEdge->lastPoint(); + std::shared_ptr aLoc = aFirstPnt->xyz()->added(aLastPnt->xyz())->multiplied(0.5); + aSrcDstPoints[i].SetCoord(aLoc->x(), aLoc->y(), aLoc->z()); + aSrcDstDirections[i].SetCoord(aDir->x(), aDir->y(), aDir->z()); + } else if (aShapes[i]->isVertex()) { + std::shared_ptr aVertex(new GeomAPI_Vertex(aShapes[i])); + std::shared_ptr aPnt = aVertex->point(); + aSrcDstPoints[i].SetCoord(aPnt->x(), aPnt->y(), aPnt->z()); + } else // something goes wrong + return; + hasNormal[i] = aSrcDstNormals[i].SquareMagnitude() >= Precision::SquareConfusion(); + hasDirection[i] = aSrcDstDirections[i].SquareMagnitude() >= Precision::SquareConfusion(); + } // Initial shapes - const TopoDS_Shape& aSourceShape = theSourceShape->impl(); - const TopoDS_Shape& aDestShape = theDestShape->impl(); - - // Calculate transformation - gp_Trsf aTrsf; - gp_Vec aSrcDir(aSourceDir->x(), aSourceDir->y(), aSourceDir->z()); - gp_Vec aDstDir(aDestDir->x(), aDestDir->y(), aDestDir->z()); + const TopoDS_Shape& aSourceShape = theSourceSolid->impl(); + const TopoDS_Shape& aDestShape = theDestSolid->impl(); // Check the material of the solids to be on the correct side BRepClass3d_SolidClassifier aClassifier; - aClassifier.Load(aSourceShape); static const double aTransStep = 10. * Precision::Confusion(); - gp_Pnt aPoint(aSourceLoc->x(), aSourceLoc->y(), aSourceLoc->z()); - aPoint.Translate(aSrcDir * aTransStep); - aClassifier.Perform(aPoint, Precision::Confusion()); - if ((aClassifier.State() == TopAbs_OUT && !theIsReverse) || + if (hasNormal[0]) { + aClassifier.Load(aSourceShape); + gp_Pnt aPoint = aSrcDstPoints[0]; + aPoint.Translate(aSrcDstNormals[0] * aTransStep); + aClassifier.Perform(aPoint, Precision::Confusion()); + if ((aClassifier.State() == TopAbs_OUT && !theIsReverse) || (aClassifier.State() == TopAbs_IN && theIsReverse)) - aSrcDir.Reverse(); - aClassifier.Load(aDestShape); - aPoint.SetCoord(aDestLoc->x(), aDestLoc->y(), aDestLoc->z()); - aPoint.Translate(aDstDir * aTransStep); - aClassifier.Perform(aPoint, Precision::Confusion()); - if (aClassifier.State() == TopAbs_IN) - aDstDir.Reverse(); + aSrcDstNormals[0].Reverse(); + } + if (hasNormal[1]) { + aClassifier.Load(aDestShape); + gp_Pnt aPoint = aSrcDstPoints[1]; + aPoint.Translate(aSrcDstNormals[1] * aTransStep); + aClassifier.Perform(aPoint, Precision::Confusion()); + if (aClassifier.State() == TopAbs_IN) + aSrcDstNormals[1].Reverse(); + } + + // Calculate directions, which comply the normal, for vertices and edges + if (!hasNormal[0] || !hasNormal[1]) { + if (hasNormal[0] || hasNormal[1]) { // plane with line or vertex + if (hasDirection[0] || hasDirection[1]) { // plane - line + int anInd = hasDirection[0] ? 0 : 1; + gp_Vec aVec = aSrcDstNormals[1 - anInd].Crossed(aSrcDstDirections[anInd]); + if (aVec.SquareMagnitude() < Precision::SquareConfusion()) { // normal and direction are collinear + aVec = aSrcDstNormals[1 - anInd].Crossed( + gp_Vec(aSrcDstPoints[1 - anInd], aSrcDstPoints[anInd])); + if (aVec.SquareMagnitude() < Precision::SquareConfusion()) { // normal and points direction are collinear + if (Abs(aSrcDstNormals[1 - anInd].Y()) >= Precision::Confusion() || + Abs(aSrcDstNormals[1 - anInd].Z()) >= Precision::Confusion()) + aVec = gp::DX(); + else + aVec = gp::DY(); + } + } + aSrcDstNormals[anInd] = aSrcDstDirections[anInd].Crossed(aVec).Normalized(); + } else { // plane - point + int anInd = hasNormal[0] ? 1 : 0; + aSrcDstNormals[anInd] = aSrcDstNormals[1 - anInd]; + } + } else { + if (hasDirection[0] && hasDirection[1]) { // line - line + gp_Vec aVec = aSrcDstDirections[0].Crossed(aSrcDstDirections[1]); + if (aVec.SquareMagnitude() < Precision::SquareConfusion()) { // lines are parallel + aVec = aSrcDstDirections[0].Crossed(gp_Vec(aSrcDstPoints[0], aSrcDstPoints[1])); + if (aVec.SquareMagnitude() < Precision::SquareConfusion()) { // lines are equal + if (Abs(aSrcDstDirections[0].Y()) >= Precision::Confusion() || + Abs(aSrcDstDirections[0].Z()) >= Precision::Confusion()) + aVec = gp::DX(); + else + aVec = gp::DY(); + } + } + aSrcDstNormals[0] = aSrcDstDirections[0].Crossed(aVec); + aSrcDstNormals[0].Normalize(); + aSrcDstNormals[1] = aSrcDstDirections[1].Crossed(aVec); + aSrcDstNormals[1].Normalize(); + if (aSrcDstDirections[0].Dot(aSrcDstDirections[1]) < -Precision::Confusion()) + aSrcDstNormals[1].Reverse(); + } else if (!hasDirection[0] && !hasDirection[1]) { // point - point + aSrcDstNormals[0] = gp_Vec(aSrcDstPoints[0], aSrcDstPoints[1]); + aSrcDstNormals[0].Normalize(); + aSrcDstNormals[1] = -aSrcDstNormals[0]; + } else { // line - point + int anInd = hasDirection[0] ? 0 : 1; + gp_Vec aVec(aSrcDstPoints[anInd], aSrcDstPoints[1 - anInd]); + aVec.Cross(aSrcDstDirections[anInd]); + if (aVec.SquareMagnitude() < Precision::SquareConfusion()) { // point is on line + if (Abs(aSrcDstDirections[1 - anInd].Y()) >= Precision::Confusion() || + Abs(aSrcDstDirections[1 - anInd].Z()) >= Precision::Confusion()) + aVec = gp::DX(); + else + aVec = gp::DY(); + } + aSrcDstNormals[anInd] = aSrcDstDirections[anInd].Crossed(aVec).Normalized(); + aSrcDstNormals[1 - anInd] = aSrcDstNormals[anInd]; + } + } + } + + // Reverse the normal if it was not done before + if (!hasNormal[0] && theIsReverse) + aSrcDstNormals[0].Reverse(); + + // Calculate transformation + gp_Trsf aTrsf; + gp_Vec aSrcDir = aSrcDstNormals[0]; + gp_Vec aDstDir = aSrcDstNormals[1]; // Calculate rotation gp_Quaternion aRot(aSrcDir, aDstDir); aTrsf.SetRotation(aRot); // Calculate translation - gp_Vec aSrcLoc(aSourceLoc->x(), aSourceLoc->y(), aSourceLoc->z()); - gp_Vec aDstLoc(aDestLoc->x(), aDestLoc->y(), aDestLoc->z()); + gp_Vec aSrcLoc(aSrcDstPoints[0].XYZ()); + gp_Vec aDstLoc(aSrcDstPoints[1].XYZ()); if (!theIsCentering) aDstLoc = aSrcLoc + gp_Vec(aDstDir) * (aDstLoc-aSrcLoc).Dot(aDstDir); aSrcLoc.Transform(aTrsf); gp_Vec aTrans = aDstLoc - aSrcLoc; aTrsf.SetTransformation(aRot, aTrans); - // Transform the shape with copying it - BRepBuilderAPI_Transform* aBuilder = new BRepBuilderAPI_Transform(aSourceShape, aTrsf, true); - if(aBuilder) { - setImpl(aBuilder); - myDone = aBuilder->IsDone() == Standard_True; - if (myDone) { - TopoDS_Shape aResult = aBuilder->Shape(); - // fill data map to keep correct orientation of sub-shapes - for (TopExp_Explorer Exp(aResult,TopAbs_FACE); Exp.More(); Exp.Next()) { - std::shared_ptr aCurrentShape(new GeomAPI_Shape()); - aCurrentShape->setImpl(new TopoDS_Shape(Exp.Current())); - myMap.bind(aCurrentShape, aCurrentShape); - } -#ifdef DEB_PLACEMENT - int aNum = myMap.size(); - cout << "MAP of Oriented shapes =" << aNum <setImpl(new TopoDS_Shape(aResult)); - myMkShape = new GeomAlgoAPI_MakeShape (aBuilder); + if (theSimpleTransform) { // just add transformation + TopLoc_Location aDelta(aTrsf); + // store the accumulated information about the result and this delta + //myTrsf = std::shared_ptr(new GeomAPI_Trsf(new gp_Trsf(aTrsf * aSourceShape.Location().Transformation()))); + myTrsf.reset(new GeomAPI_Trsf(new gp_Trsf(aTrsf))); + TopoDS_Shape aResult = aSourceShape.Moved(aDelta); + std::shared_ptr aShape(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(aResult)); + this->setShape(aShape); + this->setDone(true); // it is allways true for simple transformation generation + } else { // internal rebuild of the shape + // Transform the shape with copying it + BRepBuilderAPI_Transform* aBuilder = new BRepBuilderAPI_Transform(aSourceShape, aTrsf, true); + if(!aBuilder) { + return; } - } -} - -//============================================================================ -const bool GeomAlgoAPI_Placement::isValid() const -{ - BRepCheck_Analyzer aChecker(myShape->impl()); - return (aChecker.IsValid() == Standard_True); -} + this->setImpl(aBuilder); + this->setBuilderType(OCCT_BRepBuilderAPI_MakeShape); + if(aBuilder->IsDone() != Standard_True) { + return; + } + TopoDS_Shape aResult = aBuilder->Shape(); -//============================================================================ -const bool GeomAlgoAPI_Placement::hasVolume() const -{ - bool hasVolume(false); - if(isValid()) { - const TopoDS_Shape& aRShape = myShape->impl(); - GProp_GProps aGProp; - BRepGProp::VolumeProperties(aRShape, aGProp); - if(aGProp.Mass() > Precision::Confusion()) - hasVolume = true; + std::shared_ptr aShape(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(aResult)); + this->setShape(aShape); + this->setDone(true); } - return hasVolume; } -//============================================================================ -const std::shared_ptr& GeomAlgoAPI_Placement::shape () const +//================================================================================================= +std::shared_ptr GeomAlgoAPI_Placement::transformation() const { - return myShape; + return myTrsf; } - -//============================================================================ -void GeomAlgoAPI_Placement::mapOfShapes (GeomAPI_DataMapOfShapeShape& theMap) const -{ - theMap = myMap; -} - -//============================================================================ -GeomAlgoAPI_MakeShape * GeomAlgoAPI_Placement::makeShape() const -{ - return myMkShape; -} - -//============================================================================ -GeomAlgoAPI_Placement::~GeomAlgoAPI_Placement() -{ - if (myImpl) - myMap.clear(); -} \ No newline at end of file