Extrusion::ExtrusionParameters Extrusion::computeFinalParameters() { Extrusion::ExtrusionParameters result; Base::Vector3d dir; switch(this->DirMode.getValue()){ case dmCustom: dir = this->Dir.getValue(); break; case dmEdge:{ bool fetched; Base::Vector3d base; fetched = fetchAxisLink(this->DirLink, base, dir); if (! fetched) throw Base::Exception("DirMode is set to use edge, but no edge is linked."); this->Dir.setValue(dir); }break; case dmNormal: dir = calculateShapeNormal(this->Base); this->Dir.setValue(dir); break; default: throw Base::ValueError("Unexpected enum value"); } if(dir.Length() < Precision::Confusion()) throw Base::ValueError("Direction is zero-length"); result.dir = gp_Dir(dir.x, dir.y, dir.z); if (this->Reversed.getValue()) result.dir.Reverse(); result.lengthFwd = this->LengthFwd.getValue(); result.lengthRev = this->LengthRev.getValue(); if(fabs(result.lengthFwd) < Precision::Confusion() && fabs(result.lengthRev) < Precision::Confusion() ){ result.lengthFwd = dir.Length(); } if (this->Symmetric.getValue()){ result.lengthRev = result.lengthFwd * 0.5; result.lengthFwd = result.lengthFwd * 0.5; } if (fabs(result.lengthFwd + result.lengthRev) < Precision::Confusion()) throw Base::ValueError("Total length of extrusion is zero."); result.solid = this->Solid.getValue(); result.taperAngleFwd = this->TaperAngle.getValue() * M_PI / 180.0; if (fabs(result.taperAngleFwd) > M_PI * 0.5 - Precision::Angular() ) throw Base::ValueError("Magnitude of taper angle matches or exceeds 90 degrees. That is too much."); result.taperAngleRev = this->TaperAngleRev.getValue() * M_PI / 180.0; if (fabs(result.taperAngleRev) > M_PI * 0.5 - Precision::Angular() ) throw Base::ValueError("Magnitude of taper angle matches or exceeds 90 degrees. That is too much."); result.faceMakerClass = this->FaceMakerClass.getValue(); return result; }
void LocationWidget::setDirection(const Base::Vector3d& dir) { if (dir.Length() < Base::Vector3d::epsilon()) { return; } // check if the user-defined direction is already there for (int i=0; i<dValue->count()-1; i++) { QVariant data = dValue->itemData (i); if (data.canConvert<Base::Vector3d>()) { const Base::Vector3d val = data.value<Base::Vector3d>(); if (val == dir) { dValue->setCurrentIndex(i); return; } } } // add a new item before the very last item QString display = QString::fromLatin1("(%1,%2,%3)") .arg(dir.x) .arg(dir.y) .arg(dir.z); dValue->insertItem(dValue->count()-1, display, QVariant::fromValue<Base::Vector3d>(dir)); dValue->setCurrentIndex(dValue->count()-2); }
void LocationWidget::on_direction_activated(int index) { // last item is selected to define direction by user if (index+1 == dValue->count()) { bool ok; Base::Vector3d dir = this->getUserDirection(&ok); if (ok) { if (dir.Length() < Base::Vector3d::epsilon()) { QMessageBox::critical(this, LocationDialog::tr("Wrong direction"), LocationDialog::tr("Direction must not be the null vector")); return; } setDirection(dir); } } }
void ConstraintForce::onChanged(const App::Property* prop) { // Note: If we call this at the end, then the arrows are not oriented correctly initially // because the NormalDirection has not been calculated yet Constraint::onChanged(prop); if (prop == &References) { std::vector<Base::Vector3d> points; std::vector<Base::Vector3d> normals; if (getPoints(points, normals)) { Points.setValues(points); // We don't use the normals because all arrows should have the same direction } } else if (prop == &Direction) { Base::Vector3d direction = getDirection(Direction); if (direction.Length() < Precision::Confusion()) return; naturalDirectionVector = direction; if (Reversed.getValue()) direction = -direction; DirectionVector.setValue(direction); } else if (prop == &Reversed) { // if the direction is invalid try to compute it again if (naturalDirectionVector.Length() < Precision::Confusion()) { naturalDirectionVector = getDirection(Direction); } if (naturalDirectionVector.Length() >= Precision::Confusion()) { if (Reversed.getValue() && (DirectionVector.getValue() == naturalDirectionVector)) { DirectionVector.setValue(-naturalDirectionVector); } else if (!Reversed.getValue() && (DirectionVector.getValue() != naturalDirectionVector)) { DirectionVector.setValue(naturalDirectionVector); } } } else if (prop == &NormalDirection) { // Set a default direction if no direction reference has been given if (Direction.getValue() == NULL) { Base::Vector3d direction = NormalDirection.getValue(); if (Reversed.getValue()) direction = -direction; DirectionVector.setValue(direction); naturalDirectionVector = direction; } } }
void ConstraintGear::onChanged(const App::Property* prop) { ConstraintBearing::onChanged(prop); if (prop == &Direction) { Base::Vector3d direction = getDirection(Direction); if (direction.Length() < Precision::Confusion()) return; naturalDirectionVector = direction; if (Reversed.getValue()) direction = -direction; DirectionVector.setValue(direction); DirectionVector.touch(); } else if (prop == &Reversed) { if (Reversed.getValue() && (DirectionVector.getValue() == naturalDirectionVector)) { DirectionVector.setValue(-naturalDirectionVector); DirectionVector.touch(); } else if (!Reversed.getValue() && (DirectionVector.getValue() != naturalDirectionVector)) { DirectionVector.setValue(naturalDirectionVector); DirectionVector.touch(); } } // The computation for the force angle is simpler in the ViewProvider directly }
int DrawSketchHandler::seekAutoConstraint(std::vector<AutoConstraint> &suggestedConstraints, const Base::Vector2D& Pos, const Base::Vector2D& Dir, AutoConstraint::TargetType type) { suggestedConstraints.clear(); if (!sketchgui->Autoconstraints.getValue()) return 0; // If Autoconstraints property is not set quit Base::Vector3d hitShapeDir = Base::Vector3d(0,0,0); // direction of hit shape (if it is a line, the direction of the line) // Get Preselection int preSelPnt = sketchgui->getPreselectPoint(); int preSelCrv = sketchgui->getPreselectCurve(); int preSelCrs = sketchgui->getPreselectCross(); int GeoId = Constraint::GeoUndef; Sketcher::PointPos PosId = Sketcher::none; if (preSelPnt != -1) sketchgui->getSketchObject()->getGeoVertexIndex(preSelPnt, GeoId, PosId); else if (preSelCrv != -1){ GeoId = preSelCrv; const Part::Geometry *geom = sketchgui->getSketchObject()->getGeometry(GeoId); if(geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()){ const Part::GeomLineSegment *line = static_cast<const Part::GeomLineSegment *>(geom); hitShapeDir= line->getEndPoint()-line->getStartPoint(); } } else if (preSelCrs == 0) { // root point GeoId = -1; PosId = Sketcher::start; } else if (preSelCrs == 1){ // x axis GeoId = -1; hitShapeDir = Base::Vector3d(1,0,0); } else if (preSelCrs == 2){ // y axis GeoId = -2; hitShapeDir = Base::Vector3d(0,1,0); } if (GeoId != Constraint::GeoUndef) { // Currently only considers objects in current Sketcher AutoConstraint constr; constr.Type = Sketcher::None; constr.GeoId = GeoId; constr.PosId = PosId; if (type == AutoConstraint::VERTEX && PosId != Sketcher::none) constr.Type = Sketcher::Coincident; else if (type == AutoConstraint::CURVE && PosId != Sketcher::none) constr.Type = Sketcher::PointOnObject; else if (type == AutoConstraint::VERTEX && PosId == Sketcher::none) constr.Type = Sketcher::PointOnObject; else if (type == AutoConstraint::CURVE && PosId == Sketcher::none) constr.Type = Sketcher::Tangent; if(constr.Type == Sketcher::Tangent && Dir.Length() > 1e-8 && hitShapeDir.Length() > 1e-8) { // We are hitting a line and have hitting vector information Base::Vector3d dir3d = Base::Vector3d(Dir.fX,Dir.fY,0); double cosangle=dir3d.Normalize()*hitShapeDir.Normalize(); // the angle between the line and the hitting direction are over around 6 degrees (it is substantially parallel) // or if it is an sketch axis (that can not move to accomodate to the shape), then only if it is around 6 degrees with the normal (around 84 degrees) if (fabs(cosangle) < 0.995f || ((GeoId==-1 || GeoId==-2) && fabs(cosangle) < 0.1)) suggestedConstraints.push_back(constr); return suggestedConstraints.size(); } if (constr.Type != Sketcher::None) suggestedConstraints.push_back(constr); } if (Dir.Length() < 1e-8 || type == AutoConstraint::CURVE) // Direction not set so return; return suggestedConstraints.size(); // Suggest vertical and horizontal constraints // Number of Degree of deviation from horizontal or vertical lines const double angleDev = 2; const double angleDevRad = angleDev * M_PI / 180.; AutoConstraint constr; constr.Type = Sketcher::None; constr.GeoId = Constraint::GeoUndef; constr.PosId = Sketcher::none; double angle = std::abs(atan2(Dir.fY, Dir.fX)); if (angle < angleDevRad || (M_PI - angle) < angleDevRad ) // Suggest horizontal constraint constr.Type = Sketcher::Horizontal; else if (std::abs(angle - M_PI_2) < angleDevRad) // Suggest vertical constraint constr.Type = Sketcher::Vertical; if (constr.Type != Sketcher::None) suggestedConstraints.push_back(constr); // Find if there are tangent constraints (currently arcs and circles) int tangId = Constraint::GeoUndef; // Do not consider if distance is more than that. // Decrease this value when a candidate is found. double tangDeviation = 0.1 * sketchgui->getScaleFactor(); // Get geometry list const std::vector<Part::Geometry *> geomlist = sketchgui->getSketchObject()->getCompleteGeometry(); Base::Vector3d tmpPos(Pos.fX, Pos.fY, 0.f); // Current cursor point Base::Vector3d tmpDir(Dir.fX, Dir.fY, 0.f); // Direction of line Base::Vector3d tmpStart(Pos.fX-Dir.fX, Pos.fY-Dir.fY, 0.f); // Start point // Iterate through geometry int i = 0; for (std::vector<Part::Geometry *>::const_iterator it=geomlist.begin(); it != geomlist.end(); ++it, i++) { if ((*it)->getTypeId() == Part::GeomCircle::getClassTypeId()) { const Part::GeomCircle *circle = static_cast<const Part::GeomCircle *>((*it)); Base::Vector3d center = circle->getCenter(); double radius = circle->getRadius(); // ignore if no touch (use dot product) if(tmpDir * (center-tmpPos) > 0 || tmpDir * (center-tmpStart) < 0) continue; Base::Vector3d projPnt(0.f, 0.f, 0.f); projPnt = projPnt.ProjectToLine(center - tmpPos, tmpDir); double projDist = std::abs(projPnt.Length() - radius); // Find if nearest if (projDist < tangDeviation) { tangId = i; tangDeviation = projDist; } } else if ((*it)->getTypeId() == Part::GeomEllipse::getClassTypeId()) { const Part::GeomEllipse *ellipse = static_cast<const Part::GeomEllipse *>((*it)); Base::Vector3d center = ellipse->getCenter(); double a = ellipse->getMajorRadius(); double b = ellipse->getMinorRadius(); Base::Vector3d majdir = ellipse->getMajorAxisDir(); double cf = sqrt(a*a - b*b); Base::Vector3d focus1P = center + cf * majdir; Base::Vector3d focus2P = center - cf * majdir; Base::Vector3d norm = Base::Vector3d(Dir.fY,-Dir.fX).Normalize(); double distancetoline = norm*(tmpPos - focus1P); // distance focus1 to line Base::Vector3d focus1PMirrored = focus1P + 2*distancetoline*norm; // mirror of focus1 with respect to the line double error = fabs((focus1PMirrored-focus2P).Length() - 2*a); if ( error< tangDeviation) { tangId = i; tangDeviation = error; } } else if ((*it)->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { const Part::GeomArcOfCircle *arc = static_cast<const Part::GeomArcOfCircle *>((*it)); Base::Vector3d center = arc->getCenter(); double radius = arc->getRadius(); // ignore if no touch (use dot product) if(tmpDir * (center-tmpPos) > 0 || tmpDir * (center-tmpStart) < 0) continue; Base::Vector3d projPnt(0.f, 0.f, 0.f); projPnt = projPnt.ProjectToLine(center - tmpPos, tmpDir); double projDist = std::abs(projPnt.Length() - radius); if (projDist < tangDeviation) { double startAngle, endAngle; arc->getRange(startAngle, endAngle, /*emulateCCW=*/true); double angle = atan2(projPnt.y, projPnt.x); while(angle < startAngle) angle += 2*D_PI; // Bring it to range of arc // if the point is on correct side of arc if (angle <= endAngle) { // Now need to check only one side tangId = i; tangDeviation = projDist; } } } else if ((*it)->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) { const Part::GeomArcOfEllipse *aoe = static_cast<const Part::GeomArcOfEllipse *>((*it)); Base::Vector3d center = aoe->getCenter(); double a = aoe->getMajorRadius(); double b = aoe->getMinorRadius(); Base::Vector3d majdir = aoe->getMajorAxisDir(); double cf = sqrt(a*a - b*b); Base::Vector3d focus1P = center + cf * majdir; Base::Vector3d focus2P = center - cf * majdir; Base::Vector3d norm = Base::Vector3d(Dir.fY,-Dir.fX).Normalize(); double distancetoline = norm*(tmpPos - focus1P); // distance focus1 to line Base::Vector3d focus1PMirrored = focus1P + 2*distancetoline*norm; // mirror of focus1 with respect to the line double error = fabs((focus1PMirrored-focus2P).Length() - 2*a); if ( error< tangDeviation ) { tangId = i; tangDeviation = error; } if (error < tangDeviation) { double startAngle, endAngle; aoe->getRange(startAngle, endAngle, /*emulateCCW=*/true); double angle = Base::fmod( atan2(-aoe->getMajorRadius()*((tmpPos.x-center.x)*majdir.y-(tmpPos.y-center.y)*majdir.x), aoe->getMinorRadius()*((tmpPos.x-center.x)*majdir.x+(tmpPos.y-center.y)*majdir.y) )- startAngle, 2.f*M_PI); while(angle < startAngle) angle += 2*D_PI; // Bring it to range of arc // if the point is on correct side of arc if (angle <= endAngle) { // Now need to check only one side tangId = i; tangDeviation = error; } } } } if (tangId != Constraint::GeoUndef) { if (tangId > getHighestCurveIndex()) // external Geometry tangId = getHighestCurveIndex() - tangId; // Suggest vertical constraint constr.Type = Tangent; constr.GeoId = tangId; constr.PosId = Sketcher::none; suggestedConstraints.push_back(constr); } return suggestedConstraints.size(); }
void ViewProviderFemConstraintForce::updateData(const App::Property* prop) { // Gets called whenever a property of the attached object changes Fem::ConstraintForce* pcConstraint = static_cast<Fem::ConstraintForce*>(this->getObject()); /* // This has a HUGE performance penalty as opposed to separate nodes for every symbol // The problem seems to be SoCone if (pShapeSep->getNumChildren() == 0) { // Set up the nodes SoMultipleCopy* cp = new SoMultipleCopy(); cp->ref(); cp->matrix.setNum(0); cp->addChild((SoNode*)createArrow(ARROWLENGTH, ARROWHEADRADIUS)); pShapeSep->addChild(cp); } */ if (strcmp(prop->getName(),"Points") == 0) { // Redraw all arrows pShapeSep->removeAllChildren(); // This should always point outside of the solid Base::Vector3d normal = pcConstraint->NormalDirection.getValue(); // Get default direction (on first call to method) Base::Vector3d forceDirection = pcConstraint->DirectionVector.getValue(); if (forceDirection.Length() < Precision::Confusion()) forceDirection = normal; SbVec3f dir(forceDirection.x, forceDirection.y, forceDirection.z); SbRotation rot(SbVec3f(0,1,0), dir); const std::vector<Base::Vector3d>& points = pcConstraint->Points.getValues(); /* SoMultipleCopy* cp = static_cast<SoMultipleCopy*>(pShapeSep->getChild(0)); cp->matrix.setNum(points.size()); int idx = 0;*/ for (std::vector<Base::Vector3d>::const_iterator p = points.begin(); p != points.end(); p++) { SbVec3f base(p->x, p->y, p->z); if (forceDirection.GetAngle(normal) < M_PI_2) // Move arrow so it doesn't disappear inside the solid base = base + dir * ARROWLENGTH; /* SbMatrix m; m.setTransform(base, rot, SbVec3f(1,1,1)); cp->matrix.set1Value(idx, m); idx++; */ SoSeparator* sep = new SoSeparator(); createPlacement(sep, base, rot); createArrow(sep, ARROWLENGTH, ARROWHEADRADIUS); pShapeSep->addChild(sep); } } else if (strcmp(prop->getName(),"DirectionVector") == 0) { // Note: "Reversed" also triggers "DirectionVector" // Re-orient all arrows Base::Vector3d normal = pcConstraint->NormalDirection.getValue(); Base::Vector3d forceDirection = pcConstraint->DirectionVector.getValue(); if (forceDirection.Length() < Precision::Confusion()) forceDirection = normal; SbVec3f dir(forceDirection.x, forceDirection.y, forceDirection.z); SbRotation rot(SbVec3f(0,1,0), dir); const std::vector<Base::Vector3d>& points = pcConstraint->Points.getValues(); /* SoMultipleCopy* cp = static_cast<SoMultipleCopy*>(pShapeSep->getChild(0)); cp->matrix.setNum(points.size()); */ int idx = 0; for (std::vector<Base::Vector3d>::const_iterator p = points.begin(); p != points.end(); p++) { SbVec3f base(p->x, p->y, p->z); if (forceDirection.GetAngle(normal) < M_PI_2) base = base + dir * ARROWLENGTH; /* SbMatrix m; m.setTransform(base, rot, SbVec3f(1,1,1)); cp->matrix.set1Value(idx, m);*/ SoSeparator* sep = static_cast<SoSeparator*>(pShapeSep->getChild(idx)); updatePlacement(sep, 0, base, rot); updateArrow(sep, 2, ARROWLENGTH, ARROWHEADRADIUS); idx++; } } ViewProviderFemConstraint::updateData(prop); }
void ViewProviderFemConstraintFluidBoundary::updateData(const App::Property* prop) { // Gets called whenever a property of the attached object changes Fem::ConstraintFluidBoundary* pcConstraint = static_cast<Fem::ConstraintFluidBoundary*>(this->getObject()); float scaledwidth = WIDTH * pcConstraint->Scale.getValue(); //OvG: Calculate scaled values once only float scaledheight = HEIGHT * pcConstraint->Scale.getValue(); float scaledheadradius = ARROWHEADRADIUS * pcConstraint->Scale.getValue(); //OvG: Calculate scaled values once only float scaledlength = ARROWLENGTH * pcConstraint->Scale.getValue(); std::string boundaryType = pcConstraint->BoundaryType.getValueAsString(); if (strcmp(prop->getName(),"BoundaryType") == 0) { if (boundaryType == "wall") { FaceColor.setValue(0.0,1.0,1.0); } else if (boundaryType == "interface") { FaceColor.setValue(0.0,1.0,0.0); } else if (boundaryType == "freestream") { FaceColor.setValue(1.0,1.0,0.0); } else if(boundaryType == "inlet") { FaceColor.setValue(1.0,0.0,0.0); } else //(boundaryType == "outlet") { FaceColor.setValue(0.0,0.0,1.0); } } if (boundaryType == "inlet" || boundaryType == "outlet"){ #ifdef USE_MULTIPLE_COPY //OvG: need access to cp for scaling SoMultipleCopy* cp = new SoMultipleCopy(); if (pShapeSep->getNumChildren() == 0) { // Set up the nodes cp->matrix.setNum(0); cp->addChild((SoNode*)createArrow(scaledlength , scaledheadradius)); //OvG: Scaling pShapeSep->addChild(cp); } #endif if (strcmp(prop->getName(),"Points") == 0) { const std::vector<Base::Vector3d>& points = pcConstraint->Points.getValues(); #ifdef USE_MULTIPLE_COPY cp = static_cast<SoMultipleCopy*>(pShapeSep->getChild(0)); cp->matrix.setNum(points.size()); SbMatrix* matrices = cp->matrix.startEditing(); int idx = 0; #else // Redraw all arrows pShapeSep->removeAllChildren(); #endif // This should always point outside of the solid Base::Vector3d normal = pcConstraint->NormalDirection.getValue(); // Get default direction (on first call to method) Base::Vector3d forceDirection = pcConstraint->DirectionVector.getValue(); if (forceDirection.Length() < Precision::Confusion()) forceDirection = normal; SbVec3f dir(forceDirection.x, forceDirection.y, forceDirection.z); SbRotation rot(SbVec3f(0,1,0), dir); for (std::vector<Base::Vector3d>::const_iterator p = points.begin(); p != points.end(); p++) { SbVec3f base(p->x, p->y, p->z); if (forceDirection.GetAngle(normal) < M_PI_2) // Move arrow so it doesn't disappear inside the solid base = base + dir * scaledlength; //OvG: Scaling #ifdef USE_MULTIPLE_COPY SbMatrix m; m.setTransform(base, rot, SbVec3f(1,1,1)); matrices[idx] = m; idx++; #else SoSeparator* sep = new SoSeparator(); createPlacement(sep, base, rot); createArrow(sep, scaledlength, scaledheadradius); //OvG: Scaling pShapeSep->addChild(sep); #endif } #ifdef USE_MULTIPLE_COPY cp->matrix.finishEditing(); #endif } else if (strcmp(prop->getName(),"DirectionVector") == 0) { // Note: "Reversed" also triggers "DirectionVector" // Re-orient all arrows Base::Vector3d normal = pcConstraint->NormalDirection.getValue(); Base::Vector3d forceDirection = pcConstraint->DirectionVector.getValue(); if (forceDirection.Length() < Precision::Confusion()) forceDirection = normal; SbVec3f dir(forceDirection.x, forceDirection.y, forceDirection.z); SbRotation rot(SbVec3f(0,1,0), dir); const std::vector<Base::Vector3d>& points = pcConstraint->Points.getValues(); #ifdef USE_MULTIPLE_COPY SoMultipleCopy* cp = static_cast<SoMultipleCopy*>(pShapeSep->getChild(0)); cp->matrix.setNum(points.size()); SbMatrix* matrices = cp->matrix.startEditing(); #endif int idx = 0; for (std::vector<Base::Vector3d>::const_iterator p = points.begin(); p != points.end(); p++) { SbVec3f base(p->x, p->y, p->z); if (forceDirection.GetAngle(normal) < M_PI_2) base = base + dir * scaledlength; //OvG: Scaling #ifdef USE_MULTIPLE_COPY SbMatrix m; m.setTransform(base, rot, SbVec3f(1,1,1)); matrices[idx] = m; #else SoSeparator* sep = static_cast<SoSeparator*>(pShapeSep->getChild(idx)); updatePlacement(sep, 0, base, rot); updateArrow(sep, 2, scaledlength, scaledheadradius); //OvG: Scaling #endif idx++; } #ifdef USE_MULTIPLE_COPY cp->matrix.finishEditing(); #endif } } else{// not inlet or outlet boundary type #ifdef USE_MULTIPLE_COPY //OvG: always need access to cp for scaling SoMultipleCopy* cp = new SoMultipleCopy(); if (pShapeSep->getNumChildren() == 0) { // Set up the nodes cp->matrix.setNum(0); cp->addChild((SoNode*)createFixed(scaledheight, scaledwidth)); //OvG: Scaling pShapeSep->addChild(cp); } #endif if (strcmp(prop->getName(),"Points") == 0) { const std::vector<Base::Vector3d>& points = pcConstraint->Points.getValues(); const std::vector<Base::Vector3d>& normals = pcConstraint->Normals.getValues(); if (points.size() != normals.size()) return; std::vector<Base::Vector3d>::const_iterator n = normals.begin(); #ifdef USE_MULTIPLE_COPY cp = static_cast<SoMultipleCopy*>(pShapeSep->getChild(0)); cp->matrix.setNum(points.size()); SbMatrix* matrices = cp->matrix.startEditing(); int idx = 0; #else // Note: Points and Normals are always updated together pShapeSep->removeAllChildren(); #endif for (std::vector<Base::Vector3d>::const_iterator p = points.begin(); p != points.end(); p++) { SbVec3f base(p->x, p->y, p->z); SbVec3f dir(n->x, n->y, n->z); SbRotation rot(SbVec3f(0,-1,0), dir); #ifdef USE_MULTIPLE_COPY SbMatrix m; m.setTransform(base, rot, SbVec3f(1,1,1)); matrices[idx] = m; idx++; #else SoSeparator* sep = new SoSeparator(); createPlacement(sep, base, rot); createFixed(sep, scaledheight, scaledwidth); //OvG: Scaling pShapeSep->addChild(sep); #endif n++; } #ifdef USE_MULTIPLE_COPY cp->matrix.finishEditing(); #endif } } ViewProviderFemConstraint::updateData(prop); }
Py::Object makeFilletArc(const Py::Tuple& args) { PyObject *pM1; PyObject *pP; PyObject *pQ; PyObject *pN; double r2; int ccw; if (!PyArg_ParseTuple(args.ptr(), "O!O!O!O!di", &(Base::VectorPy::Type), &pM1, &(Base::VectorPy::Type), &pP, &(Base::VectorPy::Type), &pQ, &(Base::VectorPy::Type), &pN, &r2, &ccw)) throw Py::Exception(); Base::Vector3d M1 = Py::Vector(pM1, false).toVector(); Base::Vector3d P = Py::Vector(pP, false).toVector(); Base::Vector3d Q = Py::Vector(pQ, false).toVector(); Base::Vector3d N = Py::Vector(pN, false).toVector(); Base::Vector3d u = Q - P; Base::Vector3d v = P - M1; Base::Vector3d b; if (ccw) b = u % N; else b = N % u; b.Normalize(); double uu = u * u; double uv = u * v; double r1 = v.Length(); // distinguish between internal and external fillets r2 *= Base::sgn(uv); double cc = 2.0 * r2 * (b * v - r1); double d = uv * uv - uu * cc; if (d < 0) { throw Py::RuntimeError("Unable to calculate intersection points"); } double t; double t1 = (-uv + sqrt(d)) / uu; double t2 = (-uv - sqrt(d)) / uu; if (fabs(t1) < fabs(t2)) t = t1; else t = t2; Base::Vector3d M2 = P + (u*t) + (b*r2); Base::Vector3d S1 = (r2 * M1 + r1 * M2)/(r1+r2); Base::Vector3d S2 = M2 - (b*r2); Py::Tuple tuple(3); tuple.setItem(0, Py::Vector(S1)); tuple.setItem(1, Py::Vector(S2)); tuple.setItem(2, Py::Vector(M2)); return tuple; }
// Methods for distances (edge length, two points, edge and a point double Measurement::length() const { int numRefs = References3D.getSize(); if(!numRefs || measureType == Invalid) { throw Base::Exception("Measurement - length - Invalid References3D Provided"); } double result = 0.0; const std::vector<App::DocumentObject*> &objects = References3D.getValues(); const std::vector<std::string> &subElements = References3D.getSubValues(); if(measureType == Points || measureType == PointToEdge || measureType == PointToSurface) { Base::Vector3d diff = this->delta(); //return diff.Length(); result = diff.Length(); } else if(measureType == Edges) { double length = 0.f; // Iterate through edges and calculate each length std::vector<App::DocumentObject*>::const_iterator obj = objects.begin(); std::vector<std::string>::const_iterator subEl = subElements.begin(); for (;obj != objects.end(); ++obj, ++subEl) { //const Part::Feature *refObj = static_cast<const Part::Feature*>((*obj)); //const Part::TopoShape& refShape = refObj->Shape.getShape(); // Get the length of one edge TopoDS_Shape shape = getShape(*obj, (*subEl).c_str()); const TopoDS_Edge& edge = TopoDS::Edge(shape); BRepAdaptor_Curve curve(edge); switch(curve.GetType()) { case GeomAbs_Line : { gp_Pnt P1 = curve.Value(curve.FirstParameter()); gp_Pnt P2 = curve.Value(curve.LastParameter()); gp_XYZ diff = P2.XYZ() - P1.XYZ(); length += diff.Modulus(); } break; case GeomAbs_Circle : { double u = curve.FirstParameter(); double v = curve.LastParameter(); double radius = curve.Circle().Radius(); if (u > v) // if arc is reversed std::swap(u, v); double range = v-u; length += radius * range; } break; case GeomAbs_Ellipse: case GeomAbs_BSplineCurve: case GeomAbs_Hyperbola: case GeomAbs_BezierCurve: { length += GCPnts_AbscissaPoint::Length(curve); } break; default: { throw Base::Exception("Measurement - length - Curve type not currently handled"); } } } result = length; //return length; } return result; }