void Revolution::updateAxis(void) { Part::Part2DObject* sketch = getVerifiedSketch(); Base::Placement SketchPlm = sketch->Placement.getValue(); // get reference axis App::DocumentObject *pcReferenceAxis = ReferenceAxis.getValue(); const std::vector<std::string> &subReferenceAxis = ReferenceAxis.getSubValues(); if (pcReferenceAxis && pcReferenceAxis == sketch) { bool hasValidAxis=false; Base::Axis axis; if (subReferenceAxis[0] == "V_Axis") { hasValidAxis = true; axis = sketch->getAxis(Part::Part2DObject::V_Axis); } else if (subReferenceAxis[0] == "H_Axis") { hasValidAxis = true; axis = sketch->getAxis(Part::Part2DObject::H_Axis); } else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0,4) == "Axis") { int AxId = std::atoi(subReferenceAxis[0].substr(4,4000).c_str()); if (AxId >= 0 && AxId < sketch->getAxisCount()) { hasValidAxis = true; axis = sketch->getAxis(AxId); } } if (hasValidAxis) { axis *= SketchPlm; Base::Vector3d base=axis.getBase(); Base::Vector3d dir=axis.getDirection(); Base.setValue(base.x,base.y,base.z); Axis.setValue(dir.x,dir.y,dir.z); } } }
int ProfileBased::getSketchAxisCount(void) const { Part::Part2DObject *sketch = static_cast<Part::Part2DObject*>(Profile.getValue()); if (!sketch) return -1; // the link to the sketch is lost return sketch->getAxisCount(); }
void CmdPartDesignPad::activated(int iMsg) { unsigned int n = getSelection().countObjectsOfType(Part::Part2DObject::getClassTypeId()); if (n != 1) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), QObject::tr("Select a sketch or 2D object.")); return; } std::string FeatName = getUniqueObjectName("Pad"); std::vector<App::DocumentObject*> Sel = getSelection().getObjectsOfType(Part::Part2DObject::getClassTypeId()); Part::Part2DObject* sketch = static_cast<Part::Part2DObject*>(Sel.front()); const TopoDS_Shape& shape = sketch->Shape.getValue(); if (shape.IsNull()) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), QObject::tr("The shape of the selected object is empty.")); return; } // count free wires int ctWires=0; TopExp_Explorer ex; for (ex.Init(shape, TopAbs_WIRE); ex.More(); ex.Next()) { ctWires++; } if (ctWires == 0) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), QObject::tr("The shape of the selected object is not a wire.")); return; } App::DocumentObject* support = sketch->Support.getValue(); openCommand("Make Pad"); doCommand(Doc,"App.activeDocument().addObject(\"PartDesign::Pad\",\"%s\")",FeatName.c_str()); doCommand(Doc,"App.activeDocument().%s.Sketch = App.activeDocument().%s",FeatName.c_str(),sketch->getNameInDocument()); doCommand(Doc,"App.activeDocument().%s.Length = 10.0",FeatName.c_str()); updateActive(); if (isActiveObjectValid()) { doCommand(Gui,"Gui.activeDocument().hide(\"%s\")",sketch->getNameInDocument()); if (support) doCommand(Gui,"Gui.activeDocument().hide(\"%s\")",support->getNameInDocument()); } doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); //commitCommand(); adjustCameraPosition(); if (support) { copyVisual(FeatName.c_str(), "ShapeColor", support->getNameInDocument()); copyVisual(FeatName.c_str(), "LineColor", support->getNameInDocument()); copyVisual(FeatName.c_str(), "PointColor", support->getNameInDocument()); } }
void ProfileBased::transformPlacement(const Base::Placement &transform) { Part::Feature* feat = getBaseObject(/* silent = */ true); if (feat) { feat->transformPlacement(transform); } else { Part::Part2DObject *sketch = getVerifiedSketch(); sketch->transformPlacement(transform); } positionByPrevious(); }
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(); } }
void ProfileBased::getAxis(const App::DocumentObject *pcReferenceAxis, const std::vector<std::string> &subReferenceAxis, Base::Vector3d& base, Base::Vector3d& dir) { dir = Base::Vector3d(0,0,0); // If unchanged signals that no valid axis was found if (pcReferenceAxis == NULL) return; App::DocumentObject* profile = Profile.getValue(); gp_Pln sketchplane; if (profile->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) { Part::Part2DObject* sketch = getVerifiedSketch(); Base::Placement SketchPlm = sketch->Placement.getValue(); Base::Vector3d SketchVector = Base::Vector3d(0, 0, 1); Base::Rotation SketchOrientation = SketchPlm.getRotation(); SketchOrientation.multVec(SketchVector, SketchVector); Base::Vector3d SketchPos = SketchPlm.getPosition(); sketchplane = gp_Pln(gp_Pnt(SketchPos.x, SketchPos.y, SketchPos.z), gp_Dir(SketchVector.x, SketchVector.y, SketchVector.z)); if (pcReferenceAxis == profile) { bool hasValidAxis = false; Base::Axis axis; if (subReferenceAxis[0] == "V_Axis") { hasValidAxis = true; axis = sketch->getAxis(Part::Part2DObject::V_Axis); } else if (subReferenceAxis[0] == "H_Axis") { hasValidAxis = true; axis = sketch->getAxis(Part::Part2DObject::H_Axis); } else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0, 4) == "Axis") { int AxId = std::atoi(subReferenceAxis[0].substr(4, 4000).c_str()); if (AxId >= 0 && AxId < sketch->getAxisCount()) { hasValidAxis = true; axis = sketch->getAxis(AxId); } } if (hasValidAxis) { axis *= SketchPlm; base = axis.getBase(); dir = axis.getDirection(); return; } //else - an edge of the sketch was selected as an axis } } else if (profile->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { Base::Placement SketchPlm = getVerifiedObject()->Placement.getValue(); Base::Vector3d SketchVector = getProfileNormal(); Base::Vector3d SketchPos = SketchPlm.getPosition(); sketchplane = gp_Pln(gp_Pnt(SketchPos.x, SketchPos.y, SketchPos.z), gp_Dir(SketchVector.x, SketchVector.y, SketchVector.z)); } // get reference axis if (pcReferenceAxis->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())) { const PartDesign::Line* line = static_cast<const PartDesign::Line*>(pcReferenceAxis); base = line->getBasePoint(); dir = line->getDirection(); // Check that axis is perpendicular with sketch plane! if (sketchplane.Axis().Direction().IsParallel(gp_Dir(dir.x, dir.y, dir.z), Precision::Angular())) throw Base::ValueError("Rotation axis must not be perpendicular with the sketch plane"); return; } if (pcReferenceAxis->getTypeId().isDerivedFrom(App::Line::getClassTypeId())) { const App::Line* line = static_cast<const App::Line*>(pcReferenceAxis); base = Base::Vector3d(0,0,0); line->Placement.getValue().multVec(Base::Vector3d (1,0,0), dir); // Check that axis is perpendicular with sketch plane! if (sketchplane.Axis().Direction().IsParallel(gp_Dir(dir.x, dir.y, dir.z), Precision::Angular())) throw Base::ValueError("Rotation axis must not be perpendicular with the sketch plane"); return; } if (pcReferenceAxis->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { if (subReferenceAxis.empty()) throw Base::ValueError("No rotation axis reference specified"); const Part::Feature* refFeature = static_cast<const Part::Feature*>(pcReferenceAxis); Part::TopoShape refShape = refFeature->Shape.getShape(); TopoDS_Shape ref = refShape.getSubShape(subReferenceAxis[0].c_str()); if (ref.ShapeType() == TopAbs_EDGE) { TopoDS_Edge refEdge = TopoDS::Edge(ref); if (refEdge.IsNull()) throw Base::ValueError("Failed to extract rotation edge"); BRepAdaptor_Curve adapt(refEdge); if (adapt.GetType() != GeomAbs_Line) throw Base::TypeError("Rotation edge must be a straight line"); gp_Pnt b = adapt.Line().Location(); base = Base::Vector3d(b.X(), b.Y(), b.Z()); gp_Dir d = adapt.Line().Direction(); dir = Base::Vector3d(d.X(), d.Y(), d.Z()); // Check that axis is co-planar with sketch plane! // Check that axis is perpendicular with sketch plane! if (sketchplane.Axis().Direction().IsParallel(d, Precision::Angular())) throw Base::ValueError("Rotation axis must not be perpendicular with the sketch plane"); return; } else { throw Base::TypeError("Rotation reference must be an edge"); } } throw Base::TypeError("Rotation axis reference is invalid"); }
void CmdPartDesignMigrate::activated(int iMsg) { Q_UNUSED(iMsg); App::Document *doc = getDocument(); std::set<PartDesign::Feature*> migrateFeatures; // Retrive all PartDesign Features objects and filter out features already belongs to some body for ( const auto & feat: doc->getObjects( ) ) { if( feat->isDerivedFrom( PartDesign::Feature::getClassTypeId() ) && !PartDesign::Body::findBodyOf( feat ) && PartDesign::Body::isSolidFeature ( feat ) ) { migrateFeatures.insert ( static_cast <PartDesign::Feature *>( feat ) ); } } if ( migrateFeatures.empty() ) { if ( !PartDesignGui::isModernWorkflow ( doc ) ) { // If there is nothing to migrate and workflow is still old just set it to modern PartDesignGui::WorkflowManager::instance()->forceWorkflow ( doc, PartDesignGui::Workflow::Modern ); } else { // Huh? nothing to migrate? QMessageBox::warning ( 0, QObject::tr ( "Nothing to migrate" ), QObject::tr ( "No PartDesign features which doesn't belong to a body found." " Nothing to migrate." ) ); } return; } // Note: this action is undoable, should it be? PartDesignGui::WorkflowManager::instance()->forceWorkflow ( doc, PartDesignGui::Workflow::Modern ); // Put features into chains. Each chain should become a separate body. std::list< std::list<PartDesign::Feature *> > featureChains; std::list<PartDesign::Feature *> chain; //< the current chain we are working on for (auto featIt = migrateFeatures.begin(); !migrateFeatures.empty(); ) { Part::Feature *base = (*featIt)->getBaseObject( /*silent =*/ true ); chain.push_front ( *featIt ); if ( !base || !base->isDerivedFrom (PartDesign::Feature::getClassTypeId () ) || PartDesignGui::isAnyNonPartDesignLinksTo ( static_cast <PartDesign::Feature *>(base), /*respectGroups=*/ true ) ) { // a feature based on nothing as well as on non-partdesign solid starts a new chain auto newChainIt = featureChains.emplace (featureChains.end()); newChainIt->splice (newChainIt->end(), chain); } else { // we are basing on some partdesign feature which supposed to belong to some body PartDesign::Feature *baseFeat = static_cast <PartDesign::Feature *>( base ); auto baseFeatSetIt = find ( migrateFeatures.begin (), migrateFeatures.end (), baseFeat ); if ( baseFeatSetIt != migrateFeatures.end() ) { // base feature is pending for migration, switch to it and continue over migrateFeatures.erase(featIt); featIt = baseFeatSetIt; continue; } else { // The base feature seems already assigned to some chain // Find which std::list<PartDesign::Feature *>::iterator baseFeatIt; auto chainIt = std::find_if( featureChains.begin(), featureChains.end(), [baseFeat, &baseFeatIt] ( std::list<PartDesign::Feature *>&chain ) mutable -> bool { baseFeatIt = std::find( chain.begin(), chain.end(), baseFeat ); return baseFeatIt != chain.end(); } ); if ( chainIt != featureChains.end() ) { assert (baseFeatIt != chainIt->end()); if ( std::next ( baseFeatIt ) == chainIt->end() ) { // just append our chain to already found chainIt->splice ( chainIt->end(), chain ); // TODO If we will hit a third part everything will be messed up again. // Probably it will require a yet another smart-ass find_if. (2015-08-10, Fat-Zer) } else { // We have a fork of a partDesign feature here // add a chain for current body auto newChainIt = featureChains.emplace (featureChains.end()); newChainIt->splice (newChainIt->end(), chain); // add a chain for forked one newChainIt = featureChains.emplace (featureChains.end()); newChainIt->splice (newChainIt->end(), *chainIt, std::next ( baseFeatIt ), chainIt->end()); } } else { // The feature is not present in list pending for migration, // This generally shouldn't happen but may be if we run into some broken file // Try to find out the body we should insert into // TODO Some error/warning is needed here (2015-08-10, Fat-Zer) auto newChainIt = featureChains.emplace (featureChains.end()); newChainIt->splice (newChainIt->end(), chain); } } } migrateFeatures.erase ( featIt ); featIt = migrateFeatures.begin (); // TODO Align visibility (2015-08-17, Fat-Zer) } /* for */ // TODO make it work without parts (2015-09-04, Fat-Zer) // add a part if there is no active yet App::Part *actPart = PartDesignGui::assertActivePart (); if (!actPart) { return; } // do the actual migration Gui::Command::openCommand("Migrate legacy part design features to Bodies"); for ( auto chainIt = featureChains.begin(); !featureChains.empty(); featureChains.erase (chainIt), chainIt = featureChains.begin () ) { #ifndef FC_DEBUG if ( chainIt->empty () ) { // prevent crash in release in case of errors continue; } #else assert ( !chainIt->empty () ); #endif Part::Feature *base = chainIt->front()->getBaseObject ( /*silent =*/ true ); // Find a suitable chain to work with for( ; chainIt != featureChains.end(); chainIt ++) { base = chainIt->front()->getBaseObject ( /*silent =*/ true ); if (!base || !base->isDerivedFrom ( PartDesign::Feature::getClassTypeId () ) ) { break; // no base is ok } else { // The base feature is a PartDesign, it's a fork, try to reassign it to a body... base = PartDesign::Body::findBodyOf ( base ); if ( base ) { break; } } } if ( chainIt == featureChains.end() ) { // Shouldn't happen, may be only in case of some circular dependency? // TODO Some error message (2015-08-11, Fat-Zer) chainIt = featureChains.begin(); base = chainIt->front()->getBaseObject ( /*silent =*/ true ); } // Construct a Pretty Body name based on the Tip std::string bodyName = getUniqueObjectName ( std::string ( chainIt->back()->getNameInDocument() ).append ( "Body" ).c_str () ) ; // Create a body for the chain doCommand ( Doc,"App.activeDocument().addObject('PartDesign::Body','%s')", bodyName.c_str () ); doCommand ( Doc,"App.activeDocument().%s.addObject(App.ActiveDocument.%s)", actPart->getNameInDocument (), bodyName.c_str () ); if (base) { doCommand ( Doc,"App.activeDocument().%s.BaseFeature = App.activeDocument().%s", bodyName.c_str (), base->getNameInDocument () ); } // Fill the body with features for ( auto feature: *chainIt ) { if ( feature->isDerivedFrom ( PartDesign::ProfileBased::getClassTypeId() ) ) { // add the sketch and also reroute it if needed PartDesign::ProfileBased *sketchBased = static_cast<PartDesign::ProfileBased *> ( feature ); Part::Part2DObject *sketch = sketchBased->getVerifiedSketch( /*silent =*/ true); if ( sketch ) { doCommand ( Doc,"App.activeDocument().%s.addObject(App.activeDocument().%s)", bodyName.c_str (), sketch->getNameInDocument() ); if ( sketch->isDerivedFrom ( Sketcher::SketchObject::getClassTypeId() ) ) { try { PartDesignGui::fixSketchSupport ( static_cast<Sketcher::SketchObject *> ( sketch ) ); } catch (Base::Exception &) { QMessageBox::critical(Gui::getMainWindow(), QObject::tr("Sketch plane cannot be migrated"), QObject::tr("Please edit '%1' and redefine it to use a Base or " "Datum plane as the sketch plane."). arg(QString::fromUtf8(sketch->Label.getValue()) ) ); } } else { // TODO Message that sketchbased is based not on a sketch (2015-08-11, Fat-Zer) } } } doCommand ( Doc,"App.activeDocument().%s.addObject(App.activeDocument().%s)", bodyName.c_str (), feature->getNameInDocument() ); PartDesignGui::relinkToBody ( feature ); } } updateActive(); }
void TaskRevolutionParameters::fillAxisCombo(bool forceRefill) { // TODO share the code with TaskTransformedParameters (2015-08-31, Fat-Zer) bool oldVal_blockUpdate = blockUpdate; blockUpdate = true; if(axesInList.size() == 0) forceRefill = true;//not filled yet, full refill if (forceRefill){ ui->axis->clear(); for(size_t i = 0 ; i < axesInList.size() ; i++ ){ delete axesInList[i]; } this->axesInList.clear(); //add sketch axes PartDesign::ProfileBased* pcFeat = static_cast<PartDesign::Revolution*>(vp->getObject()); Part::Part2DObject* pcSketch = static_cast<Part::Part2DObject*>(pcFeat->Profile.getValue()); if (pcSketch){ addAxisToCombo(pcSketch,"V_Axis",QObject::tr("Vertical sketch axis")); addAxisToCombo(pcSketch,"H_Axis",QObject::tr("Horizontal sketch axis")); for (int i=0; i < pcSketch->getAxisCount(); i++) { QString itemText = QObject::tr("Construction line %1").arg(i+1); std::stringstream sub; sub << "Axis" << i; addAxisToCombo(pcSketch,sub.str(),itemText); } } //add part axes App::DocumentObject* obj = vp->getObject(); PartDesign::Body * body = PartDesign::Body::findBodyOf ( obj ); if (body) { try { App::Origin* orig = body->getOrigin(); addAxisToCombo(orig->getX(),"",tr("Base X axis")); addAxisToCombo(orig->getY(),"",tr("Base Y axis")); addAxisToCombo(orig->getZ(),"",tr("Base Z axis")); } catch (const Base::Exception &ex) { Base::Console().Error ("%s\n", ex.what() ); } } //add "Select reference" addAxisToCombo(0,std::string(),tr("Select reference...")); }//endif forceRefill //add current link, if not in list //first, figure out the item number for current axis int indexOfCurrent = -1; App::DocumentObject* ax = propReferenceAxis->getValue(); const std::vector<std::string> &subList = propReferenceAxis->getSubValues(); for(size_t i = 0 ; i < axesInList.size() ; i++) { if(ax == axesInList[i]->getValue() && subList == axesInList[i]->getSubValues()) indexOfCurrent = i; } if ( indexOfCurrent == -1 && ax ){ assert(subList.size() <= 1); std::string sub; if (subList.size()>0) sub = subList[0]; addAxisToCombo(ax, sub, getRefStr(ax, subList)); indexOfCurrent = axesInList.size()-1; } //highlight current. if (indexOfCurrent != -1) ui->axis->setCurrentIndex(indexOfCurrent); blockUpdate = oldVal_blockUpdate; }
const std::list<gp_Trsf> PolarPattern::getTransformations(const std::vector<App::DocumentObject*>) { float angle = Angle.getValue(); if (angle < Precision::Confusion()) throw Base::Exception("Pattern angle too small"); int occurrences = Occurrences.getValue(); if (occurrences < 2) throw Base::Exception("At least two occurrences required"); bool reversed = Reversed.getValue(); double offset; if (std::abs(angle - 360.0) < Precision::Confusion()) offset = Base::toRadians<double>(angle) / occurrences; // Because e.g. two occurrences in 360 degrees need to be 180 degrees apart else offset = Base::toRadians<double>(angle) / (occurrences - 1); App::DocumentObject* refObject = Axis.getValue(); if (refObject == NULL) throw Base::Exception("No axis reference specified"); if (!refObject->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) throw Base::Exception("Axis reference must be edge of a feature"); std::vector<std::string> subStrings = Axis.getSubValues(); if (subStrings.empty() || subStrings[0].empty()) throw Base::Exception("No axis reference specified"); gp_Pnt axbase; gp_Dir axdir; if (refObject->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) { Part::Part2DObject* refSketch = static_cast<Part::Part2DObject*>(refObject); Base::Axis axis; if (subStrings[0] == "H_Axis") axis = refSketch->getAxis(Part::Part2DObject::H_Axis); else if (subStrings[0] == "V_Axis") axis = refSketch->getAxis(Part::Part2DObject::V_Axis); else if (subStrings[0] == "N_Axis") axis = refSketch->getAxis(Part::Part2DObject::N_Axis); else if (subStrings[0].size() > 4 && subStrings[0].substr(0,4) == "Axis") { int AxId = std::atoi(subStrings[0].substr(4,4000).c_str()); if (AxId >= 0 && AxId < refSketch->getAxisCount()) axis = refSketch->getAxis(AxId); } axis *= refSketch->Placement.getValue(); axbase = gp_Pnt(axis.getBase().x, axis.getBase().y, axis.getBase().z); axdir = gp_Dir(axis.getDirection().x, axis.getDirection().y, axis.getDirection().z); } else { Part::Feature* refFeature = static_cast<Part::Feature*>(refObject); Part::TopoShape refShape = refFeature->Shape.getShape(); TopoDS_Shape ref = refShape.getSubShape(subStrings[0].c_str()); if (ref.ShapeType() == TopAbs_EDGE) { TopoDS_Edge refEdge = TopoDS::Edge(ref); if (refEdge.IsNull()) throw Base::Exception("Failed to extract axis edge"); BRepAdaptor_Curve adapt(refEdge); if (adapt.GetType() != GeomAbs_Line) throw Base::Exception("Axis edge must be a straight line"); axbase = adapt.Value(adapt.FirstParameter()); axdir = adapt.Line().Direction(); } else { throw Base::Exception("Axis reference must be an edge"); } } TopLoc_Location invObjLoc = this->getLocation().Inverted(); axbase.Transform(invObjLoc.Transformation()); axdir.Transform(invObjLoc.Transformation()); gp_Ax2 axis(axbase, axdir); if (reversed) axis.SetDirection(axis.Direction().Reversed()); // 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.SetRotation(axis.Axis(), i * offset); transformations.push_back(trans); } return transformations; }
App::DocumentObjectExecReturn *Groove::execute(void) { // Validate parameters double angle = Angle.getValue(); if (angle < Precision::Confusion()) return new App::DocumentObjectExecReturn("Angle of groove too small"); if (angle > 360.0) return new App::DocumentObjectExecReturn("Angle of groove too large"); angle = Base::toRadians<double>(angle); // Reverse angle if selected if (Reversed.getValue() && !Midplane.getValue()) angle *= (-1.0); Part::Part2DObject* sketch = 0; std::vector<TopoDS_Wire> wires; TopoDS_Shape support; try { sketch = getVerifiedSketch(); wires = getSketchWires(); support = getSupportShape(); } catch (const Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } // get the Sketch plane Base::Placement SketchPlm = sketch->Placement.getValue(); // get reference axis App::DocumentObject *pcReferenceAxis = ReferenceAxis.getValue(); const std::vector<std::string> &subReferenceAxis = ReferenceAxis.getSubValues(); if (pcReferenceAxis && pcReferenceAxis == sketch) { bool hasValidAxis=false; Base::Axis axis; if (subReferenceAxis[0] == "V_Axis") { hasValidAxis = true; axis = sketch->getAxis(Part::Part2DObject::V_Axis); } else if (subReferenceAxis[0] == "H_Axis") { hasValidAxis = true; axis = sketch->getAxis(Part::Part2DObject::H_Axis); } else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0,4) == "Axis") { int AxId = std::atoi(subReferenceAxis[0].substr(4,4000).c_str()); if (AxId >= 0 && AxId < sketch->getAxisCount()) { hasValidAxis = true; axis = sketch->getAxis(AxId); } } if (hasValidAxis) { axis *= SketchPlm; Base::Vector3d base=axis.getBase(); Base::Vector3d dir=axis.getDirection(); Base.setValue(base.x,base.y,base.z); Axis.setValue(dir.x,dir.y,dir.z); } } // get revolve axis Base::Vector3f b = Base.getValue(); gp_Pnt pnt(b.x,b.y,b.z); Base::Vector3f v = Axis.getValue(); gp_Dir dir(v.x,v.y,v.z); try { TopoDS_Shape sketchshape = makeFace(wires); if (sketchshape.IsNull()) return new App::DocumentObjectExecReturn("Creating a face from sketch failed"); // Rotate the face by half the angle to get Groove symmetric to sketch plane if (Midplane.getValue()) { gp_Trsf mov; mov.SetRotation(gp_Ax1(pnt, dir), Base::toRadians<double>(Angle.getValue()) * (-1.0) / 2.0); TopLoc_Location loc(mov); sketchshape.Move(loc); } this->positionBySketch(); TopLoc_Location invObjLoc = this->getLocation().Inverted(); pnt.Transform(invObjLoc.Transformation()); dir.Transform(invObjLoc.Transformation()); support.Move(invObjLoc); sketchshape.Move(invObjLoc); // Check distance between sketchshape and axis - to avoid failures and crashes if (checkLineCrossesFace(gp_Lin(pnt, dir), TopoDS::Face(sketchshape))) return new App::DocumentObjectExecReturn("Revolve axis intersects the sketch"); // revolve the face to a solid BRepPrimAPI_MakeRevol RevolMaker(sketchshape, gp_Ax1(pnt, dir), angle); if (RevolMaker.IsDone()) { TopoDS_Shape result = RevolMaker.Shape(); // set the subtractive shape property for later usage in e.g. pattern this->SubShape.setValue(result); // cut out groove to get one result object BRepAlgoAPI_Cut mkCut(support, result); // Let's check if the fusion has been successful if (!mkCut.IsDone()) throw Base::Exception("Cut out of support failed"); // we have to get the solids (fuse sometimes creates compounds) TopoDS_Shape solRes = this->getSolid(mkCut.Shape()); if (solRes.IsNull()) return new App::DocumentObjectExecReturn("Resulting shape is not a solid"); this->Shape.setValue(solRes); } else return new App::DocumentObjectExecReturn("Could not revolve the sketch!"); return App::DocumentObject::StdReturn; } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); if (std::string(e->GetMessageString()) == "TopoDS::Face") return new App::DocumentObjectExecReturn("Could not create face from sketch.\n" "Intersecting sketch entities or multiple faces in a sketch are not allowed."); else return new App::DocumentObjectExecReturn(e->GetMessageString()); } catch (Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } }
const std::list<gp_Trsf> LinearPattern::getTransformations(const std::vector<App::DocumentObject*>) { double distance = Length.getValue(); if (distance < Precision::Confusion()) throw Base::Exception("Pattern length too small"); int occurrences = Occurrences.getValue(); if (occurrences < 2) throw Base::Exception("At least two occurrences required"); bool reversed = Reversed.getValue(); double offset = distance / (occurrences - 1); App::DocumentObject* refObject = Direction.getValue(); if (refObject == NULL) throw Base::Exception("No direction reference specified"); std::vector<std::string> subStrings = Direction.getSubValues(); if (subStrings.empty()) throw Base::Exception("No direction reference specified"); gp_Dir dir; if (refObject->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) { Part::Part2DObject* refSketch = static_cast<Part::Part2DObject*>(refObject); Base::Axis axis; if (subStrings[0] == "H_Axis") axis = refSketch->getAxis(Part::Part2DObject::H_Axis); else if (subStrings[0] == "V_Axis") axis = refSketch->getAxis(Part::Part2DObject::V_Axis); else if (subStrings[0] == "N_Axis") axis = refSketch->getAxis(Part::Part2DObject::N_Axis); else if (subStrings[0].size() > 4 && subStrings[0].substr(0,4) == "Axis") { int AxId = std::atoi(subStrings[0].substr(4,4000).c_str()); if (AxId >= 0 && AxId < refSketch->getAxisCount()) axis = refSketch->getAxis(AxId); } axis *= refSketch->Placement.getValue(); dir = gp_Dir(axis.getDirection().x, axis.getDirection().y, axis.getDirection().z); } else if (refObject->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId())) { PartDesign::Plane* plane = static_cast<PartDesign::Plane*>(refObject); Base::Vector3d d = plane->getNormal(); dir = gp_Dir(d.x, d.y, d.z); } else if (refObject->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())) { PartDesign::Line* line = static_cast<PartDesign::Line*>(refObject); Base::Vector3d d = line->getDirection(); dir = gp_Dir(d.x, d.y, d.z); } else if (refObject->getTypeId().isDerivedFrom(App::Line::getClassTypeId())) { App::Line* line = static_cast<App::Line*>(refObject); Base::Rotation rot = line->Placement.getValue().getRotation(); Base::Vector3d d(1,0,0); rot.multVec(d, d); dir = gp_Dir(d.x, d.y, d.z); } else if (refObject->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { if (subStrings[0].empty()) throw Base::Exception("No direction reference specified"); Part::Feature* refFeature = static_cast<Part::Feature*>(refObject); Part::TopoShape refShape = refFeature->Shape.getShape(); TopoDS_Shape ref = refShape.getSubShape(subStrings[0].c_str()); if (ref.ShapeType() == TopAbs_FACE) { TopoDS_Face refFace = TopoDS::Face(ref); if (refFace.IsNull()) throw Base::Exception("Failed to extract direction plane"); BRepAdaptor_Surface adapt(refFace); if (adapt.GetType() != GeomAbs_Plane) throw Base::Exception("Direction face must be planar"); dir = adapt.Plane().Axis().Direction(); } else if (ref.ShapeType() == TopAbs_EDGE) { TopoDS_Edge refEdge = TopoDS::Edge(ref); if (refEdge.IsNull()) throw Base::Exception("Failed to extract direction edge"); BRepAdaptor_Curve adapt(refEdge); if (adapt.GetType() != GeomAbs_Line) throw Base::Exception("Direction edge must be a straight line"); dir = adapt.Line().Direction(); } else { throw Base::Exception("Direction reference must be edge or face"); } } else { throw Base::Exception("Direction reference must be edge/face of a feature or a datum line/plane"); } TopLoc_Location invObjLoc = this->getLocation().Inverted(); dir.Transform(invObjLoc.Transformation()); gp_Vec direction(dir.X(), dir.Y(), dir.Z()); if (reversed) direction.Reverse(); // 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.SetTranslation(direction * i * offset); transformations.push_back(trans); } return transformations; }
int SketchBased::getSketchAxisCount(void) const { Part::Part2DObject *sketch = static_cast<Part::Part2DObject*>(Sketch.getValue()); return sketch->getAxisCount(); }