int Part::ImportStepParts(App::Document *pcDoc, const char* Name) { STEPControl_Reader aReader; TopoDS_Shape aShape; Base::FileInfo fi(Name); if (!fi.exists()) { std::stringstream str; str << "File '" << Name << "' does not exist!"; throw Base::Exception(str.str().c_str()); } std::string encodednamestr = encodeFilename(std::string(Name)); const char * encodedname = encodednamestr.c_str(); if (aReader.ReadFile((Standard_CString)encodedname) != IFSelect_RetDone) { throw Base::Exception("Cannot open STEP file"); } Handle_Message_ProgressIndicator pi = new ProgressIndicator(100); aReader.WS()->MapReader()->SetProgress(pi); pi->NewScope(100, "Reading STEP file..."); pi->Show(); // Root transfers Standard_Integer nbr = aReader.NbRootsForTransfer(); //aReader.PrintCheckTransfer (failsonly, IFSelect_ItemsByEntity); for (Standard_Integer n = 1; n<= nbr; n++) { Base::Console().Log("STEP: Transferring Root %d\n",n); aReader.TransferRoot(n); } pi->EndScope(); // Collecting resulting entities Standard_Integer nbs = aReader.NbShapes(); if (nbs == 0) { throw Base::Exception("No shapes found in file "); } else { //Handle(StepData_StepModel) Model = aReader.StepModel(); //Handle_XSControl_WorkSession ws = aReader.WS(); //Handle_XSControl_TransferReader tr = ws->TransferReader(); std::map<int, Quantity_Color> hash_col; //ReadColors(aReader.WS(), hash_col); //ReadNames(aReader.WS()); for (Standard_Integer i=1; i<=nbs; i++) { Base::Console().Log("STEP: Transferring Shape %d\n",i); aShape = aReader.Shape(i); // load each solid as an own object TopExp_Explorer ex; for (ex.Init(aShape, TopAbs_SOLID); ex.More(); ex.Next()) { // get the shape const TopoDS_Solid& aSolid = TopoDS::Solid(ex.Current()); std::string name = fi.fileNamePure(); //Handle_Standard_Transient ent = tr->EntityFromShapeResult(aSolid, 3); //if (!ent.IsNull()) { // name += ws->Model()->StringLabel(ent)->ToCString(); //} Part::Feature *pcFeature; pcFeature = static_cast<Part::Feature*>(pcDoc->addObject("Part::Feature", name.c_str())); pcFeature->Shape.setValue(aSolid); // This is a trick to access the GUI via Python and set the color property // of the associated view provider. If no GUI is up an exception is thrown // and cleared immediately std::map<int, Quantity_Color>::iterator it = hash_col.find(aSolid.HashCode(INT_MAX)); if (it != hash_col.end()) { try { Py::Object obj(pcFeature->getPyObject(), true); Py::Object vp(obj.getAttr("ViewObject")); Py::Tuple col(3); col.setItem(0, Py::Float(it->second.Red())); col.setItem(1, Py::Float(it->second.Green())); col.setItem(2, Py::Float(it->second.Blue())); vp.setAttr("ShapeColor", col); //Base::Console().Message("Set color to shape\n"); } catch (Py::Exception& e) { e.clear(); } } } // load all non-solids now for (ex.Init(aShape, TopAbs_SHELL, TopAbs_SOLID); ex.More(); ex.Next()) { // get the shape const TopoDS_Shell& aShell = TopoDS::Shell(ex.Current()); std::string name = fi.fileNamePure(); //Handle_Standard_Transient ent = tr->EntityFromShapeResult(aShell, 3); //if (!ent.IsNull()) { // name += ws->Model()->StringLabel(ent)->ToCString(); //} Part::Feature *pcFeature = static_cast<Part::Feature*>(pcDoc->addObject("Part::Feature", name.c_str())); pcFeature->Shape.setValue(aShell); } // put all other free-flying shapes into a single compound Standard_Boolean emptyComp = Standard_True; BRep_Builder builder; TopoDS_Compound comp; builder.MakeCompound(comp); for (ex.Init(aShape, TopAbs_FACE, TopAbs_SHELL); ex.More(); ex.Next()) { if (!ex.Current().IsNull()) { builder.Add(comp, ex.Current()); emptyComp = Standard_False; } } for (ex.Init(aShape, TopAbs_WIRE, TopAbs_FACE); ex.More(); ex.Next()) { if (!ex.Current().IsNull()) { builder.Add(comp, ex.Current()); emptyComp = Standard_False; } } for (ex.Init(aShape, TopAbs_EDGE, TopAbs_WIRE); ex.More(); ex.Next()) { if (!ex.Current().IsNull()) { builder.Add(comp, ex.Current()); emptyComp = Standard_False; } } for (ex.Init(aShape, TopAbs_VERTEX, TopAbs_EDGE); ex.More(); ex.Next()) { if (!ex.Current().IsNull()) { builder.Add(comp, ex.Current()); emptyComp = Standard_False; } } if (!emptyComp) { std::string name = fi.fileNamePure(); Part::Feature *pcFeature = static_cast<Part::Feature*>(pcDoc->addObject ("Part::Feature", name.c_str())); pcFeature->Shape.setValue(comp); } } } return 0; }
// 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; }
App::DocumentObjectExecReturn* ShapeBinder::execute(void) { if (!this->isRestoring()) { Part::Feature* obj = nullptr; std::vector<std::string> subs; ShapeBinder::getFilteredReferences(&Support, obj, subs); //if we have a link we rebuild the shape, but we change nothing if we are a simple copy if (obj) { Part::TopoShape shape = ShapeBinder::buildShapeFromReferences(obj, subs); //now, shape is in object's CS, and includes local Placement of obj but nothing else. if (TraceSupport.getValue()) { //compute the transform, and apply it to the shape. Base::Placement sourceCS = //full placement of container of obj obj->globalPlacement() * obj->Placement.getValue().inverse(); Base::Placement targetCS = //full placement of container of this shapebinder this->globalPlacement() * this->Placement.getValue().inverse(); Base::Placement transform = targetCS.inverse() * sourceCS; shape.setPlacement(transform * shape.getPlacement()); } this->Placement.setValue(shape.getTransform()); this->Shape.setValue(shape); } } return Part::Feature::execute(); }
void TaskPocketParameters::onButtonFace(const bool pressed) { PartDesign::Pocket* pcPocket = static_cast<PartDesign::Pocket*>(PocketView->getObject()); Part::Feature* support = pcPocket->getSupport(); if (support == NULL) { // There is no support, so we can't select from it... return; } if (pressed) { Gui::Document* doc = Gui::Application::Instance->activeDocument(); if (doc) { doc->setHide(PocketView->getObject()->getNameInDocument()); doc->setShow(support->getNameInDocument()); } Gui::Selection().clearSelection(); Gui::Selection().addSelectionGate (new ReferenceSelection(support, false, true, false)); } else { Gui::Selection().rmvSelectionGate(); Gui::Document* doc = Gui::Application::Instance->activeDocument(); if (doc) { doc->setShow(PocketView->getObject()->getNameInDocument()); doc->setHide(support->getNameInDocument()); } } // Update button if onButtonFace() is called explicitly ui->buttonFace->setChecked(pressed); }
bool TaskDlgPocketParameters::accept() { std::string name = PocketView->getObject()->getNameInDocument(); try { //Gui::Command::openCommand("Pocket changed"); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Length = %f",name.c_str(),parameter->getLength()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Type = %u",name.c_str(),parameter->getMode()); std::string facename = parameter->getFaceName().data(); PartDesign::Pocket* pcPocket = static_cast<PartDesign::Pocket*>(PocketView->getObject()); Part::Feature* support = pcPocket->getSupport(); if (support != NULL && !facename.empty()) { QString buf = QString::fromUtf8("(App.ActiveDocument.%1,[\"%2\"])"); buf = buf.arg(QString::fromUtf8(support->getNameInDocument())); buf = buf.arg(QString::fromStdString(facename)); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.UpToFace = %s", name.c_str(), buf.toStdString().c_str()); } else Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.UpToFace = None", name.c_str()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()"); if (!PocketView->getObject()->isValid()) throw Base::Exception(PocketView->getObject()->getStatusString()); Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); Gui::Command::commitCommand(); } catch (const Base::Exception& e) { QMessageBox::warning(parameter, tr("Input error"), QString::fromAscii(e.what())); return false; } return true; }
void TaskPadParameters::apply() { std::string name = PadView->getObject()->getNameInDocument(); const char * cname = name.c_str(); ui->lengthEdit->apply(); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Reversed = %i",cname,getReversed()?1:0); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Midplane = %i",cname,getMidplane()?1:0); ui->lengthEdit2->apply(); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Type = %u",cname,getMode()); std::string facename = getFaceName().data(); PartDesign::Pad* pcPad = static_cast<PartDesign::Pad*>(PadView->getObject()); Part::Feature* support = pcPad->getSupport(); if (support != NULL && !facename.empty()) { QString buf = QString::fromUtf8("(App.ActiveDocument.%1,[\"%2\"])"); buf = buf.arg(QString::fromUtf8(support->getNameInDocument())); buf = buf.arg(QString::fromStdString(facename)); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.UpToFace = %s", cname, buf.toStdString().c_str()); } else Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.UpToFace = None", cname); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()"); if (!PadView->getObject()->isValid()) throw Base::Exception(PadView->getObject()->getStatusString()); Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); Gui::Command::commitCommand(); }
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); }
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 TaskPocketParameters::onSelectionChanged(const Gui::SelectionChanges& msg) { if (msg.Type == Gui::SelectionChanges::AddSelection) { // Don't allow selection in other document if (strcmp(msg.pDocName, PocketView->getObject()->getDocument()->getName()) != 0) return; if (!msg.pSubName || msg.pSubName[0] == '\0') return; std::string subName(msg.pSubName); if (subName.substr(0,4) != "Face") return; int faceId = std::atoi(&subName[4]); // Don't allow selection outside of support PartDesign::Pocket* pcPocket = static_cast<PartDesign::Pocket*>(PocketView->getObject()); Part::Feature* support = pcPocket->getSupport(); if (support == NULL) { // There is no support, so we can't select from it... // Turn off reference selection mode onButtonFace(false); return; } if (strcmp(msg.pObjectName, support->getNameInDocument()) != 0) return; std::vector<std::string> upToFaces(1,subName); pcPocket->UpToFace.setValue(support, upToFaces); if (updateView()) pcPocket->getDocument()->recomputeFeature(pcPocket); ui->lineFaceName->blockSignals(true); ui->lineFaceName->setText(tr("Face") + QString::number(faceId)); ui->lineFaceName->setProperty("FaceName", QByteArray(subName.c_str())); ui->lineFaceName->blockSignals(false); // Turn off reference selection mode onButtonFace(false); } else if (msg.Type == Gui::SelectionChanges::ClrSelection) { ui->lineFaceName->blockSignals(true); ui->lineFaceName->setText(tr("No face selected")); ui->lineFaceName->setProperty("FaceName", QByteArray()); ui->lineFaceName->blockSignals(false); } }
void CmdFemAddPart::activated(int iMsg) { #ifndef FCWithNetgen QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), QObject::tr("Your FreeCAD is build without NETGEN support. Meshing will not work....")); return; #endif std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx(); if (selection.size() != 1) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), QObject::tr("Select an edge, face or body. Only one body is allowed.")); return; } if (!selection[0].isObjectTypeOf(Part::Feature::getClassTypeId())){ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong object type"), QObject::tr("Fillet works only on parts")); return; } Part::Feature *base = static_cast<Part::Feature*>(selection[0].getObject()); std::string AnalysisName = getUniqueObjectName("FemAnalysis"); std::string MeshName = getUniqueObjectName((std::string(base->getNameInDocument()) +"_Mesh").c_str()); openCommand("Create FEM analysis"); doCommand(Doc,"App.activeDocument().addObject('Fem::FemAnalysis','%s')",AnalysisName.c_str()); doCommand(Doc,"App.activeDocument().addObject('Fem::FemMeshShapeNetgenObject','%s')",MeshName.c_str()); doCommand(Doc,"App.activeDocument().ActiveObject.Shape = App.activeDocument().%s",base->getNameInDocument()); doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s",AnalysisName.c_str(),MeshName.c_str()); addModule(Gui,"FemGui"); doCommand(Gui,"FemGui.setActiveAnalysis(App.activeDocument().%s)",AnalysisName.c_str()); commitCommand(); updateActive(); }
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; }
// 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)); }
Part::Feature *ProfileBased::getBaseObject(bool silent) const { // Test the base's class feature. Part::Feature *rv = Feature::getBaseObject(/* silent = */ true); if (rv) { return rv; } // getVerifiedObject() may throw it's own exception if fail Part::Feature* obj = getVerifiedObject(silent); if(!obj) return nullptr; if (!obj->isDerivedFrom(Part::Part2DObject::getClassTypeId())) return obj; //due to former test we know we have a 2d object Part::Part2DObject* sketch = getVerifiedSketch(silent); const char* err = nullptr; App::DocumentObject* spt = sketch->Support.getValue(); if (spt) { if (spt->isDerivedFrom(Part::Feature::getClassTypeId())) { rv = static_cast<Part::Feature*>(spt); } else { err = "No base set, sketch support is not Part::Feature"; } } else { err = "No base set, no sketch support either"; } if (!silent && err) { throw Base::RuntimeError (err); } return rv; }
void ShapeBinder::slotChangedObject(const App::DocumentObject& Obj, const App::Property& Prop) { App::Document* doc = getDocument(); if (!doc || doc->testStatus(App::Document::Restoring)) return; if (this == &Obj) return; if (!TraceSupport.getValue()) return; if (!Prop.getTypeId().isDerivedFrom(App::PropertyPlacement::getClassTypeId())) return; Part::Feature* obj = nullptr; std::vector<std::string> subs; ShapeBinder::getFilteredReferences(&Support, obj, subs); if (obj) { if (obj == &Obj) { // the directly referenced object has changed enforceRecompute(); } else if (Obj.hasExtension(App::GroupExtension::getExtensionClassTypeId())) { // check if the changed property belongs to a group-like object // like Body or Part std::vector<App::DocumentObject*> chain; std::vector<App::DocumentObject*> list = getInListRecursive(); chain.insert(chain.end(), list.begin(), list.end()); list = obj->getInListRecursive(); chain.insert(chain.end(), list.begin(), list.end()); auto it = std::find(chain.begin(), chain.end(), &Obj); if (it != chain.end()) { enforceRecompute(); } } } }
void CmdPathShape::activated(int iMsg) { std::vector<Gui::SelectionSingleton::SelObj> Sel = getSelection().getSelection(); if (Sel.size() == 1) { if (Sel[0].pObject->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { Part::Feature *pcPartObject = dynamic_cast<Part::Feature*>(Sel[0].pObject); std::string FeatName = getUniqueObjectName("PathShape"); openCommand("Create Path Compound"); doCommand(Doc,"FreeCAD.activeDocument().addObject('Path::FeatureShape','%s')",FeatName.c_str()); doCommand(Doc,"FreeCAD.activeDocument().%s.Shape = FreeCAD.activeDocument().%s.Shape.copy()",FeatName.c_str(),pcPartObject->getNameInDocument()); commitCommand(); updateActive(); } else { Base::Console().Error("Exactly one shape object must be selected\n"); return; } } else { Base::Console().Error("Exactly one shape object must be selected\n"); return; } }
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; }
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 CmdSketcherMapSketch::activated(int iMsg) { App::Document* doc = App::GetApplication().getActiveDocument(); std::vector<App::DocumentObject*> sel = doc->getObjectsOfType(Sketcher::SketchObject::getClassTypeId()); if (sel.empty()) { QMessageBox::warning(Gui::getMainWindow(), qApp->translate(className(), "No sketch found"), qApp->translate(className(), "The document doesn't have a sketch")); return; } bool ok; QStringList items; for (std::vector<App::DocumentObject*>::iterator it = sel.begin(); it != sel.end(); ++it) items.push_back(QString::fromUtf8((*it)->Label.getValue())); QString text = QInputDialog::getItem(Gui::getMainWindow(), qApp->translate(className(), "Select sketch"), qApp->translate(className(), "Select a sketch from the list"), items, 0, false, &ok); if (!ok) return; int index = items.indexOf(text); std::string featName = sel[index]->getNameInDocument(); Gui::SelectionFilter FaceFilter ("SELECT Part::Feature SUBELEMENT Face COUNT 1"); if (FaceFilter.match()) { // get the selected object Part::Feature *part = static_cast<Part::Feature*>(FaceFilter.Result[0][0].getObject()); Base::Placement ObjectPos = part->Placement.getValue(); const std::vector<std::string> &sub = FaceFilter.Result[0][0].getSubNames(); if (sub.size() > 1){ // No assert for wrong user input! QMessageBox::warning(Gui::getMainWindow(), qApp->translate(className(),"Several sub-elements selected"), qApp->translate(className(),"You have to select a single face as support for a sketch!")); return; } std::vector<App::DocumentObject*> input = part->getOutList(); if (std::find(input.begin(), input.end(), sel[index]) != input.end()) { QMessageBox::warning(Gui::getMainWindow(), qApp->translate(className(),"Cyclic dependency"), qApp->translate(className(),"You cannot choose a support object depending on the selected sketch!")); return; } // get the selected sub shape (a Face) const Part::TopoShape &shape = part->Shape.getValue(); TopoDS_Shape sh = shape.getSubShape(sub[0].c_str()); const TopoDS_Face& face = TopoDS::Face(sh); if (face.IsNull()) { // No assert for wrong user input! QMessageBox::warning(Gui::getMainWindow(), qApp->translate(className(),"No support face selected"), qApp->translate(className(),"You have to select a face as support for a sketch!")); return; } BRepAdaptor_Surface adapt(face); if (adapt.GetType() != GeomAbs_Plane){ QMessageBox::warning(Gui::getMainWindow(), qApp->translate(className(),"No planar support"), qApp->translate(className(),"You need a planar face as support for a sketch!")); return; } std::string supportString = FaceFilter.Result[0][0].getAsPropertyLinkSubString(); openCommand("Map a Sketch on Face"); doCommand(Gui,"App.activeDocument().%s.Support = %s",featName.c_str(),supportString.c_str()); doCommand(Gui,"App.activeDocument().recompute()"); doCommand(Gui,"Gui.activeDocument().setEdit('%s')",featName.c_str()); } else { QMessageBox::warning(Gui::getMainWindow(), qApp->translate(className(), "No face selected"), qApp->translate(className(), "No face was selected to map the sketch to")); } }
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)); }
void CrossSections::apply() { std::vector<App::DocumentObject*> obj = Gui::Selection(). getObjectsOfType(Part::Feature::getClassTypeId()); std::vector<double> d; if (ui->sectionsBox->isChecked()) d = getPlanes(); else d.push_back(ui->position->value().getValue()); double a=0,b=0,c=0; switch (plane()) { case CrossSections::XY: c = 1.0; break; case CrossSections::XZ: b = 1.0; break; case CrossSections::YZ: a = 1.0; break; } #ifdef CS_FUTURE Standard::SetReentrant(Standard_True); for (std::vector<App::DocumentObject*>::iterator it = obj.begin(); it != obj.end(); ++it) { Part::CrossSection cs(a,b,c,static_cast<Part::Feature*>(*it)->Shape.getValue()); QFuture< std::list<TopoDS_Wire> > future = QtConcurrent::mapped (d, boost::bind(&Part::CrossSection::section, &cs, _1)); future.waitForFinished(); QFuture< std::list<TopoDS_Wire> >::const_iterator ft; TopoDS_Compound comp; BRep_Builder builder; builder.MakeCompound(comp); for (ft = future.begin(); ft != future.end(); ++ft) { const std::list<TopoDS_Wire>& w = *ft; for (std::list<TopoDS_Wire>::const_iterator wt = w.begin(); wt != w.end(); ++wt) { if (!wt->IsNull()) builder.Add(comp, *wt); } } App::Document* doc = (*it)->getDocument(); std::string s = (*it)->getNameInDocument(); s += "_cs"; Part::Feature* section = static_cast<Part::Feature*> (doc->addObject("Part::Feature",s.c_str())); section->Shape.setValue(comp); section->purgeTouched(); } #else Base::SequencerLauncher seq("Cross-sections...", obj.size() * (d.size() +1)); Gui::Command::runCommand(Gui::Command::App, "import Part\n"); Gui::Command::runCommand(Gui::Command::App, "from FreeCAD import Base\n"); for (std::vector<App::DocumentObject*>::iterator it = obj.begin(); it != obj.end(); ++it) { App::Document* doc = (*it)->getDocument(); std::string s = (*it)->getNameInDocument(); s += "_cs"; Gui::Command::runCommand(Gui::Command::App, QString::fromLatin1( "wires=list()\n" "shape=FreeCAD.getDocument(\"%1\").%2.Shape\n") .arg(QLatin1String(doc->getName())) .arg(QLatin1String((*it)->getNameInDocument())).toLatin1()); for (std::vector<double>::iterator jt = d.begin(); jt != d.end(); ++jt) { Gui::Command::runCommand(Gui::Command::App, QString::fromLatin1( "for i in shape.slice(Base.Vector(%1,%2,%3),%4):\n" " wires.append(i)\n" ).arg(a).arg(b).arg(c).arg(*jt).toLatin1()); seq.next(); } Gui::Command::runCommand(Gui::Command::App, QString::fromLatin1( "comp=Part.Compound(wires)\n" "slice=FreeCAD.getDocument(\"%1\").addObject(\"Part::Feature\",\"%2\")\n" "slice.Shape=comp\n" "slice.purgeTouched()\n" "del slice,comp,wires,shape") .arg(QLatin1String(doc->getName())) .arg(QLatin1String(s.c_str())).toLatin1()); seq.next(); } #endif }
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()); }
void CmdSketcherNewSketch::activated(int iMsg) { Attacher::eMapMode mapmode = Attacher::mmDeactivated; bool bAttach = false; if (Gui::Selection().hasSelection()){ Attacher::SuggestResult::eSuggestResult msgid = Attacher::SuggestResult::srOK; QString msg_str; std::vector<Attacher::eMapMode> validModes; mapmode = SuggestAutoMapMode(&msgid, &msg_str, &validModes); if (msgid == Attacher::SuggestResult::srOK) bAttach = true; if (msgid != Attacher::SuggestResult::srOK && msgid != Attacher::SuggestResult::srNoModesFit){ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Sketch mapping"), QObject::tr("Can't map the skecth to selected object. %1.").arg(msg_str)); return; } if (validModes.size() > 1){ validModes.insert(validModes.begin(), Attacher::mmDeactivated); bool ok; QStringList items; items.push_back(QObject::tr("Don't attach")); int iSugg = 0;//index of the auto-suggested mode in the list of valid modes for (size_t i = 0 ; i < validModes.size() ; ++i){ items.push_back(QString::fromLatin1(AttachEngine::getModeName(validModes[i]).c_str())); if (validModes[i] == mapmode) iSugg = items.size()-1; } QString text = QInputDialog::getItem(Gui::getMainWindow(), qApp->translate(className(), "Sketch attachment"), qApp->translate(className(), "Select the method to attach this sketch to selected object"), items, iSugg, false, &ok); if (!ok) return; int index = items.indexOf(text); if (index == 0){ bAttach = false; mapmode = Attacher::mmDeactivated; } else { bAttach = true; mapmode = validModes[index-1]; } } } if (bAttach) { std::vector<Gui::SelectionObject> objects = Gui::Selection().getSelectionEx(); //assert (objects.size() == 1); //should have been filtered out by SuggestAutoMapMode //Gui::SelectionObject &sel_support = objects[0]; App::PropertyLinkSubList support; Gui::Selection().getAsPropertyLinkSubList(support); std::string supportString = support.getPyReprString(); // create Sketch on Face std::string FeatName = getUniqueObjectName("Sketch"); openCommand("Create a Sketch on Face"); doCommand(Doc,"App.activeDocument().addObject('Sketcher::SketchObject','%s')",FeatName.c_str()); if (mapmode >= 0 && mapmode < Attacher::mmDummy_NumberOfModes) doCommand(Gui,"App.activeDocument().%s.MapMode = \"%s\"",FeatName.c_str(),AttachEngine::getModeName(mapmode).c_str()); else assert(0 /* mapmode index out of range */); doCommand(Gui,"App.activeDocument().%s.Support = %s",FeatName.c_str(),supportString.c_str()); doCommand(Gui,"App.activeDocument().recompute()"); // recompute the sketch placement based on its support doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); Part::Feature *part = static_cast<Part::Feature*>(support.getValue());//if multi-part support, this will return 0 if (part){ App::DocumentObjectGroup* grp = part->getGroup(); if (grp) { doCommand(Doc,"App.activeDocument().%s.addObject(App.activeDocument().%s)" ,grp->getNameInDocument(),FeatName.c_str()); } } } else { // ask user for orientation SketchOrientationDialog Dlg; if (Dlg.exec() != QDialog::Accepted) return; // canceled Base::Vector3d p = Dlg.Pos.getPosition(); Base::Rotation r = Dlg.Pos.getRotation(); // do the right view direction std::string camstring; switch(Dlg.DirType){ case 0: camstring = "#Inventor V2.1 ascii \\n OrthographicCamera {\\n viewportMapping ADJUST_CAMERA \\n position 0 0 87 \\n orientation 0 0 1 0 \\n nearDistance -112.88701 \\n farDistance 287.28702 \\n aspectRatio 1 \\n focalDistance 87 \\n height 143.52005 }"; break; case 1: camstring = "#Inventor V2.1 ascii \\n OrthographicCamera {\\n viewportMapping ADJUST_CAMERA \\n position 0 0 -87 \\n orientation -1 0 0 3.1415927 \\n nearDistance -112.88701 \\n farDistance 287.28702 \\n aspectRatio 1 \\n focalDistance 87 \\n height 143.52005 }"; break; case 2: camstring = "#Inventor V2.1 ascii \\n OrthographicCamera {\\n viewportMapping ADJUST_CAMERA\\n position 0 -87 0 \\n orientation -1 0 0 4.712389\\n nearDistance -112.88701\\n farDistance 287.28702\\n aspectRatio 1\\n focalDistance 87\\n height 143.52005\\n\\n}"; break; case 3: camstring = "#Inventor V2.1 ascii \\n OrthographicCamera {\\n viewportMapping ADJUST_CAMERA\\n position 0 87 0 \\n orientation 0 0.70710683 0.70710683 3.1415927\\n nearDistance -112.88701\\n farDistance 287.28702\\n aspectRatio 1\\n focalDistance 87\\n height 143.52005\\n\\n}"; break; case 4: camstring = "#Inventor V2.1 ascii \\n OrthographicCamera {\\n viewportMapping ADJUST_CAMERA\\n position 87 0 0 \\n orientation 0.57735026 0.57735026 0.57735026 2.0943952 \\n nearDistance -112.887\\n farDistance 287.28699\\n aspectRatio 1\\n focalDistance 87\\n height 143.52005\\n\\n}"; break; case 5: camstring = "#Inventor V2.1 ascii \\n OrthographicCamera {\\n viewportMapping ADJUST_CAMERA\\n position -87 0 0 \\n orientation -0.57735026 0.57735026 0.57735026 4.1887903 \\n nearDistance -112.887\\n farDistance 287.28699\\n aspectRatio 1\\n focalDistance 87\\n height 143.52005\\n\\n}"; break; } std::string FeatName = getUniqueObjectName("Sketch"); openCommand("Create a new Sketch"); doCommand(Doc,"App.activeDocument().addObject('Sketcher::SketchObject','%s')",FeatName.c_str()); doCommand(Doc,"App.activeDocument().%s.Placement = App.Placement(App.Vector(%f,%f,%f),App.Rotation(%f,%f,%f,%f))",FeatName.c_str(),p.x,p.y,p.z,r[0],r[1],r[2],r[3]); doCommand(Doc,"App.activeDocument().%s.MapMode = \"%s\"",FeatName.c_str(),AttachEngine::getModeName(Attacher::mmDeactivated).c_str()); doCommand(Gui,"Gui.activeDocument().activeView().setCamera('%s')",camstring.c_str()); doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); } }