//! calculate the section Normal/Projection Direction given baseView projection direction and section name Base::Vector3d DrawViewSection::getSectionVector (const std::string sectionName) { Base::Vector3d result; Base::Vector3d stdX(1.0,0.0,0.0); Base::Vector3d stdY(0.0,1.0,0.0); Base::Vector3d stdZ(0.0,0.0,1.0); double adjustAngle = 0.0; if (getBaseDPGI() != nullptr) { adjustAngle = getBaseDPGI()->getRotateAngle(); } Base::Vector3d view = getBaseDVP()->Direction.getValue(); view.Normalize(); Base::Vector3d left = view.Cross(stdZ); left.Normalize(); Base::Vector3d up = view.Cross(left); up.Normalize(); double dot = view.Dot(stdZ); if (sectionName == "Up") { result = up; if (DrawUtil::fpCompare(dot,1.0)) { //view = stdZ result = (-1.0 * stdY); } else if (DrawUtil::fpCompare(dot,-1.0)) { //view = -stdZ result = stdY; } } else if (sectionName == "Down") { result = up * -1.0; if (DrawUtil::fpCompare(dot,1.0)) { //view = stdZ result = stdY; } else if (DrawUtil::fpCompare(dot, -1.0)) { //view = -stdZ result = (-1.0 * stdY); } } else if (sectionName == "Left") { result = left * -1.0; if (DrawUtil::fpCompare(fabs(dot),1.0)) { //view = +/- stdZ result = stdX; } } else if (sectionName == "Right") { result = left; if (DrawUtil::fpCompare(fabs(dot),1.0)) { result = -1.0 * stdX; } } else { Base::Console().Log("Error - DVS::getSectionVector - bad sectionName: %s\n",sectionName.c_str()); result = stdZ; } Base::Vector3d adjResult = DrawUtil::vecRotate(result,adjustAngle,view); return adjResult; }
/// utility non-class member functions //! gets a coordinate system that matches view system used in 3D with +Z up (or +Y up if neccessary) //! used for individual views, but not secondary views in projection groups gp_Ax2 TechDrawGeometry::getViewAxis(const Base::Vector3d origin, const Base::Vector3d& direction, const bool flip) { gp_Pnt inputCenter(origin.x,origin.y,origin.z); Base::Vector3d stdZ(0.0,0.0,1.0); Base::Vector3d flipDirection(direction.x,-direction.y,direction.z); if (!flip) { flipDirection = Base::Vector3d(direction.x,direction.y,direction.z); } Base::Vector3d cross = flipDirection; //special cases if (flipDirection == stdZ) { cross = Base::Vector3d(1.0,0.0,0.0); } else if (flipDirection == (stdZ * -1.0)) { cross = Base::Vector3d(1.0,0.0,0.0); } else { cross.Normalize(); cross = cross.Cross(stdZ); } gp_Ax2 viewAxis; viewAxis = gp_Ax2(inputCenter, gp_Dir(flipDirection.x, flipDirection.y, flipDirection.z), // gp_Dir(1.0, 1.0, 0.0)); gp_Dir(cross.x, cross.y, cross.z)); return viewAxis; }
Base::Vector3d MeshObject::getPointNormal(unsigned long index) const { std::vector<Base::Vector3f> temp = _kernel.CalcVertexNormals(); Base::Vector3d normal = transformToOutside(temp[index]); // the normal is a vector, hence we must not apply the translation part // of the transformation to the vector normal.x -= _Mtrx[0][3]; normal.y -= _Mtrx[1][3]; normal.z -= _Mtrx[2][3]; normal.Normalize(); return normal; }
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(); }
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; }