// TODO: This code is taken from and duplicates code in Part2DObject::positionBySupport()
// Note: We cannot return a reference, because it will become Null.
// Not clear where, because we check for IsNull() here, but as soon as it is passed out of
// this method, it becomes null!
const TopoDS_Face SketchBased::getSupportFace() const {
    const App::PropertyLinkSub& Support = static_cast<Part::Part2DObject*>(Sketch.getValue())->Support;
    Part::Feature *part = static_cast<Part::Feature*>(Support.getValue());
    if (!part || !part->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))
        throw Base::Exception("Sketch has no support shape");

    const std::vector<std::string> &sub = Support.getSubValues();
    assert(sub.size()==1);
    // get the selected sub shape (a Face)
    const Part::TopoShape &shape = part->Shape.getShape();
    if (shape._Shape.IsNull())
        throw Base::Exception("Sketch support shape is empty!");

    TopoDS_Shape sh = shape.getSubShape(sub[0].c_str());
    if (sh.IsNull())
        throw Base::Exception("Null shape in SketchBased::getSupportFace()!");

    const TopoDS_Face face = TopoDS::Face(sh);
    if (face.IsNull())
        throw Base::Exception("Null face in SketchBased::getSupportFace()!");

    BRepAdaptor_Surface adapt(face);
    if (adapt.GetType() != GeomAbs_Plane)
        throw Base::Exception("No planar face in SketchBased::getSupportFace()!");

    return face;
}
예제 #2
0
void Part2DObject::transformPlacement(const Base::Placement &transform)
{
    Part::Feature *part = static_cast<Part::Feature*>(Support.getValue());
    if (part && part->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
        part->transformPlacement(transform);
        positionBySupport();
    } else
        GeoFeature::transformPlacement(transform);
}
예제 #3
0
const std::list<gp_Trsf> Scaled::getTransformations(const std::vector<App::DocumentObject*> originals)
{
    double factor = Factor.getValue();
    if (factor < Precision::Confusion())
        throw Base::Exception("Scaling factor too small");
    int occurrences = Occurrences.getValue();
    if (occurrences < 2)
        throw Base::Exception("At least two occurrences required");

    double f = (factor - 1.0) / double(occurrences - 1);

    // Find centre of gravity of first original
    // FIXME: This method will NOT give the expected result for more than one original!
    Part::Feature* originalFeature = static_cast<Part::Feature*>(originals.front());
    TopoDS_Shape original;

    if (originalFeature->getTypeId().isDerivedFrom(PartDesign::Additive::getClassTypeId())) {
        PartDesign::Additive* addFeature = static_cast<PartDesign::Additive*>(originalFeature);
        original = addFeature->AddShape.getShape()._Shape;
    } else if (originalFeature->getTypeId().isDerivedFrom(PartDesign::Subtractive::getClassTypeId())) {
        PartDesign::Subtractive* subFeature = static_cast<PartDesign::Subtractive*>(originalFeature);
        original = subFeature->SubShape.getShape()._Shape;
    }

    GProp_GProps props;
    BRepGProp::VolumeProperties(original,props);
    gp_Pnt cog = props.CentreOfMass();

    // Note: The original feature is NOT included in the list of transformations! Therefore
    // we start with occurrence number 1, not number 0
    std::list<gp_Trsf> transformations;
    gp_Trsf trans;
    transformations.push_back(trans); // identity transformation

    for (int i = 1; i < occurrences; i++) {
        trans.SetScale(cog, 1.0 + double(i) * f);
        transformations.push_back(trans);
    }

    return transformations;
}
void SketchBased::transformPlacement(const Base::Placement &transform)
{
    Part::Part2DObject *sketch = static_cast<Part::Part2DObject*>(Sketch.getValue());
    if (sketch && sketch->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) {
        Part::Feature *part = static_cast<Part::Feature*>(sketch->Support.getValue());
        if (part && part->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))
            part->transformPlacement(transform);
        else
            sketch->transformPlacement(transform);
        positionBySketch();
    }
}
예제 #5
0
// Note: We cannot return a reference, because it will become Null.
// Not clear where, because we check for IsNull() here, but as soon as it is passed out of
// this method, it becomes null!
const TopoDS_Face ProfileBased::getSupportFace() const {
    const Part::Part2DObject* sketch = getVerifiedSketch();
    if (sketch->MapMode.getValue() == Attacher::mmFlatFace  &&  sketch->Support.getValue()) {
        const auto &Support = sketch->Support;
        App::DocumentObject* ref = Support.getValue();

        Part::Feature *part = static_cast<Part::Feature*>(ref);
        if (part && part->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
            const std::vector<std::string> &sub = Support.getSubValues();
            assert(sub.size()==1);

            if (sub.at(0) == "") {
                // This seems to happen when sketch is on a datum plane
                return TopoDS::Face(Feature::makeShapeFromPlane(sketch));
            }

            // get the selected sub shape (a Face)
            const Part::TopoShape &shape = part->Shape.getShape();
            if (shape.getShape().IsNull())
                throw Base::ValueError("Sketch support shape is empty!");

            TopoDS_Shape sh = shape.getSubShape(sub[0].c_str());
            if (sh.IsNull())
                throw Base::ValueError("Null shape in SketchBased::getSupportFace()!");

            const TopoDS_Face face = TopoDS::Face(sh);
            if (face.IsNull())
                throw Base::ValueError("Null face in SketchBased::getSupportFace()!");

            BRepAdaptor_Surface adapt(face);
            if (adapt.GetType() != GeomAbs_Plane)
                throw Base::TypeError("No planar face in SketchBased::getSupportFace()!");

            return face;
        }
    }
    return TopoDS::Face(Feature::makeShapeFromPlane(sketch));

}
void Transformed::positionBySupport(void)
{
    Part::Feature *support = static_cast<Part::Feature*>(getSupportObject());
    if ((support != NULL) && support->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))
        this->Placement.setValue(support->Placement.getValue());
}
const std::list<gp_Trsf> MultiTransform::getTransformations(const std::vector<App::DocumentObject*> originals)
{
    std::vector<App::DocumentObject*> transFeatures = Transformations.getValues();

    // Find centre of gravity of first original
    // FIXME: This method will NOT give the expected result for more than one original!
    Part::Feature* originalFeature = static_cast<Part::Feature*>(originals.front());
    TopoDS_Shape original;

    if (originalFeature->getTypeId().isDerivedFrom(PartDesign::FeatureAddSub::getClassTypeId())) {
        PartDesign::FeatureAddSub* addFeature = static_cast<PartDesign::FeatureAddSub*>(originalFeature);
        if(addFeature->getAddSubType() == FeatureAddSub::Additive)
            original = addFeature->AddSubShape.getShape()._Shape;
        else 
            original = addFeature->AddSubShape.getShape()._Shape;
    }

    GProp_GProps props;
    BRepGProp::VolumeProperties(original,props);
    gp_Pnt cog = props.CentreOfMass();

    std::list<gp_Trsf> result;
    std::list<gp_Pnt> cogs;
    std::vector<App::DocumentObject*>::const_iterator f;

    for (f = transFeatures.begin(); f != transFeatures.end(); ++f) {
        if (!((*f)->getTypeId().isDerivedFrom(PartDesign::Transformed::getClassTypeId())))
            throw Base::Exception("Transformation features must be subclasses of Transformed");
        PartDesign::Transformed* transFeature = static_cast<PartDesign::Transformed*>(*f);
        std::list<gp_Trsf> newTransformations = transFeature->getTransformations(originals);

        if (result.empty()) {
            // First transformation Feature
            result = newTransformations;
            for (std::list<gp_Trsf>::const_iterator nt = newTransformations.begin(); nt != newTransformations.end(); ++nt) {
                cogs.push_back(cog.Transformed(*nt));
            }
        } else {
            // Retain a copy of the first set of transformations for iterator ot
            // We can't iterate through result if we are also adding elements with push_back()!
            std::list<gp_Trsf> oldTransformations;
            result.swap(oldTransformations); // empty result to receive new transformations
            std::list<gp_Pnt> oldCogs;
            cogs.swap(oldCogs); // empty cogs to receive new cogs

            if ((*f)->getTypeId() == PartDesign::Scaled::getClassTypeId()) {
                // Diagonal method
                // Multiply every element in the old transformations' slices with the corresponding
                // element in the newTransformations. Example:
                // a11 a12 a13 a14          b1    a11*b1 a12*b1 a13*b1 a14*b1
                // a21 a22 a23 a24   diag   b2  = a21*b2 a22*b2 a23*b2 a24*b1
                // a31 a23 a33 a34          b3    a31*b3 a23*b3 a33*b3 a34*b1
                // In other words, the length of the result vector is equal to the length of the
                // oldTransformations vector

                if (oldTransformations.size() % newTransformations.size() != 0)
                    throw Base::Exception("Number of occurrences must be a divisor of previous number of occurrences");

                unsigned sliceLength = oldTransformations.size() / newTransformations.size();
                std::list<gp_Trsf>::const_iterator ot = oldTransformations.begin();
                std::list<gp_Pnt>::const_iterator oc = oldCogs.begin();

                for (std::list<gp_Trsf>::const_iterator nt = newTransformations.begin(); nt != newTransformations.end(); ++nt) {
                    for (unsigned s = 0; s < sliceLength; s++) {
                        gp_Trsf trans;
                        double factor = nt->ScaleFactor(); // extract scale factor

                        if (factor > Precision::Confusion()) {
                            trans.SetScale(*oc, factor); // recreate the scaled transformation to use the correct COG
                            trans = trans * (*ot);
                            cogs.push_back(*oc); // Scaling does not affect the COG
                        } else {
                            trans = (*nt) * (*ot);
                            cogs.push_back(oc->Transformed(*nt));
                        }
                        result.push_back(trans);
                        ++ot;
                        ++oc;
                    }
                }
            } else {
                // Multiplication method: Combine the new transformations with the old ones.
                // All old transformations are multiplied with all new ones, so that the length of the
                // result vector is the length of the old and new transformations multiplied.
                // a11 a12         b1    a11*b1 a12*b1 a11*b2 a12*b2 a11*b3 a12*b3
                // a21 a22   mul   b2  = a21*b1 a22*b1 a21*b2 a22*b2 a21*b3 a22*b3
                //                 b3
                for (std::list<gp_Trsf>::const_iterator nt = newTransformations.begin(); nt != newTransformations.end(); ++nt) {
                    std::list<gp_Pnt>::const_iterator oc = oldCogs.begin();

                    for (std::list<gp_Trsf>::const_iterator ot = oldTransformations.begin(); ot != oldTransformations.end(); ++ot) {
                        result.push_back((*nt) * (*ot));
                        cogs.push_back(oc->Transformed(*nt));
                        ++oc;
                    }
                }
            }
            // What about the Additive method: Take the last (set of) transformations and use them as
            // "originals" for the next transformationFeature, so that something similar to a sweep
            // for transformations could be put together?
        }
    }

    return result;
}
예제 #8
0
void Part2DObject::positionBySupport(void)
{
    // recalculate support:
    Part::Feature *part = static_cast<Part::Feature*>(Support.getValue());
    if (!part || !part->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))
        return;

    Base::Placement Place = part->Placement.getValue();
    const std::vector<std::string> &sub = Support.getSubValues();
    assert(sub.size()==1);
    // get the selected sub shape (a Face)
    const Part::TopoShape &shape = part->Shape.getShape();
    if (shape._Shape.IsNull())
        throw Base::Exception("Support shape is empty!");
    TopoDS_Shape sh;
    try {
        sh = shape.getSubShape(sub[0].c_str());
    }
    catch (Standard_Failure) {
        throw Base::Exception("Face in support shape doesn't exist!");
    }
    const TopoDS_Face &face = TopoDS::Face(sh);
    if (face.IsNull())
        throw Base::Exception("Null face in Part2DObject::positionBySupport()!");

    BRepAdaptor_Surface adapt(face);
    if (adapt.GetType() != GeomAbs_Plane)
        throw Base::Exception("No planar face in Part2DObject::positionBySupport()!");

    bool Reverse = false;
    if (face.Orientation() == TopAbs_REVERSED)
        Reverse = true;

    gp_Pln plane = adapt.Plane();
    Standard_Boolean ok = plane.Direct();
    if (!ok) {
        // toggle if plane has a left-handed coordinate system
        plane.UReverse();
        Reverse = !Reverse;
    }

    gp_Ax1 Normal = plane.Axis();
    if (Reverse)
        Normal.Reverse();

    gp_Pnt ObjOrg(Place.getPosition().x,Place.getPosition().y,Place.getPosition().z);

    Handle (Geom_Plane) gPlane = new Geom_Plane(plane);
    GeomAPI_ProjectPointOnSurf projector(ObjOrg,gPlane);
    gp_Pnt SketchBasePoint = projector.NearestPoint();

    gp_Dir dir = Normal.Direction();
    gp_Ax3 SketchPos;

    Base::Vector3d dX,dY,dZ;
    Place.getRotation().multVec(Base::Vector3d(1,0,0),dX);
    Place.getRotation().multVec(Base::Vector3d(0,1,0),dY);
    Place.getRotation().multVec(Base::Vector3d(0,0,1),dZ);
    gp_Dir dirX(dX.x, dX.y, dX.z);
    gp_Dir dirY(dY.x, dY.y, dY.z);
    gp_Dir dirZ(dZ.x, dZ.y, dZ.z);
    double cosNX = dir.Dot(dirX);
    double cosNY = dir.Dot(dirY);
    double cosNZ = dir.Dot(dirZ);
    std::vector<double> cosXYZ;
    cosXYZ.push_back(fabs(cosNX));
    cosXYZ.push_back(fabs(cosNY));
    cosXYZ.push_back(fabs(cosNZ));

    int pos = std::max_element(cosXYZ.begin(), cosXYZ.end()) - cosXYZ.begin();

    // +X/-X
    if (pos == 0) {
        if (cosNX > 0)
            SketchPos = gp_Ax3(SketchBasePoint, dir, dirY);
        else
            SketchPos = gp_Ax3(SketchBasePoint, dir, -dirY);
    }
    // +Y/-Y
    else if (pos == 1) {
        if (cosNY > 0)
            SketchPos = gp_Ax3(SketchBasePoint, dir, -dirX);
        else
            SketchPos = gp_Ax3(SketchBasePoint, dir, dirX);
    }
    // +Z/-Z
    else {
        SketchPos = gp_Ax3(SketchBasePoint, dir, dirX);
    }

    gp_Trsf Trf;
    Trf.SetTransformation(SketchPos);
    Trf.Invert();

    Base::Matrix4D mtrx;

    gp_Mat m = Trf._CSFDB_Getgp_Trsfmatrix();
    gp_XYZ p = Trf._CSFDB_Getgp_Trsfloc();
    Standard_Real scale = 1.0;

    // set Rotation matrix
    mtrx[0][0] = scale * m._CSFDB_Getgp_Matmatrix(0,0);
    mtrx[0][1] = scale * m._CSFDB_Getgp_Matmatrix(0,1);
    mtrx[0][2] = scale * m._CSFDB_Getgp_Matmatrix(0,2);

    mtrx[1][0] = scale * m._CSFDB_Getgp_Matmatrix(1,0);
    mtrx[1][1] = scale * m._CSFDB_Getgp_Matmatrix(1,1);
    mtrx[1][2] = scale * m._CSFDB_Getgp_Matmatrix(1,2);

    mtrx[2][0] = scale * m._CSFDB_Getgp_Matmatrix(2,0);
    mtrx[2][1] = scale * m._CSFDB_Getgp_Matmatrix(2,1);
    mtrx[2][2] = scale * m._CSFDB_Getgp_Matmatrix(2,2);

    // set pos vector
    mtrx[0][3] = p._CSFDB_Getgp_XYZx();
    mtrx[1][3] = p._CSFDB_Getgp_XYZy();
    mtrx[2][3] = p._CSFDB_Getgp_XYZz();

    // check the angle against the Z Axis
    //Standard_Real a = Normal.Angle(gp_Ax1(gp_Pnt(0,0,0),gp_Dir(0,0,1)));

    Placement.setValue(Base::Placement(mtrx));
}