Sketcher: Chamfer tool (and fillet refactor)
This commit is contained in:
committed by
WandererFan
parent
9d43e7fda7
commit
b3fe5bba28
@@ -548,7 +548,7 @@
|
||||
<FCText Name="Sketcher_CreatePeriodicBSpline">G, B, P</FCText>
|
||||
<FCText Name="Sketcher_CreatePeriodicBSplineByInterpolation">G, B, O</FCText>
|
||||
<FCText Name="Sketcher_CreatePoint">G, Y</FCText>
|
||||
<FCText Name="Sketcher_CreatePointFillet">G, F, P</FCText>
|
||||
<FCText Name="Sketcher_CreateChamfer">G, F, C</FCText>
|
||||
<FCText Name="Sketcher_CreatePolyline">G, M</FCText>
|
||||
<FCText Name="Sketcher_CreateRectangle">G, R</FCText>
|
||||
<FCText Name="Sketcher_CreateRectangle_Center">G, V</FCText>
|
||||
|
||||
@@ -2065,7 +2065,7 @@ int SketchObject::transferConstraints(int fromGeoId, PointPos fromPosId, int toG
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SketchObject::fillet(int GeoId, PointPos PosId, double radius, bool trim, bool createCorner)
|
||||
int SketchObject::fillet(int GeoId, PointPos PosId, double radius, bool trim, bool createCorner, bool chamfer)
|
||||
{
|
||||
if (GeoId < 0 || GeoId > getHighestCurveIndex())
|
||||
return -1;
|
||||
@@ -2081,12 +2081,12 @@ int SketchObject::fillet(int GeoId, PointPos PosId, double radius, bool trim, bo
|
||||
const Part::Geometry* geo2 = getGeometry(GeoIdList[1]);
|
||||
if (geo1->is<Part::GeomLineSegment>()
|
||||
&& geo2->is<Part::GeomLineSegment>()) {
|
||||
const Part::GeomLineSegment* lineSeg1 = static_cast<const Part::GeomLineSegment*>(geo1);
|
||||
const Part::GeomLineSegment* lineSeg2 = static_cast<const Part::GeomLineSegment*>(geo2);
|
||||
auto* lineSeg1 = static_cast<const Part::GeomLineSegment*>(geo1);
|
||||
auto* lineSeg2 = static_cast<const Part::GeomLineSegment*>(geo2);
|
||||
|
||||
Base::Vector3d midPnt1 = (lineSeg1->getStartPoint() + lineSeg1->getEndPoint()) / 2;
|
||||
Base::Vector3d midPnt2 = (lineSeg2->getStartPoint() + lineSeg2->getEndPoint()) / 2;
|
||||
return fillet(GeoIdList[0], GeoIdList[1], midPnt1, midPnt2, radius, trim, createCorner);
|
||||
return fillet(GeoIdList[0], GeoIdList[1], midPnt1, midPnt2, radius, trim, createCorner, chamfer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2094,11 +2094,11 @@ int SketchObject::fillet(int GeoId, PointPos PosId, double radius, bool trim, bo
|
||||
}
|
||||
|
||||
int SketchObject::fillet(int GeoId1, int GeoId2, const Base::Vector3d& refPnt1,
|
||||
const Base::Vector3d& refPnt2, double radius, bool trim, bool createCorner)
|
||||
const Base::Vector3d& refPnt2, double radius, bool trim, bool createCorner, bool chamfer)
|
||||
{
|
||||
if (GeoId1 < 0 || GeoId1 > getHighestCurveIndex() || GeoId2 < 0
|
||||
|| GeoId2 > getHighestCurveIndex())
|
||||
if (GeoId1 < 0 || GeoId1 > getHighestCurveIndex() || GeoId2 < 0 || GeoId2 > getHighestCurveIndex()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// If either of the two input lines are locked, don't try to trim since it won't work anyway
|
||||
const Part::Geometry* geo1 = getGeometry(GeoId1);
|
||||
@@ -2107,14 +2107,19 @@ int SketchObject::fillet(int GeoId1, int GeoId2, const Base::Vector3d& refPnt1,
|
||||
trim = false;
|
||||
}
|
||||
|
||||
if (geo1->is<Part::GeomLineSegment>()
|
||||
&& geo2->is<Part::GeomLineSegment>()) {
|
||||
const Part::GeomLineSegment* lineSeg1 = static_cast<const Part::GeomLineSegment*>(geo1);
|
||||
const Part::GeomLineSegment* lineSeg2 = static_cast<const Part::GeomLineSegment*>(geo2);
|
||||
Base::Vector3d p1, p2;
|
||||
PointPos PosId1 = PointPos::none;
|
||||
PointPos PosId2 = PointPos::none;
|
||||
int filletId;
|
||||
|
||||
if (geo1->is<Part::GeomLineSegment>() && geo2->is<Part::GeomLineSegment>()) {
|
||||
auto* lineSeg1 = static_cast<const Part::GeomLineSegment*>(geo1);
|
||||
auto* lineSeg2 = static_cast<const Part::GeomLineSegment*>(geo2);
|
||||
|
||||
Base::Vector3d filletCenter;
|
||||
if (!Part::findFilletCenter(lineSeg1, lineSeg2, radius, refPnt1, refPnt2, filletCenter))
|
||||
if (!Part::findFilletCenter(lineSeg1, lineSeg2, radius, refPnt1, refPnt2, filletCenter)) {
|
||||
return -1;
|
||||
}
|
||||
Base::Vector3d dir1 = lineSeg1->getEndPoint() - lineSeg1->getStartPoint();
|
||||
Base::Vector3d dir2 = lineSeg2->getEndPoint() - lineSeg2->getStartPoint();
|
||||
|
||||
@@ -2123,27 +2128,27 @@ int SketchObject::fillet(int GeoId1, int GeoId2, const Base::Vector3d& refPnt1,
|
||||
Base::Vector3d intersection, dist1, dist2;
|
||||
|
||||
// create arc from known parameters and lines
|
||||
int filletId;
|
||||
std::unique_ptr<Part::GeomArcOfCircle> arc(
|
||||
Part::createFilletGeometry(lineSeg1, lineSeg2, filletCenter, radius));
|
||||
if (!arc)
|
||||
if (!arc) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// calculate intersection and distances before we invalidate lineSeg1 and lineSeg2
|
||||
if (!find2DLinesIntersection(lineSeg1, lineSeg2, intersection)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
p1 = arc->getStartPoint();
|
||||
p2 = arc->getEndPoint();
|
||||
|
||||
dist1.ProjectToLine(arc->getStartPoint(/*emulateCCW=*/true) - intersection, dir1);
|
||||
dist2.ProjectToLine(arc->getStartPoint(/*emulateCCW=*/true) - intersection, dir2);
|
||||
Part::Geometry* newgeo = arc.get();
|
||||
filletId = addGeometry(newgeo);
|
||||
filletId = addGeometry(arc.get());
|
||||
|
||||
if (trim) {
|
||||
PointPos PosId1 =
|
||||
(filletCenter - intersection) * dir1 > 0 ? PointPos::start : PointPos::end;
|
||||
PointPos PosId2 =
|
||||
(filletCenter - intersection) * dir2 > 0 ? PointPos::start : PointPos::end;
|
||||
PosId1 = (filletCenter - intersection) * dir1 > 0 ? PointPos::start : PointPos::end;
|
||||
PosId2 = (filletCenter - intersection) * dir2 > 0 ? PointPos::start : PointPos::end;
|
||||
|
||||
if (createCorner) {
|
||||
transferFilletConstraints(GeoId1, PosId1, GeoId2, PosId2);
|
||||
@@ -2182,16 +2187,8 @@ int SketchObject::fillet(int GeoId1, int GeoId2, const Base::Vector3d& refPnt1,
|
||||
addConstraint(std::move(tangent1));
|
||||
addConstraint(std::move(tangent2));
|
||||
}
|
||||
|
||||
// if we do not have a recompute after the geometry creation, the sketch must be solved to
|
||||
// update the DoF of the solver
|
||||
if (noRecomputes)
|
||||
solve();
|
||||
|
||||
return 0;
|
||||
}
|
||||
else if (geo1->isDerivedFrom<Part::GeomBoundedCurve>()
|
||||
&& geo2->isDerivedFrom<Part::GeomBoundedCurve>()) {
|
||||
else if (geo1->isDerivedFrom<Part::GeomBoundedCurve>() && geo2->isDerivedFrom<Part::GeomBoundedCurve>()) {
|
||||
|
||||
auto distancetorefpoints =
|
||||
[](Base::Vector3d ip1, Base::Vector3d ip2, Base::Vector3d ref1, Base::Vector3d ref2) {
|
||||
@@ -2284,40 +2281,35 @@ int SketchObject::fillet(int GeoId1, int GeoId2, const Base::Vector3d& refPnt1,
|
||||
|
||||
// look for coincident constraints between curves, take the coincident closest to the
|
||||
// refpoints
|
||||
Sketcher::PointPos curve1PosId = Sketcher::PointPos::none;
|
||||
Sketcher::PointPos curve2PosId = Sketcher::PointPos::none;
|
||||
|
||||
double dist = INFINITY;
|
||||
|
||||
const std::vector<Constraint*>& constraints = this->Constraints.getValues();
|
||||
|
||||
for (std::vector<Constraint*>::const_iterator it = constraints.begin();
|
||||
it != constraints.end();
|
||||
++it) {
|
||||
if ((*it)->Type == Sketcher::Coincident || (*it)->Type == Sketcher::Perpendicular
|
||||
|| (*it)->Type == Sketcher::Tangent) {
|
||||
if ((*it)->First == GeoId1 && (*it)->Second == GeoId2
|
||||
&& (*it)->FirstPos != Sketcher::PointPos::none
|
||||
&& (*it)->SecondPos != Sketcher::PointPos::none) {
|
||||
Base::Vector3d tmpp1 = getPoint((*it)->First, (*it)->FirstPos);
|
||||
Base::Vector3d tmpp2 = getPoint((*it)->Second, (*it)->SecondPos);
|
||||
for (auto& constr : constraints) {
|
||||
if (constr->Type == Sketcher::Coincident || constr->Type == Sketcher::Perpendicular
|
||||
|| constr->Type == Sketcher::Tangent) {
|
||||
if (constr->First == GeoId1 && constr->Second == GeoId2
|
||||
&& constr->FirstPos != PointPos::none
|
||||
&& constr->SecondPos != PointPos::none) {
|
||||
Base::Vector3d tmpp1 = getPoint(constr->First, constr->FirstPos);
|
||||
Base::Vector3d tmpp2 = getPoint(constr->Second, constr->SecondPos);
|
||||
double tmpdist = distancetorefpoints(tmpp1, tmpp2, refPnt1, refPnt2);
|
||||
if (tmpdist < dist) {
|
||||
curve1PosId = (*it)->FirstPos;
|
||||
curve2PosId = (*it)->SecondPos;
|
||||
PosId1 = constr->FirstPos;
|
||||
PosId2 = constr->SecondPos;
|
||||
dist = tmpdist;
|
||||
interpoints = std::make_pair(tmpp1, tmpp2);
|
||||
}
|
||||
}
|
||||
else if ((*it)->First == GeoId2 && (*it)->Second == GeoId1
|
||||
&& (*it)->FirstPos != Sketcher::PointPos::none
|
||||
&& (*it)->SecondPos != Sketcher::PointPos::none) {
|
||||
Base::Vector3d tmpp2 = getPoint((*it)->First, (*it)->FirstPos);
|
||||
Base::Vector3d tmpp1 = getPoint((*it)->Second, (*it)->SecondPos);
|
||||
else if (constr->First == GeoId2 && constr->Second == GeoId1
|
||||
&& constr->FirstPos != PointPos::none
|
||||
&& constr->SecondPos != PointPos::none) {
|
||||
Base::Vector3d tmpp2 = getPoint(constr->First, constr->FirstPos);
|
||||
Base::Vector3d tmpp1 = getPoint(constr->Second, constr->SecondPos);
|
||||
double tmpdist = distancetorefpoints(tmpp1, tmpp2, refPnt1, refPnt2);
|
||||
if (tmpdist < dist) {
|
||||
curve2PosId = (*it)->FirstPos;
|
||||
curve1PosId = (*it)->SecondPos;
|
||||
PosId2 = constr->FirstPos;
|
||||
PosId1 = constr->SecondPos;
|
||||
dist = tmpdist;
|
||||
interpoints = std::make_pair(tmpp1, tmpp2);
|
||||
}
|
||||
@@ -2325,15 +2317,13 @@ int SketchObject::fillet(int GeoId1, int GeoId2, const Base::Vector3d& refPnt1,
|
||||
}
|
||||
}
|
||||
|
||||
if (curve1PosId == Sketcher::PointPos::none) {
|
||||
if (PosId1 == PointPos::none) {
|
||||
// no coincident was found, try basis curve intersection if GeomTrimmedCurve
|
||||
if (geo1->isDerivedFrom(Part::GeomTrimmedCurve::getClassTypeId())
|
||||
&& geo2->isDerivedFrom(Part::GeomTrimmedCurve::getClassTypeId())) {
|
||||
if (geo1->isDerivedFrom<Part::GeomTrimmedCurve>()
|
||||
&& geo2->isDerivedFrom<Part::GeomTrimmedCurve>()) {
|
||||
|
||||
const Part::GeomTrimmedCurve* tcurve1 =
|
||||
static_cast<const Part::GeomTrimmedCurve*>(geo1);
|
||||
const Part::GeomTrimmedCurve* tcurve2 =
|
||||
static_cast<const Part::GeomTrimmedCurve*>(geo2);
|
||||
auto* tcurve1 =static_cast<const Part::GeomTrimmedCurve*>(geo1);
|
||||
auto* tcurve2 = static_cast<const Part::GeomTrimmedCurve*>(geo2);
|
||||
|
||||
try {
|
||||
if (!tcurve1->intersectBasisCurves(tcurve2, points))
|
||||
@@ -2350,11 +2340,13 @@ int SketchObject::fillet(int GeoId1, int GeoId2, const Base::Vector3d& refPnt1,
|
||||
|
||||
int res = selectintersection(points, interpoints, refPnt1, refPnt2);
|
||||
|
||||
if (res != 0)
|
||||
if (res != 0) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else
|
||||
else {
|
||||
return -1;// not a GeomTrimmedCurve and no coincident point.
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we know where the curves intersect, get the parameters in the curves of those
|
||||
@@ -2363,8 +2355,9 @@ int SketchObject::fillet(int GeoId1, int GeoId2, const Base::Vector3d& refPnt1,
|
||||
double intparam2;
|
||||
|
||||
try {
|
||||
if (!curve1->closestParameter(interpoints.first, intparam1))
|
||||
if (!curve1->closestParameter(interpoints.first, intparam1)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
catch (Base::CADKernelError& e) {
|
||||
e.ReportException();
|
||||
@@ -2374,8 +2367,9 @@ int SketchObject::fillet(int GeoId1, int GeoId2, const Base::Vector3d& refPnt1,
|
||||
}
|
||||
|
||||
try {
|
||||
if (!curve2->closestParameter(interpoints.second, intparam2))
|
||||
if (!curve2->closestParameter(interpoints.second, intparam2)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
catch (Base::CADKernelError& e) {
|
||||
e.ReportException();
|
||||
@@ -2439,8 +2433,7 @@ int SketchObject::fillet(int GeoId1, int GeoId2, const Base::Vector3d& refPnt1,
|
||||
/ det,
|
||||
0);
|
||||
|
||||
radius =
|
||||
((refp1 - normalintersect).Length() + (refp2 - normalintersect).Length()) / 2;
|
||||
radius = ((refp1 - normalintersect).Length() + (refp2 - normalintersect).Length()) / 2;
|
||||
}
|
||||
catch (const Base::Exception&) {
|
||||
radius = ref21.Length();// fall-back to simplest estimation.
|
||||
@@ -2543,8 +2536,9 @@ int SketchObject::fillet(int GeoId1, int GeoId2, const Base::Vector3d& refPnt1,
|
||||
|
||||
int res = selectintersection(offsetintersectionpoints, filletcenterpoint, refPnt1, refPnt2);
|
||||
|
||||
if (res != 0)
|
||||
if (res != 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
Base::Console().Log(
|
||||
@@ -2555,8 +2549,9 @@ int SketchObject::fillet(int GeoId1, int GeoId2, const Base::Vector3d& refPnt1,
|
||||
double refoparam2;
|
||||
|
||||
try {
|
||||
if (!curve1->closestParameter(filletcenterpoint.first, refoparam1))
|
||||
if (!curve1->closestParameter(filletcenterpoint.first, refoparam1)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
catch (Base::CADKernelError& e) {
|
||||
e.ReportException();
|
||||
@@ -2564,8 +2559,9 @@ int SketchObject::fillet(int GeoId1, int GeoId2, const Base::Vector3d& refPnt1,
|
||||
}
|
||||
|
||||
try {
|
||||
if (!curve2->closestParameter(filletcenterpoint.second, refoparam2))
|
||||
if (!curve2->closestParameter(filletcenterpoint.second, refoparam2)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
catch (Base::CADKernelError& e) {
|
||||
e.ReportException();
|
||||
@@ -2599,25 +2595,29 @@ int SketchObject::fillet(int GeoId1, int GeoId2, const Base::Vector3d& refPnt1,
|
||||
|
||||
endAngle = startAngle + range;
|
||||
|
||||
if (endAngle < startAngle)
|
||||
if (endAngle < startAngle) {
|
||||
std::swap(startAngle, endAngle);
|
||||
}
|
||||
|
||||
if (endAngle > 2 * M_PI)
|
||||
if (endAngle > 2 * M_PI) {
|
||||
endAngle -= 2 * M_PI;
|
||||
}
|
||||
|
||||
if (startAngle < 0)
|
||||
if (startAngle < 0) {
|
||||
endAngle += 2 * M_PI;
|
||||
}
|
||||
|
||||
// Create Arc Segment
|
||||
Part::GeomArcOfCircle* arc = new Part::GeomArcOfCircle();
|
||||
auto* arc = new Part::GeomArcOfCircle();
|
||||
arc->setRadius(radDir1.Length());
|
||||
arc->setCenter(filletcenterpoint.first);
|
||||
arc->setRange(startAngle, endAngle, /*emulateCCWXY=*/true);
|
||||
|
||||
p1 = arc->getStartPoint();
|
||||
p2 = arc->getEndPoint();
|
||||
|
||||
// add arc to sketch geometry
|
||||
int filletId;
|
||||
Part::Geometry* newgeo = arc;
|
||||
filletId = addGeometry(newgeo);
|
||||
filletId = addGeometry(arc);
|
||||
if (filletId < 0) {
|
||||
delete arc;
|
||||
return -1;
|
||||
@@ -2639,27 +2639,27 @@ int SketchObject::fillet(int GeoId1, int GeoId2, const Base::Vector3d& refPnt1,
|
||||
// b) we used the basis curve intersection
|
||||
|
||||
|
||||
if (curve1PosId == Sketcher::PointPos::none) {
|
||||
curve1PosId = selectend(intparam1, refoparam1, spc1);
|
||||
curve2PosId = selectend(intparam2, refoparam2, spc2);
|
||||
if (PosId1 == Sketcher::PointPos::none) {
|
||||
PosId1 = selectend(intparam1, refoparam1, spc1);
|
||||
PosId2 = selectend(intparam2, refoparam2, spc2);
|
||||
}
|
||||
|
||||
|
||||
delConstraintOnPoint(GeoId1, curve1PosId, false);
|
||||
delConstraintOnPoint(GeoId2, curve2PosId, false);
|
||||
delConstraintOnPoint(GeoId1, PosId1, false);
|
||||
delConstraintOnPoint(GeoId2, PosId2, false);
|
||||
|
||||
|
||||
Sketcher::Constraint* tangent1 = new Sketcher::Constraint();
|
||||
Sketcher::Constraint* tangent2 = new Sketcher::Constraint();
|
||||
auto* tangent1 = new Sketcher::Constraint();
|
||||
auto* tangent2 = new Sketcher::Constraint();
|
||||
|
||||
tangent1->Type = Sketcher::Tangent;
|
||||
tangent1->First = GeoId1;
|
||||
tangent1->FirstPos = curve1PosId;
|
||||
tangent1->FirstPos = PosId1;
|
||||
tangent1->Second = filletId;
|
||||
|
||||
tangent2->Type = Sketcher::Tangent;
|
||||
tangent2->First = GeoId2;
|
||||
tangent2->FirstPos = curve2PosId;
|
||||
tangent2->FirstPos = PosId2;
|
||||
tangent2->Second = filletId;
|
||||
|
||||
double dist1 = (refp1 - arc->getStartPoint(true)).Length();
|
||||
@@ -2670,14 +2670,14 @@ int SketchObject::fillet(int GeoId1, int GeoId2, const Base::Vector3d& refPnt1,
|
||||
if (dist1 < dist2) {
|
||||
tangent1->SecondPos = PointPos::start;
|
||||
tangent2->SecondPos = PointPos::end;
|
||||
movePoint(GeoId1, curve1PosId, arc->getStartPoint(true), false, true);
|
||||
movePoint(GeoId2, curve2PosId, arc->getEndPoint(true), false, true);
|
||||
movePoint(GeoId1, PosId1, arc->getStartPoint(true), false, true);
|
||||
movePoint(GeoId2, PosId2, arc->getEndPoint(true), false, true);
|
||||
}
|
||||
else {
|
||||
tangent1->SecondPos = PointPos::end;
|
||||
tangent2->SecondPos = PointPos::start;
|
||||
movePoint(GeoId1, curve1PosId, arc->getEndPoint(true), false, true);
|
||||
movePoint(GeoId2, curve2PosId, arc->getStartPoint(true), false, true);
|
||||
movePoint(GeoId1, PosId1, arc->getEndPoint(true), false, true);
|
||||
movePoint(GeoId2, PosId2, arc->getStartPoint(true), false, true);
|
||||
}
|
||||
|
||||
addConstraint(tangent1);
|
||||
@@ -2692,15 +2692,53 @@ int SketchObject::fillet(int GeoId1, int GeoId2, const Base::Vector3d& refPnt1,
|
||||
#ifdef DEBUG
|
||||
Base::Console().Log("\n\nEND OF FILLET DEBUG\n\n");
|
||||
#endif
|
||||
|
||||
// if we do not have a recompute after the geometry creation, the sketch must be solved to
|
||||
// update the DoF of the solver
|
||||
if (noRecomputes)
|
||||
solve();
|
||||
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (chamfer) {
|
||||
auto line = std::make_unique<Part::GeomLineSegment>();
|
||||
line->setPoints(p1, p2);
|
||||
int lineGeoId = addGeometry(line.get());
|
||||
|
||||
auto coinc1 = std::make_unique<Sketcher::Constraint>();
|
||||
auto coinc2 = std::make_unique<Sketcher::Constraint>();
|
||||
|
||||
coinc1->Type = Sketcher::Coincident;
|
||||
coinc1->First = lineGeoId;
|
||||
coinc1->FirstPos = PointPos::start;
|
||||
|
||||
coinc2->Type = Sketcher::Coincident;
|
||||
coinc2->First = lineGeoId;
|
||||
coinc2->FirstPos = PointPos::end;
|
||||
|
||||
if (trim) {
|
||||
coinc1->Second = GeoId1;
|
||||
coinc1->SecondPos = PosId1;
|
||||
coinc2->Second = GeoId2;
|
||||
coinc2->SecondPos = PosId2;
|
||||
}
|
||||
else {
|
||||
coinc1->Second = filletId;
|
||||
coinc1->SecondPos = PointPos::start;
|
||||
coinc2->Second = filletId;
|
||||
coinc2->SecondPos = PointPos::end;
|
||||
}
|
||||
|
||||
addConstraint(std::move(coinc1));
|
||||
addConstraint(std::move(coinc2));
|
||||
|
||||
setConstruction(filletId, true);
|
||||
}
|
||||
|
||||
// if we do not have a recompute after the geometry creation, the sketch must be solved to
|
||||
// update the DoF of the solver
|
||||
if (noRecomputes) {
|
||||
solve();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SketchObject::extend(int GeoId, double increment, PointPos endpoint)
|
||||
|
||||
@@ -323,8 +323,12 @@ public:
|
||||
\param createCorner - keep geoId/pos as a Point and keep as many constraints as possible
|
||||
\retval - 0 on success, -1 on failure
|
||||
*/
|
||||
int
|
||||
fillet(int geoId, PointPos pos, double radius, bool trim = true, bool preserveCorner = false);
|
||||
int fillet(int geoId,
|
||||
PointPos pos,
|
||||
double radius,
|
||||
bool trim = true,
|
||||
bool preserveCorner = false,
|
||||
bool chamfer = false);
|
||||
/*!
|
||||
\brief More general form of fillet
|
||||
\param geoId1, geoId2 - geoId for two lines (which don't necessarily have to coincide)
|
||||
@@ -340,7 +344,8 @@ public:
|
||||
const Base::Vector3d& refPnt2,
|
||||
double radius,
|
||||
bool trim = true,
|
||||
bool createCorner = false);
|
||||
bool createCorner = false,
|
||||
bool chamfer = false);
|
||||
|
||||
/// trim a curve
|
||||
int trim(int geoId, const Base::Vector3d& point);
|
||||
|
||||
@@ -1196,11 +1196,12 @@ PyObject* SketchObjectPy::fillet(PyObject* args)
|
||||
int geoId1, geoId2, posId1;
|
||||
int trim = true;
|
||||
PyObject* createCorner = Py_False;
|
||||
PyObject* chamfer = Py_False;
|
||||
double radius;
|
||||
|
||||
// Two Lines, radius
|
||||
if (PyArg_ParseTuple(args,
|
||||
"iiO!O!d|iO!",
|
||||
"iiO!O!d|iO!O!",
|
||||
&geoId1,
|
||||
&geoId2,
|
||||
&(Base::VectorPy::Type),
|
||||
@@ -1210,15 +1211,23 @@ PyObject* SketchObjectPy::fillet(PyObject* args)
|
||||
&radius,
|
||||
&trim,
|
||||
&PyBool_Type,
|
||||
&createCorner)) {
|
||||
&createCorner,
|
||||
&PyBool_Type,
|
||||
&chamfer)) {
|
||||
// The i for &trim should probably have been a bool like &createCorner, but we'll leave it
|
||||
// an int for backward compatibility (and because python will accept a bool there anyway)
|
||||
|
||||
Base::Vector3d v1 = static_cast<Base::VectorPy*>(pcObj1)->value();
|
||||
Base::Vector3d v2 = static_cast<Base::VectorPy*>(pcObj2)->value();
|
||||
|
||||
if (this->getSketchObjectPtr()
|
||||
->fillet(geoId1, geoId2, v1, v2, radius, trim, Base::asBoolean(createCorner))) {
|
||||
if (this->getSketchObjectPtr()->fillet(geoId1,
|
||||
geoId2,
|
||||
v1,
|
||||
v2,
|
||||
radius,
|
||||
trim,
|
||||
Base::asBoolean(createCorner),
|
||||
Base::asBoolean(chamfer))) {
|
||||
std::stringstream str;
|
||||
str << "Not able to fillet curves with ids : (" << geoId1 << ", " << geoId2
|
||||
<< ") and points (" << v1.x << ", " << v1.y << ", " << v1.z << ") & "
|
||||
@@ -1232,18 +1241,21 @@ PyObject* SketchObjectPy::fillet(PyObject* args)
|
||||
PyErr_Clear();
|
||||
// Point, radius
|
||||
if (PyArg_ParseTuple(args,
|
||||
"iid|iO!",
|
||||
"iid|iO!O!",
|
||||
&geoId1,
|
||||
&posId1,
|
||||
&radius,
|
||||
&trim,
|
||||
&PyBool_Type,
|
||||
&createCorner)) {
|
||||
&createCorner,
|
||||
&PyBool_Type,
|
||||
&chamfer)) {
|
||||
if (this->getSketchObjectPtr()->fillet(geoId1,
|
||||
static_cast<Sketcher::PointPos>(posId1),
|
||||
radius,
|
||||
trim,
|
||||
Base::asBoolean(createCorner))) {
|
||||
Base::asBoolean(createCorner),
|
||||
Base::asBoolean(chamfer))) {
|
||||
std::stringstream str;
|
||||
str << "Not able to fillet point with ( geoId: " << geoId1 << ", PointPos: " << posId1
|
||||
<< " )";
|
||||
|
||||
@@ -1431,8 +1431,9 @@ CmdSketcherCreateFillet::CmdSketcherCreateFillet()
|
||||
void CmdSketcherCreateFillet::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
ActivateHandler(getActiveGuiDocument(),
|
||||
new DrawSketchHandlerFillet(DrawSketchHandlerFillet::SimpleFillet));
|
||||
ActivateHandler(
|
||||
getActiveGuiDocument(),
|
||||
new DrawSketchHandlerFillet(ConstructionMethods::FilletConstructionMethod::Fillet));
|
||||
}
|
||||
|
||||
bool CmdSketcherCreateFillet::isActive()
|
||||
@@ -1442,149 +1443,62 @@ bool CmdSketcherCreateFillet::isActive()
|
||||
|
||||
// ======================================================================================
|
||||
|
||||
DEF_STD_CMD_A(CmdSketcherCreatePointFillet)
|
||||
DEF_STD_CMD_A(CmdSketcherCreateChamfer)
|
||||
|
||||
CmdSketcherCreatePointFillet::CmdSketcherCreatePointFillet()
|
||||
: Command("Sketcher_CreatePointFillet")
|
||||
CmdSketcherCreateChamfer::CmdSketcherCreateChamfer()
|
||||
: Command("Sketcher_CreateChamfer")
|
||||
{
|
||||
sAppModule = "Sketcher";
|
||||
sGroup = "Sketcher";
|
||||
sMenuText = QT_TR_NOOP("Create corner-preserving fillet");
|
||||
sToolTipText = QT_TR_NOOP("Fillet that preserves intersection point and most constraints");
|
||||
sWhatsThis = "Sketcher_CreatePointFillet";
|
||||
sMenuText = QT_TR_NOOP("Create chamfer");
|
||||
sToolTipText = QT_TR_NOOP("Create a chamfer between two lines or at a coincident point");
|
||||
sWhatsThis = "Sketcher_CreateChamfer";
|
||||
sStatusTip = sToolTipText;
|
||||
sPixmap = "Sketcher_CreatePointFillet";
|
||||
sAccel = "G, F, P";
|
||||
sPixmap = "Sketcher_CreateChamfer";
|
||||
sAccel = "G, F, C";
|
||||
eType = ForEdit;
|
||||
}
|
||||
|
||||
void CmdSketcherCreatePointFillet::activated(int iMsg)
|
||||
void CmdSketcherCreateChamfer::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
ActivateHandler(
|
||||
getActiveGuiDocument(),
|
||||
new DrawSketchHandlerFillet(DrawSketchHandlerFillet::ConstraintPreservingFillet));
|
||||
new DrawSketchHandlerFillet(ConstructionMethods::FilletConstructionMethod::Chamfer));
|
||||
}
|
||||
|
||||
bool CmdSketcherCreatePointFillet::isActive()
|
||||
bool CmdSketcherCreateChamfer::isActive()
|
||||
{
|
||||
return isCommandActive(getActiveGuiDocument());
|
||||
}
|
||||
|
||||
/// @brief Macro that declares a new sketcher command class 'CmdSketcherCompCreateFillets'
|
||||
DEF_STD_CMD_ACLU(CmdSketcherCompCreateFillets)
|
||||
|
||||
/**
|
||||
* @brief ctor
|
||||
*/
|
||||
CmdSketcherCompCreateFillets::CmdSketcherCompCreateFillets()
|
||||
: Command("Sketcher_CompCreateFillets")
|
||||
class CmdSketcherCompCreateFillets: public Gui::GroupCommand
|
||||
{
|
||||
sAppModule = "Sketcher";
|
||||
sGroup = "Sketcher";
|
||||
sMenuText = QT_TR_NOOP("Create fillet");
|
||||
sToolTipText = QT_TR_NOOP("Create a fillet between two lines");
|
||||
sWhatsThis = "Sketcher_CompCreateFillets";
|
||||
sStatusTip = sToolTipText;
|
||||
eType = ForEdit;
|
||||
}
|
||||
public:
|
||||
CmdSketcherCompCreateFillets()
|
||||
: GroupCommand("Sketcher_CompCreateFillets")
|
||||
{
|
||||
sAppModule = "Sketcher";
|
||||
sGroup = "Sketcher";
|
||||
sMenuText = QT_TR_NOOP("Create fillet or chamfer");
|
||||
sToolTipText = QT_TR_NOOP("Create a fillet or chamfer between two lines");
|
||||
sWhatsThis = "Sketcher_CompCreateFillets";
|
||||
sStatusTip = sToolTipText;
|
||||
eType = ForEdit;
|
||||
|
||||
/**
|
||||
* @brief Instantiates the fillet handler when the fillet command activated
|
||||
* @param int iMsg
|
||||
*/
|
||||
void CmdSketcherCompCreateFillets::activated(int iMsg)
|
||||
{
|
||||
if (iMsg == 0) {
|
||||
ActivateHandler(getActiveGuiDocument(),
|
||||
new DrawSketchHandlerFillet(DrawSketchHandlerFillet::SimpleFillet));
|
||||
}
|
||||
else if (iMsg == 1) {
|
||||
ActivateHandler(
|
||||
getActiveGuiDocument(),
|
||||
new DrawSketchHandlerFillet(DrawSketchHandlerFillet::ConstraintPreservingFillet));
|
||||
}
|
||||
else {
|
||||
return;
|
||||
setCheckable(false);
|
||||
|
||||
addCommand("Sketcher_CreateFillet");
|
||||
addCommand("Sketcher_CreateChamfer");
|
||||
}
|
||||
|
||||
// Since the default icon is reset when enabling/disabling the command we have
|
||||
// to explicitly set the icon of the used command.
|
||||
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
|
||||
QList<QAction*> a = pcAction->actions();
|
||||
|
||||
assert(iMsg < a.size());
|
||||
pcAction->setIcon(a[iMsg]->icon());
|
||||
}
|
||||
|
||||
Gui::Action* CmdSketcherCompCreateFillets::createAction()
|
||||
{
|
||||
Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow());
|
||||
pcAction->setDropDownMenu(true);
|
||||
applyCommandData(this->className(), pcAction);
|
||||
|
||||
QAction* oldFillet = pcAction->addAction(QString());
|
||||
oldFillet->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreateFillet"));
|
||||
|
||||
QAction* pointFillet = pcAction->addAction(QString());
|
||||
pointFillet->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreatePointFillet"));
|
||||
|
||||
_pcAction = pcAction;
|
||||
languageChange();
|
||||
|
||||
pcAction->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreatePointFillet"));
|
||||
int defaultId = 1;
|
||||
pcAction->setProperty("defaultAction", QVariant(defaultId));
|
||||
|
||||
return pcAction;
|
||||
}
|
||||
|
||||
void CmdSketcherCompCreateFillets::updateAction(int mode)
|
||||
{
|
||||
Q_UNUSED(mode);
|
||||
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(getAction());
|
||||
if (!pcAction) {
|
||||
return;
|
||||
const char* className() const override
|
||||
{
|
||||
return "CmdSketcherCompCreateFillets";
|
||||
}
|
||||
};
|
||||
|
||||
QList<QAction*> a = pcAction->actions();
|
||||
int index = pcAction->property("defaultAction").toInt();
|
||||
a[0]->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreateFillet"));
|
||||
a[1]->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_CreatePointFillet"));
|
||||
getAction()->setIcon(a[index]->icon());
|
||||
}
|
||||
|
||||
void CmdSketcherCompCreateFillets::languageChange()
|
||||
{
|
||||
Command::languageChange();
|
||||
|
||||
if (!_pcAction) {
|
||||
return;
|
||||
}
|
||||
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
|
||||
QList<QAction*> a = pcAction->actions();
|
||||
|
||||
QAction* oldFillet = a[0];
|
||||
oldFillet->setText(QApplication::translate("CmdSketcherCompCreateFillets", "Sketch fillet"));
|
||||
oldFillet->setToolTip(
|
||||
QApplication::translate("Sketcher_CreateFillet", "Creates a radius between two lines"));
|
||||
oldFillet->setStatusTip(
|
||||
QApplication::translate("Sketcher_CreateFillet", "Creates a radius between two lines"));
|
||||
QAction* pointFillet = a[1];
|
||||
pointFillet->setText(
|
||||
QApplication::translate("CmdSketcherCompCreateFillets", "Corner-preserving sketch fillet"));
|
||||
pointFillet->setToolTip(
|
||||
QApplication::translate("Sketcher_CreatePointFillet",
|
||||
"Fillet that preserves constraints and intersection point"));
|
||||
pointFillet->setStatusTip(
|
||||
QApplication::translate("Sketcher_CreatePointFillet",
|
||||
"Fillet that preserves constraints and intersection point"));
|
||||
}
|
||||
|
||||
bool CmdSketcherCompCreateFillets::isActive()
|
||||
{
|
||||
return isCommandActive(getActiveGuiDocument());
|
||||
}
|
||||
|
||||
// ======================================================================================
|
||||
|
||||
@@ -2323,9 +2237,9 @@ void CreateSketcherCommandsCreateGeo()
|
||||
rcCmdMgr.addCommand(new CmdSketcherCreateSlot());
|
||||
rcCmdMgr.addCommand(new CmdSketcherCreateArcSlot());
|
||||
rcCmdMgr.addCommand(new CmdSketcherCompSlot());
|
||||
rcCmdMgr.addCommand(new CmdSketcherCompCreateFillets());
|
||||
rcCmdMgr.addCommand(new CmdSketcherCreateFillet());
|
||||
rcCmdMgr.addCommand(new CmdSketcherCreatePointFillet());
|
||||
rcCmdMgr.addCommand(new CmdSketcherCreateChamfer());
|
||||
rcCmdMgr.addCommand(new CmdSketcherCompCreateFillets());
|
||||
// rcCmdMgr.addCommand(new CmdSketcherCreateText());
|
||||
// rcCmdMgr.addCommand(new CmdSketcherCreateDraftLine());
|
||||
rcCmdMgr.addCommand(new CmdSketcherTrimming());
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#include "Utils.h"
|
||||
#include "ViewProviderSketch.h"
|
||||
|
||||
using namespace Sketcher;
|
||||
|
||||
namespace SketcherGui
|
||||
{
|
||||
|
||||
@@ -86,80 +88,106 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class DrawSketchHandlerFillet: public DrawSketchHandler
|
||||
{
|
||||
public:
|
||||
enum FilletType
|
||||
{
|
||||
SimpleFillet,
|
||||
ConstraintPreservingFillet
|
||||
};
|
||||
class DrawSketchHandlerFillet;
|
||||
|
||||
explicit DrawSketchHandlerFillet(FilletType filletType)
|
||||
: filletType(filletType)
|
||||
, Mode(STATUS_SEEK_First)
|
||||
, firstCurve(0)
|
||||
namespace ConstructionMethods
|
||||
{
|
||||
|
||||
enum class FilletConstructionMethod
|
||||
{
|
||||
Fillet,
|
||||
Chamfer,
|
||||
End // Must be the last one
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using DSHFilletController =
|
||||
DrawSketchDefaultWidgetController<DrawSketchHandlerFillet,
|
||||
StateMachines::TwoSeekEnd,
|
||||
/*PAutoConstraintSize =*/0,
|
||||
/*OnViewParametersT =*/OnViewParameters<0, 0>, // NOLINT
|
||||
/*WidgetParametersT =*/WidgetParameters<0, 0>, // NOLINT
|
||||
/*WidgetCheckboxesT =*/WidgetCheckboxes<1, 1>, // NOLINT
|
||||
/*WidgetComboboxesT =*/WidgetComboboxes<1, 1>, // NOLINT
|
||||
ConstructionMethods::FilletConstructionMethod,
|
||||
/*bool PFirstComboboxIsConstructionMethod =*/true>;
|
||||
|
||||
using DSHFilletControllerBase = DSHFilletController::ControllerBase;
|
||||
|
||||
using DrawSketchHandlerFilletBase = DrawSketchControllableHandler<DSHFilletController>;
|
||||
|
||||
class DrawSketchHandlerFillet: public DrawSketchHandlerFilletBase
|
||||
{
|
||||
friend DSHFilletController;
|
||||
friend DSHFilletControllerBase;
|
||||
|
||||
public:
|
||||
explicit DrawSketchHandlerFillet(ConstructionMethod constrMethod = ConstructionMethod::Fillet)
|
||||
: DrawSketchHandlerFilletBase(constrMethod)
|
||||
, preserveCorner(true)
|
||||
, vtId(-1)
|
||||
, geoId1(GeoEnum::GeoUndef)
|
||||
, geoId2(GeoEnum::GeoUndef)
|
||||
{}
|
||||
~DrawSketchHandlerFillet() override
|
||||
{
|
||||
Gui::Selection().rmvSelectionGate();
|
||||
}
|
||||
|
||||
enum SelectMode
|
||||
private:
|
||||
void updateDataAndDrawToPosition(Base::Vector2d onSketchPos) override
|
||||
{
|
||||
STATUS_SEEK_First,
|
||||
STATUS_SEEK_Second
|
||||
};
|
||||
|
||||
void mouseMove(Base::Vector2d onSketchPos) override
|
||||
{
|
||||
Q_UNUSED(onSketchPos);
|
||||
switch (state()) {
|
||||
case SelectMode::SeekFirst: {
|
||||
vtId = getPreselectPoint();
|
||||
geoId1 = getPreselectCurve();
|
||||
firstPos = onSketchPos;
|
||||
} break;
|
||||
case SelectMode::SeekSecond: {
|
||||
geoId2 = getPreselectCurve();
|
||||
secondPos = onSketchPos;
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool pressButton(Base::Vector2d onSketchPos) override
|
||||
void executeCommands() override
|
||||
{
|
||||
Q_UNUSED(onSketchPos);
|
||||
return true;
|
||||
}
|
||||
SketchObject* obj = sketchgui->getSketchObject();
|
||||
|
||||
bool releaseButton(Base::Vector2d onSketchPos) override
|
||||
{
|
||||
bool construction = false;
|
||||
int VtId = getPreselectPoint();
|
||||
if (Mode == STATUS_SEEK_First && VtId != -1) {
|
||||
bool isChamfer = constructionMethod() == ConstructionMethod::Chamfer;
|
||||
|
||||
if (vtId != -1) {
|
||||
int GeoId;
|
||||
Sketcher::PointPos PosId = Sketcher::PointPos::none;
|
||||
sketchgui->getSketchObject()->getGeoVertexIndex(VtId, GeoId, PosId);
|
||||
const Part::Geometry* geom = sketchgui->getSketchObject()->getGeometry(GeoId);
|
||||
if (geom->is<Part::GeomLineSegment>()
|
||||
&& (PosId == Sketcher::PointPos::start || PosId == Sketcher::PointPos::end)) {
|
||||
PointPos PosId = PointPos::none;
|
||||
obj->getGeoVertexIndex(vtId, GeoId, PosId);
|
||||
const Part::Geometry* geom = obj->getGeometry(GeoId);
|
||||
if (isLineSegment(*geom) && (PosId == PointPos::start || PosId == PointPos::end)) {
|
||||
|
||||
// guess fillet radius
|
||||
double radius = -1;
|
||||
std::vector<int> GeoIdList;
|
||||
std::vector<Sketcher::PointPos> PosIdList;
|
||||
sketchgui->getSketchObject()->getDirectlyCoincidentPoints(GeoId,
|
||||
PosId,
|
||||
GeoIdList,
|
||||
PosIdList);
|
||||
obj->getDirectlyCoincidentPoints(GeoId, PosId, GeoIdList, PosIdList);
|
||||
if (GeoIdList.size() == 2 && GeoIdList[0] >= 0 && GeoIdList[1] >= 0) {
|
||||
const Part::Geometry* geom1 =
|
||||
sketchgui->getSketchObject()->getGeometry(GeoIdList[0]);
|
||||
const Part::Geometry* geom2 =
|
||||
sketchgui->getSketchObject()->getGeometry(GeoIdList[1]);
|
||||
construction = Sketcher::GeometryFacade::getConstruction(geom1)
|
||||
&& Sketcher::GeometryFacade::getConstruction(geom2);
|
||||
if (geom1->is<Part::GeomLineSegment>() && geom2->is<Part::GeomLineSegment>()) {
|
||||
const Part::GeomLineSegment* lineSeg1 =
|
||||
static_cast<const Part::GeomLineSegment*>(geom1);
|
||||
const Part::GeomLineSegment* lineSeg2 =
|
||||
static_cast<const Part::GeomLineSegment*>(geom2);
|
||||
Base::Vector3d dir1 = lineSeg1->getEndPoint() - lineSeg1->getStartPoint();
|
||||
Base::Vector3d dir2 = lineSeg2->getEndPoint() - lineSeg2->getStartPoint();
|
||||
if (PosIdList[0] == Sketcher::PointPos::end) {
|
||||
const Part::Geometry* geo1 = obj->getGeometry(GeoIdList[0]);
|
||||
const Part::Geometry* geo2 = obj->getGeometry(GeoIdList[1]);
|
||||
|
||||
construction = GeometryFacade::getConstruction(geo1)
|
||||
&& GeometryFacade::getConstruction(geo2);
|
||||
|
||||
if (isLineSegment(*geo1) && isLineSegment(*geo2)) {
|
||||
auto* line1 = static_cast<const Part::GeomLineSegment*>(geo1);
|
||||
auto* line2 = static_cast<const Part::GeomLineSegment*>(geo2);
|
||||
Base::Vector3d dir1 = line1->getEndPoint() - line1->getStartPoint();
|
||||
Base::Vector3d dir2 = line2->getEndPoint() - line2->getStartPoint();
|
||||
if (PosIdList[0] == PointPos::end) {
|
||||
dir1 *= -1;
|
||||
}
|
||||
if (PosIdList[1] == Sketcher::PointPos::end) {
|
||||
if (PosIdList[1] == PointPos::end) {
|
||||
dir2 *= -1;
|
||||
}
|
||||
double l1 = dir1.Length();
|
||||
@@ -169,55 +197,197 @@ public:
|
||||
}
|
||||
}
|
||||
if (radius < 0) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
int currentgeoid = getHighestCurveIndex();
|
||||
int filletGeoId = getHighestCurveIndex() + (isChamfer ? 2 : 1);
|
||||
// create fillet at point
|
||||
try {
|
||||
bool pointFillet = (filletType == 1);
|
||||
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create fillet"));
|
||||
Gui::cmdAppObjectArgs(sketchgui->getObject(),
|
||||
"fillet(%d,%d,%f,%s,%s)",
|
||||
Gui::cmdAppObjectArgs(obj,
|
||||
"fillet(%d,%d,%f,%s,%s,%s)",
|
||||
GeoId,
|
||||
static_cast<int>(PosId),
|
||||
radius,
|
||||
"True",
|
||||
pointFillet ? "True" : "False");
|
||||
preserveCorner ? "True" : "False",
|
||||
isChamfer ? "True" : "False");
|
||||
|
||||
if (construction) {
|
||||
Gui::cmdAppObjectArgs(sketchgui->getObject(),
|
||||
"toggleConstruction(%d) ",
|
||||
currentgeoid + 1);
|
||||
Gui::cmdAppObjectArgs(obj, "toggleConstruction(%d) ", filletGeoId);
|
||||
}
|
||||
|
||||
Gui::Command::commitCommand();
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
Gui::NotifyUserError(
|
||||
sketchgui->getObject(),
|
||||
obj,
|
||||
QT_TRANSLATE_NOOP("Notifications", "Failed to create fillet"),
|
||||
e.what());
|
||||
Gui::Command::abortCommand();
|
||||
}
|
||||
|
||||
tryAutoRecomputeIfNotSolve(
|
||||
static_cast<Sketcher::SketchObject*>(sketchgui->getObject()));
|
||||
tryAutoRecomputeIfNotSolve(obj);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int GeoId = getPreselectCurve();
|
||||
if (GeoId > -1) {
|
||||
const Part::Geometry* geom = sketchgui->getSketchObject()->getGeometry(GeoId);
|
||||
if (geom->isDerivedFrom<Part::GeomBoundedCurve>()) {
|
||||
if (Mode == STATUS_SEEK_First) {
|
||||
firstCurve = GeoId;
|
||||
firstPos = onSketchPos;
|
||||
Mode = STATUS_SEEK_Second;
|
||||
// add the line to the selection
|
||||
else {
|
||||
Base::Vector3d refPnt1(firstPos.x, firstPos.y, 0.f);
|
||||
Base::Vector3d refPnt2(secondPos.x, secondPos.y, 0.f);
|
||||
|
||||
const Part::Geometry* geo1 = obj->getGeometry(geoId1);
|
||||
const Part::Geometry* geo2 = obj->getGeometry(geoId2);
|
||||
|
||||
construction =
|
||||
GeometryFacade::getConstruction(geo1) && GeometryFacade::getConstruction(geo2);
|
||||
|
||||
double radius = 0;
|
||||
|
||||
if (isLineSegment(*geo1) && isLineSegment(*geo2)) {
|
||||
// guess fillet radius
|
||||
auto* line1 = static_cast<const Part::GeomLineSegment*>(geo1);
|
||||
auto* line2 = static_cast<const Part::GeomLineSegment*>(geo2);
|
||||
|
||||
radius = Part::suggestFilletRadius(line1, line2, refPnt1, refPnt2);
|
||||
if (radius < 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int filletGeoId = getHighestCurveIndex() + (isChamfer ? 2 : 1);
|
||||
|
||||
// create fillet between lines
|
||||
try {
|
||||
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create fillet"));
|
||||
Gui::cmdAppObjectArgs(
|
||||
obj,
|
||||
"fillet(%d,%d,App.Vector(%f,%f,0),App.Vector(%f,%f,0),%f,%s,%s,%s)",
|
||||
geoId1,
|
||||
geoId2,
|
||||
firstPos.x,
|
||||
firstPos.y,
|
||||
secondPos.x,
|
||||
secondPos.y,
|
||||
radius,
|
||||
"True",
|
||||
preserveCorner ? "True" : "False",
|
||||
isChamfer ? "True" : "False");
|
||||
Gui::Command::commitCommand();
|
||||
}
|
||||
catch (const Base::CADKernelError& e) {
|
||||
if (e.getTranslatable()) {
|
||||
Gui::TranslatedUserError(sketchgui,
|
||||
QObject::tr("CAD Kernel Error"),
|
||||
QObject::tr(e.getMessage().c_str()));
|
||||
}
|
||||
Gui::Selection().clearSelection();
|
||||
Gui::Command::abortCommand();
|
||||
}
|
||||
catch (const Base::ValueError& e) {
|
||||
Gui::TranslatedUserError(sketchgui,
|
||||
QObject::tr("Value Error"),
|
||||
QObject::tr(e.getMessage().c_str()));
|
||||
Gui::Selection().clearSelection();
|
||||
Gui::Command::abortCommand();
|
||||
}
|
||||
|
||||
tryAutoRecompute(obj);
|
||||
|
||||
if (construction) {
|
||||
Gui::cmdAppObjectArgs(obj, "toggleConstruction(%d) ", filletGeoId);
|
||||
}
|
||||
|
||||
|
||||
Gui::Selection().clearSelection();
|
||||
}
|
||||
}
|
||||
|
||||
std::string getToolName() const override
|
||||
{
|
||||
return "DSH_Fillet";
|
||||
}
|
||||
|
||||
QString getCrosshairCursorSVGName() const override
|
||||
{
|
||||
Gui::Selection().rmvSelectionGate();
|
||||
Gui::Selection().addSelectionGate(new FilletSelection(sketchgui->getObject()));
|
||||
|
||||
if (constructionMethod() == DrawSketchHandlerFillet::ConstructionMethod::Fillet) {
|
||||
if (preserveCorner) {
|
||||
return QString::fromLatin1("Sketcher_Pointer_Create_PointFillet");
|
||||
}
|
||||
else {
|
||||
return QString::fromLatin1("Sketcher_Pointer_Create_Fillet");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (preserveCorner) {
|
||||
return QString::fromLatin1("Sketcher_Pointer_Create_PointChamfer");
|
||||
}
|
||||
else {
|
||||
return QString::fromLatin1("Sketcher_Pointer_Create_Chamfer");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<QWidget> createWidget() const override
|
||||
{
|
||||
return std::make_unique<SketcherToolDefaultWidget>();
|
||||
}
|
||||
|
||||
bool isWidgetVisible() const override
|
||||
{
|
||||
return true;
|
||||
};
|
||||
|
||||
QPixmap getToolIcon() const override
|
||||
{
|
||||
return Gui::BitmapFactory().pixmap("Sketcher_CreateFillet");
|
||||
}
|
||||
|
||||
QString getToolWidgetText() const override
|
||||
{
|
||||
return QString(QObject::tr("Fillet/Chamfer parameters"));
|
||||
}
|
||||
|
||||
bool canGoToNextMode() override
|
||||
{
|
||||
if (state() == SelectMode::SeekFirst) {
|
||||
if (vtId != -1) {
|
||||
return true;
|
||||
}
|
||||
if (geoId1 >= 0) {
|
||||
const Part::Geometry* geo = sketchgui->getSketchObject()->getGeometry(geoId1);
|
||||
if (geo->isDerivedFrom<Part::GeomBoundedCurve>()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (state() == SelectMode::SeekSecond) {
|
||||
if (geoId2 >= 0) {
|
||||
const Part::Geometry* geo = sketchgui->getSketchObject()->getGeometry(geoId2);
|
||||
if (geo->isDerivedFrom<Part::GeomBoundedCurve>()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void onButtonPressed(Base::Vector2d onSketchPos) override
|
||||
{
|
||||
this->updateDataAndDrawToPosition(onSketchPos);
|
||||
if (canGoToNextMode()) {
|
||||
if (state() == SelectMode::SeekFirst) {
|
||||
if (vtId != -1) {
|
||||
setState(SelectMode::End);
|
||||
}
|
||||
else {
|
||||
// add the edge to the selection
|
||||
std::stringstream ss;
|
||||
ss << "Edge" << firstCurve + 1;
|
||||
ss << "Edge" << geoId1 + 1;
|
||||
Gui::Selection().addSelection(
|
||||
sketchgui->getSketchObject()->getDocument()->getName(),
|
||||
sketchgui->getSketchObject()->getNameInDocument(),
|
||||
@@ -225,128 +395,66 @@ public:
|
||||
onSketchPos.x,
|
||||
onSketchPos.y,
|
||||
0.f);
|
||||
}
|
||||
else if (Mode == STATUS_SEEK_Second) {
|
||||
int secondCurve = GeoId;
|
||||
Base::Vector2d secondPos = onSketchPos;
|
||||
|
||||
Base::Vector3d refPnt1(firstPos.x, firstPos.y, 0.f);
|
||||
Base::Vector3d refPnt2(secondPos.x, secondPos.y, 0.f);
|
||||
|
||||
const Part::Geometry* geom1 =
|
||||
sketchgui->getSketchObject()->getGeometry(firstCurve);
|
||||
|
||||
double radius = 0;
|
||||
|
||||
if (geom->is<Part::GeomLineSegment>() && geom1->is<Part::GeomLineSegment>()) {
|
||||
// guess fillet radius
|
||||
const Part::GeomLineSegment* lineSeg1 =
|
||||
static_cast<const Part::GeomLineSegment*>(
|
||||
sketchgui->getSketchObject()->getGeometry(firstCurve));
|
||||
const Part::GeomLineSegment* lineSeg2 =
|
||||
static_cast<const Part::GeomLineSegment*>(
|
||||
sketchgui->getSketchObject()->getGeometry(secondCurve));
|
||||
|
||||
radius = Part::suggestFilletRadius(lineSeg1, lineSeg2, refPnt1, refPnt2);
|
||||
if (radius < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
construction = Sketcher::GeometryFacade::getConstruction(lineSeg1)
|
||||
&& Sketcher::GeometryFacade::getConstruction(lineSeg2);
|
||||
}
|
||||
else { // other supported curves
|
||||
const Part::Geometry* geo1 = static_cast<const Part::Geometry*>(
|
||||
sketchgui->getSketchObject()->getGeometry(firstCurve));
|
||||
const Part::Geometry* geo2 = static_cast<const Part::Geometry*>(
|
||||
sketchgui->getSketchObject()->getGeometry(secondCurve));
|
||||
|
||||
construction = Sketcher::GeometryFacade::getConstruction(geo1)
|
||||
&& Sketcher::GeometryFacade::getConstruction(geo2);
|
||||
}
|
||||
|
||||
|
||||
int currentgeoid = getHighestCurveIndex();
|
||||
|
||||
// create fillet between lines
|
||||
try {
|
||||
bool pointFillet = (filletType == 1);
|
||||
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create fillet"));
|
||||
Gui::cmdAppObjectArgs(
|
||||
sketchgui->getObject(),
|
||||
"fillet(%d,%d,App.Vector(%f,%f,0),App.Vector(%f,%f,0),%f,%s,%s)",
|
||||
firstCurve,
|
||||
secondCurve,
|
||||
firstPos.x,
|
||||
firstPos.y,
|
||||
secondPos.x,
|
||||
secondPos.y,
|
||||
radius,
|
||||
"True",
|
||||
pointFillet ? "True" : "False");
|
||||
Gui::Command::commitCommand();
|
||||
}
|
||||
catch (const Base::CADKernelError& e) {
|
||||
if (e.getTranslatable()) {
|
||||
Gui::TranslatedUserError(sketchgui,
|
||||
QObject::tr("CAD Kernel Error"),
|
||||
QObject::tr(e.getMessage().c_str()));
|
||||
}
|
||||
Gui::Selection().clearSelection();
|
||||
Gui::Command::abortCommand();
|
||||
Mode = STATUS_SEEK_First;
|
||||
}
|
||||
catch (const Base::ValueError& e) {
|
||||
Gui::TranslatedUserError(sketchgui,
|
||||
QObject::tr("Value Error"),
|
||||
QObject::tr(e.getMessage().c_str()));
|
||||
Gui::Selection().clearSelection();
|
||||
Gui::Command::abortCommand();
|
||||
Mode = STATUS_SEEK_First;
|
||||
}
|
||||
|
||||
tryAutoRecompute(static_cast<Sketcher::SketchObject*>(sketchgui->getObject()));
|
||||
|
||||
if (construction) {
|
||||
Gui::cmdAppObjectArgs(sketchgui->getObject(),
|
||||
"toggleConstruction(%d) ",
|
||||
currentgeoid + 1);
|
||||
}
|
||||
|
||||
|
||||
Gui::Selection().clearSelection();
|
||||
Mode = STATUS_SEEK_First;
|
||||
moveToNextMode();
|
||||
}
|
||||
}
|
||||
else {
|
||||
moveToNextMode();
|
||||
}
|
||||
}
|
||||
|
||||
if (VtId < 0 && GeoId < 0) { // exit the fillet tool if the user clicked on empty space
|
||||
sketchgui
|
||||
->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
QString getCrosshairCursorSVGName() const override
|
||||
{
|
||||
Gui::Selection().rmvSelectionGate();
|
||||
Gui::Selection().addSelectionGate(new FilletSelection(sketchgui->getObject()));
|
||||
if (filletType == SimpleFillet) {
|
||||
return QString::fromLatin1("Sketcher_Pointer_Create_Fillet");
|
||||
}
|
||||
else {
|
||||
return QString::fromLatin1("Sketcher_Pointer_Create_PointFillet");
|
||||
}
|
||||
bool preserveCorner;
|
||||
int vtId, geoId1, geoId2;
|
||||
Base::Vector2d firstPos, secondPos;
|
||||
};
|
||||
|
||||
template<>
|
||||
void DSHFilletController::configureToolWidget()
|
||||
{
|
||||
if (!init) { // Code to be executed only upon initialisation
|
||||
QStringList names = {QStringLiteral("Fillet"), QStringLiteral("Chamfer")};
|
||||
toolWidget->setComboboxElements(WCombobox::FirstCombo, names);
|
||||
|
||||
toolWidget->setComboboxItemIcon(
|
||||
WCombobox::FirstCombo,
|
||||
0,
|
||||
Gui::BitmapFactory().iconFromTheme("Sketcher_CreateFillet"));
|
||||
toolWidget->setComboboxItemIcon(
|
||||
WCombobox::FirstCombo,
|
||||
1,
|
||||
Gui::BitmapFactory().iconFromTheme("Sketcher_CreateChamfer"));
|
||||
|
||||
toolWidget->setCheckboxLabel(
|
||||
WCheckbox::FirstBox,
|
||||
QApplication::translate("TaskSketcherTool_c1_fillet", "Preserve corner (U)"));
|
||||
toolWidget->setCheckboxToolTip(
|
||||
WCheckbox::FirstBox,
|
||||
QApplication::translate("TaskSketcherTool_c1_fillet",
|
||||
"Preserves intersection point and most constraints"));
|
||||
|
||||
toolWidget->setCheckboxIcon(
|
||||
WCheckbox::FirstBox,
|
||||
Gui::BitmapFactory().iconFromTheme("Sketcher_CreatePointFillet"));
|
||||
}
|
||||
syncCheckboxToHandler(WCheckbox::FirstBox, handler->preserveCorner);
|
||||
}
|
||||
|
||||
template<>
|
||||
void DSHFilletController::adaptDrawingToCheckboxChange(int checkboxindex, bool value)
|
||||
{
|
||||
Q_UNUSED(checkboxindex);
|
||||
|
||||
switch (checkboxindex) {
|
||||
case WCheckbox::FirstBox:
|
||||
handler->preserveCorner = value;
|
||||
break;
|
||||
}
|
||||
|
||||
protected:
|
||||
int filletType;
|
||||
SelectMode Mode;
|
||||
int firstCurve;
|
||||
Base::Vector2d firstPos;
|
||||
};
|
||||
handler->updateCursor();
|
||||
}
|
||||
|
||||
} // namespace SketcherGui
|
||||
|
||||
|
||||
@@ -139,6 +139,7 @@
|
||||
<file>icons/geometry/Sketcher_CreateBSplineByInterpolation_Constr.svg</file>
|
||||
<file>icons/geometry/Sketcher_Create_Periodic_BSplineByInterpolation.svg</file>
|
||||
<file>icons/geometry/Sketcher_Create_Periodic_BSplineByInterpolation_Constr.svg</file>
|
||||
<file>icons/geometry/Sketcher_CreateChamfer.svg</file>
|
||||
<file>icons/geometry/Sketcher_CreateCircle.svg</file>
|
||||
<file>icons/geometry/Sketcher_CreateCircle_Constr.svg</file>
|
||||
<file>icons/geometry/Sketcher_CreateEllipse_3points.svg</file>
|
||||
@@ -229,6 +230,7 @@
|
||||
<file>icons/pointers/Sketcher_Pointer_Create_BSpline.svg</file>
|
||||
<file>icons/pointers/Sketcher_Pointer_Create_BSplineByInterpolation.svg</file>
|
||||
<file>icons/pointers/Sketcher_Pointer_Create_Circle.svg</file>
|
||||
<file>icons/pointers/Sketcher_Pointer_Create_Chamfer.svg</file>
|
||||
<file>icons/pointers/Sketcher_Pointer_Create_EllipseByCenter.svg</file>
|
||||
<file>icons/pointers/Sketcher_Pointer_Create_Ellipse_3points.svg</file>
|
||||
<file>icons/pointers/Sketcher_Pointer_Create_Fillet.svg</file>
|
||||
@@ -238,6 +240,7 @@
|
||||
<file>icons/pointers/Sketcher_Pointer_Create_Periodic_BSpline.svg</file>
|
||||
<file>icons/pointers/Sketcher_Pointer_Create_Periodic_BSplineByInterpolation.svg</file>
|
||||
<file>icons/pointers/Sketcher_Pointer_Create_Point.svg</file>
|
||||
<file>icons/pointers/Sketcher_Pointer_Create_PointChamfer.svg</file>
|
||||
<file>icons/pointers/Sketcher_Pointer_Create_PointFillet.svg</file>
|
||||
<file>icons/pointers/Sketcher_Pointer_Create_Translate.svg</file>
|
||||
<file>icons/pointers/Sketcher_Pointer_Create_Offset.svg</file>
|
||||
|
||||
@@ -0,0 +1,537 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
id="svg2869"
|
||||
version="1.1"
|
||||
viewBox="0 0 64 64"
|
||||
sodipodi:docname="Sketcher_CreateChamfer.svg"
|
||||
inkscape:version="1.1-beta1 (77e7b44db3, 2021-03-28)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<sodipodi:namedview
|
||||
id="namedview89"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
objecttolerance="10.0"
|
||||
gridtolerance="10.0"
|
||||
guidetolerance="10.0"
|
||||
inkscape:pageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="23.53125"
|
||||
inkscape:cx="29.173971"
|
||||
inkscape:cy="38.438247"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="1571"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2869" />
|
||||
<defs
|
||||
id="defs2871">
|
||||
<linearGradient
|
||||
id="linearGradient34">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop33" />
|
||||
<stop
|
||||
style="stop-color:#d3d7cf;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop34" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient32">
|
||||
<stop
|
||||
style="stop-color:#d3d7cf;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop31" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop32" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient17">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop16" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
offset="1"
|
||||
id="stop17" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5">
|
||||
<stop
|
||||
style="stop-color:#ef2929;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop19" />
|
||||
<stop
|
||||
style="stop-color:#ef2929;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop20" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="swatch18">
|
||||
<stop
|
||||
style="stop-color:#ef2929;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop18" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="swatch15">
|
||||
<stop
|
||||
style="stop-color:#3d0000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop15" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5-1">
|
||||
<stop
|
||||
style="stop-color:#ef2929;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5" />
|
||||
<stop
|
||||
style="stop-color:#ef2929;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop6" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3836-9">
|
||||
<stop
|
||||
style="stop-color:#a40000;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3838-8" />
|
||||
<stop
|
||||
style="stop-color:#ef2929;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3840-1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3836-9-3">
|
||||
<stop
|
||||
style="stop-color:#a40000;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3838-8-5" />
|
||||
<stop
|
||||
style="stop-color:#ef2929;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3840-1-6" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="5"
|
||||
x2="-22"
|
||||
y1="18"
|
||||
x1="-18"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3082"
|
||||
xlink:href="#linearGradient3836-9-3" />
|
||||
<linearGradient
|
||||
id="linearGradient3836-9-7">
|
||||
<stop
|
||||
style="stop-color:#a40000;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3838-8-0" />
|
||||
<stop
|
||||
style="stop-color:#ef2929;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3840-1-9" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="5"
|
||||
x2="-22"
|
||||
y1="18"
|
||||
x1="-18"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3082-3"
|
||||
xlink:href="#linearGradient3836-9-7" />
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient3836-9-3"
|
||||
id="linearGradient3801-1-3"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="-18"
|
||||
y1="18"
|
||||
x2="-22"
|
||||
y2="5"
|
||||
gradientTransform="matrix(0.76342439,0,0,0.75750425,-4.596389,2.7525637)" />
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient3836-9-3"
|
||||
id="linearGradient3801-1-3-2"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="-18"
|
||||
y1="18"
|
||||
x2="-22"
|
||||
y2="5"
|
||||
gradientTransform="matrix(0.84956703,0,0,0.84301394,-2.927337,1.7790378)" />
|
||||
<radialGradient
|
||||
xlink:href="#linearGradient3809"
|
||||
id="radialGradient3815"
|
||||
cx="225.93762"
|
||||
cy="91.956673"
|
||||
fx="225.93762"
|
||||
fy="91.956673"
|
||||
r="22"
|
||||
gradientTransform="matrix(-1.4090915,3.8636359,-0.97565325,-0.35582669,437.08461,-816.22007)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient3809">
|
||||
<stop
|
||||
style="stop-color:#729fcf;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3811" />
|
||||
<stop
|
||||
style="stop-color:#204a87;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3813" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="5"
|
||||
x2="-22"
|
||||
y1="18"
|
||||
x1="-18"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3444"
|
||||
xlink:href="#linearGradient3836-9-3"
|
||||
gradientTransform="matrix(0.90206746,0,0,0.90216902,-1.9060863,1.1084289)" />
|
||||
<linearGradient
|
||||
y2="5"
|
||||
x2="-22"
|
||||
y1="18"
|
||||
x1="-18"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3857"
|
||||
xlink:href="#linearGradient3836-9-3"
|
||||
gradientTransform="matrix(0.89262616,0,0,0.89258466,72.894067,1.2176306)" />
|
||||
<linearGradient
|
||||
y2="5"
|
||||
x2="-22"
|
||||
y1="18"
|
||||
x1="-18"
|
||||
gradientTransform="matrix(0.93724177,0,0,0.93725692,-1.2227671,0.70650014)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3148"
|
||||
xlink:href="#linearGradient3836-9-3" />
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient17"
|
||||
id="linearGradient3898"
|
||||
x1="37.429146"
|
||||
y1="41.590584"
|
||||
x2="24.483221"
|
||||
y2="4.9104676"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient3892">
|
||||
<stop
|
||||
style="stop-color:#bdd2e9;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3894" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
offset="1"
|
||||
id="stop3896" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient3892"
|
||||
id="linearGradient3856"
|
||||
x1="22.84341"
|
||||
y1="4.8241611"
|
||||
x2="30.783579"
|
||||
y2="28.644661"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<radialGradient
|
||||
r="22"
|
||||
fy="91.956673"
|
||||
fx="225.93762"
|
||||
cy="91.956673"
|
||||
cx="225.93762"
|
||||
gradientTransform="matrix(-1.7064667,4.6731721,-1.1815555,-0.43038201,776.9032,-933.08315)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient3163"
|
||||
xlink:href="#linearGradient3809" />
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient4104"
|
||||
id="linearGradient4110"
|
||||
x1="-23.070524"
|
||||
y1="18.383886"
|
||||
x2="-24.194258"
|
||||
y2="6.534451"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient4104">
|
||||
<stop
|
||||
style="stop-color:#d3d7cf;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4106" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop4108" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient4096"
|
||||
id="linearGradient4102"
|
||||
x1="-24.035076"
|
||||
y1="16.85112"
|
||||
x2="-23.821426"
|
||||
y2="7.2881389"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient4096">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4098" />
|
||||
<stop
|
||||
style="stop-color:#d3d7cf;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop4100" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient3836-9-3"
|
||||
id="linearGradient4216"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.71430595,0,0,0.71426219,259.5032,71.709694)"
|
||||
x1="-18"
|
||||
y1="18"
|
||||
x2="-22"
|
||||
y2="5" />
|
||||
<radialGradient
|
||||
r="22"
|
||||
fy="91.956673"
|
||||
fx="225.93762"
|
||||
cy="91.956673"
|
||||
cx="225.93762"
|
||||
gradientTransform="matrix(-1.7064667,4.6731721,-1.1815555,-0.43038201,776.9032,-933.08315)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient3163-9"
|
||||
xlink:href="#linearGradient3809" />
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient4104"
|
||||
id="linearGradient4347"
|
||||
x1="-21.31983"
|
||||
y1="18.008659"
|
||||
x2="-24.907471"
|
||||
y2="6.9377007"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient4096"
|
||||
id="linearGradient4339"
|
||||
x1="-21.141161"
|
||||
y1="17.489555"
|
||||
x2="-24.733845"
|
||||
y2="7.0083036"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
y2="5"
|
||||
x2="-22"
|
||||
y1="18"
|
||||
x1="-18"
|
||||
gradientTransform="matrix(0.65313239,0,0,0.65304994,258.31758,72.40809)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4235-2"
|
||||
xlink:href="#linearGradient3836-9-3" />
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient3836-9-3"
|
||||
id="linearGradient3801-1-3-7"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="-18"
|
||||
y1="18"
|
||||
x2="-22"
|
||||
y2="5" />
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient3836-9-3"
|
||||
id="linearGradient29"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.82607043,0,0,0.82533448,-4.0098079,1.346708)"
|
||||
x1="-18"
|
||||
y1="18"
|
||||
x2="-22"
|
||||
y2="5" />
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient32"
|
||||
id="linearGradient3901"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="30.202745"
|
||||
y1="56.729507"
|
||||
x2="35.013981"
|
||||
y2="19.843365"
|
||||
gradientTransform="matrix(0.62354045,-0.62354046,0.62354039,0.62354042,-12.205772,28.459494)" />
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient34"
|
||||
id="linearGradient3903"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="29.993565"
|
||||
y1="54.846851"
|
||||
x2="36.094769"
|
||||
y2="20.854424"
|
||||
gradientTransform="matrix(0.57365718,-0.57365723,0.57365712,0.57365719,-8.6693108,28.742734)" />
|
||||
<linearGradient
|
||||
y2="5"
|
||||
x2="-22"
|
||||
y1="18"
|
||||
x1="-18"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3922"
|
||||
xlink:href="#linearGradient3836-9-3"
|
||||
gradientTransform="matrix(0.85221122,0,0,0.85228409,-2.8500258,1.6945624)" />
|
||||
<linearGradient
|
||||
y2="5"
|
||||
x2="-22"
|
||||
y1="18"
|
||||
x1="-18"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3096"
|
||||
xlink:href="#linearGradient3836-9-3" />
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient3836-9-3"
|
||||
id="linearGradient38"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.82607043,0,0,0.82533448,-4.0098079,1.346708)"
|
||||
x1="-18"
|
||||
y1="18"
|
||||
x2="-22"
|
||||
y2="5" />
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient3836-9-3"
|
||||
id="linearGradient3801-7"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="-18"
|
||||
y1="18"
|
||||
x2="-22"
|
||||
y2="5"
|
||||
gradientTransform="translate(-90,-5.9999999)" />
|
||||
<linearGradient
|
||||
y2="5"
|
||||
x2="-22"
|
||||
y1="18"
|
||||
x1="-18"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3082-3-8"
|
||||
xlink:href="#linearGradient3836-9-3" />
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata2874">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>[maxwxyz]</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:relation>https://www.freecad.org/wiki/index.php?title=Artwork</dc:relation>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<dc:identifier>FreeCAD/src/Mod/Sketcher/Gui/Resources/icons/Sketcher_CreateArc.svg</dc:identifier>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD LGPL2+</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<dc:date>2023-12-19</dc:date>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="g3401"
|
||||
transform="matrix(0.146567,0,0,0.146567,70.402356,-55.12963)">
|
||||
<path
|
||||
style="fill:#d3d7cf;stroke:#151819;stroke-width:13.6456;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m -64.150569,751.39444 v -40.93691 l -68.227781,0.13987 c -245.62106,-231.83597 0,0 -245.62106,-231.83597 -0.11268,-0.10636 -8.1e-4,-82.15354 -8.1e-4,-82.15354 h -40.93691 v 98.11086 c 271.77108,256.96565 2.11823,0.15342 271.77108,256.96565 v 0 z"
|
||||
id="path3077"
|
||||
sodipodi:nodetypes="cccscccccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:13.6456;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m -139.20159,724.1032 c -252.44428,-238.79865 0,0 -252.44428,-238.79865"
|
||||
id="path3892"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:13.6456;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m -405.2915,403.4307 v 81.87383"
|
||||
id="path3079" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:13.6456;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M -70.973388,724.10317 H -146.02439"
|
||||
id="path3081" />
|
||||
<rect
|
||||
style="fill:#d3d7cf;fill-opacity:1;stroke:#151819;stroke-width:13.6456;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:1.9;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect3083"
|
||||
width="27.291277"
|
||||
height="54.582546"
|
||||
x="-418.93713"
|
||||
y="737.74866" />
|
||||
<rect
|
||||
style="fill:#d3d7cf;fill-opacity:1;stroke:#151819;stroke-width:13.6456;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:1.9;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect3083-3"
|
||||
width="27.291368"
|
||||
height="54.582546"
|
||||
x="-418.93723"
|
||||
y="642.22906" />
|
||||
<rect
|
||||
style="fill:#d3d7cf;fill-opacity:1;stroke:#151819;stroke-width:13.6456;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:1.9;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect3083-7"
|
||||
width="27.291306"
|
||||
height="68.228004"
|
||||
x="724.10321"
|
||||
y="391.64584"
|
||||
transform="rotate(90)" />
|
||||
<rect
|
||||
style="fill:#d3d7cf;fill-opacity:1;stroke:none;stroke-width:6.44377;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="rect3083-5"
|
||||
width="13.645644"
|
||||
height="54.582569"
|
||||
x="-412.11432"
|
||||
y="730.92596" />
|
||||
<rect
|
||||
style="fill:#d3d7cf;fill-opacity:1;stroke:#151819;stroke-width:13.6456;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:1.9;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect3083-35"
|
||||
width="27.291306"
|
||||
height="54.582546"
|
||||
x="724.10321"
|
||||
y="309.77203"
|
||||
transform="rotate(90)" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.77869459,0,0,0.77869445,63.667786,43.342778)"
|
||||
id="g29"
|
||||
style="stroke-width:1.2842">
|
||||
<path
|
||||
style="fill:none;stroke:#2e0000;stroke-width:2.56841;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path28"
|
||||
d="M -26.310778,5.3580033 A 8.3519646,8.3515832 0.02039876 1 1 -13.623399,16.222662 8.3519646,8.3515832 0.02039876 1 1 -26.310778,5.3580033 Z" />
|
||||
<path
|
||||
style="fill:url(#linearGradient29);fill-opacity:1;stroke:#ef2929;stroke-width:2.56842;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path29"
|
||||
d="m -24.358888,7.0362241 a 5.782493,5.7773415 0 1 1 8.784093,7.5158349 5.782493,5.7773415 0 0 1 -8.784093,-7.5158349 z" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.77869459,0,0,0.77869445,27.71825,8.6680131)"
|
||||
id="g38"
|
||||
style="stroke-width:1.2842">
|
||||
<path
|
||||
style="fill:none;stroke:#2e0000;stroke-width:2.56841;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path37"
|
||||
d="M -26.310778,5.3580033 A 8.3519646,8.3515832 0.02039876 1 1 -13.623399,16.222662 8.3519646,8.3515832 0.02039876 1 1 -26.310778,5.3580033 Z" />
|
||||
<path
|
||||
style="fill:url(#linearGradient38);fill-opacity:1;stroke:#ef2929;stroke-width:2.56842;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path38"
|
||||
d="m -24.358888,7.0362241 a 5.782493,5.7773415 0 1 1 8.784093,7.5158349 5.782493,5.7773415 0 0 1 -8.784093,-7.5158349 z" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,159 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
height="64"
|
||||
width="64"
|
||||
id="svg10"
|
||||
sodipodi:docname="Sketcher_Pointer_Create_Chamfer.svg"
|
||||
inkscape:version="1.1-beta1 (77e7b44db3, 2021-03-28)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="32"
|
||||
inkscape:cx="30.640625"
|
||||
inkscape:cy="51.484375"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="1571"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="symbol"
|
||||
objecttolerance="10.0"
|
||||
gridtolerance="10.0"
|
||||
guidetolerance="10.0"
|
||||
inkscape:pageshadow="0"
|
||||
showgrid="false" />
|
||||
<defs
|
||||
id="defs14">
|
||||
<inkscape:path-effect
|
||||
effect="dashed_stroke"
|
||||
id="path-effect4"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
numberdashes="3"
|
||||
holefactor="-0.16"
|
||||
splitsegments="true"
|
||||
halfextreme="false"
|
||||
unifysegment="false"
|
||||
message="Add <b>"Fill Between Many LPE"</b> to add fill." />
|
||||
<inkscape:path-effect
|
||||
effect="dashed_stroke"
|
||||
id="path-effect3"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
numberdashes="3"
|
||||
holefactor="0.18"
|
||||
splitsegments="true"
|
||||
halfextreme="false"
|
||||
unifysegment="false"
|
||||
message="Add <b>"Fill Between Many LPE"</b> to add fill." />
|
||||
<inkscape:path-effect
|
||||
effect="dashed_stroke"
|
||||
id="path-effect2"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
numberdashes="3"
|
||||
holefactor="0"
|
||||
splitsegments="true"
|
||||
halfextreme="false"
|
||||
unifysegment="true"
|
||||
message="Add <b>"Fill Between Many LPE"</b> to add fill." />
|
||||
<inkscape:path-effect
|
||||
effect="dashed_stroke"
|
||||
id="path-effect1"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
numberdashes="4"
|
||||
holefactor="0.11"
|
||||
splitsegments="true"
|
||||
halfextreme="false"
|
||||
unifysegment="true"
|
||||
message="Add <b>"Fill Between Many LPE"</b> to add fill." />
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient3836-9"
|
||||
id="linearGradient3801-7"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="-18"
|
||||
y1="18"
|
||||
x2="-22"
|
||||
y2="5"
|
||||
gradientTransform="translate(-90,-5.9999999)" />
|
||||
<linearGradient
|
||||
id="linearGradient3836-9">
|
||||
<stop
|
||||
style="stop-color:#a40000;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3838-8" />
|
||||
<stop
|
||||
style="stop-color:#ef2929;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3840-1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="5"
|
||||
x2="-22"
|
||||
y1="18"
|
||||
x1="-18"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3082-3"
|
||||
xlink:href="#linearGradient3836-9" />
|
||||
</defs>
|
||||
<g
|
||||
id="symbol"
|
||||
style="display:inline;fill:none;stroke:#cc0000;stroke-width:2"
|
||||
transform="translate(4,-2)">
|
||||
<circle
|
||||
cx="26.439085"
|
||||
cy="38.106495"
|
||||
r="4"
|
||||
id="circle4" />
|
||||
<circle
|
||||
cx="42.978943"
|
||||
cy="54.646351"
|
||||
r="4"
|
||||
id="circle4-9"
|
||||
style="display:inline;fill:none;stroke:#cc0000;stroke-width:2" />
|
||||
<path
|
||||
id="rect4"
|
||||
d="M 53.021065,54.646352 H 42.978943 c -16.539858,-16.539858 0,0 -16.539858,-16.539858 V 28.064372"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#cc0000;stroke-width:2;stroke-linecap:butt;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
d="m 26.439086,53.646352 v 5"
|
||||
id="path4"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="display:inline;fill:none;stroke:#cc0000;stroke-width:2;stroke-linecap:butt;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
d="m 26.439086,47.646352 v 3"
|
||||
id="path4-9"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#cc0000;stroke-width:2;stroke-linecap:butt;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
d="m 27.439086,54.646352 -5.000001,-10e-7"
|
||||
id="path5"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="display:inline;fill:none;stroke:#cc0000;stroke-width:2;stroke-linecap:butt;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
d="m 33.439086,54.646352 -3.000001,-10e-7"
|
||||
id="path5-5"
|
||||
sodipodi:nodetypes="cc" />
|
||||
</g>
|
||||
<g
|
||||
id="crosshair"
|
||||
style="stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter">
|
||||
<path
|
||||
d="m16,3v9m0,8v9m-13-13h9m8,0h9"
|
||||
id="path7" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.9 KiB |
@@ -0,0 +1,145 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
height="64"
|
||||
width="64"
|
||||
id="svg10"
|
||||
sodipodi:docname="Sketcher_Pointer_Create_PointChamfer.svg"
|
||||
inkscape:version="1.1-beta1 (77e7b44db3, 2021-03-28)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="11.313708"
|
||||
inkscape:cx="6.7617086"
|
||||
inkscape:cy="43.000931"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="1571"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="symbol"
|
||||
objecttolerance="10.0"
|
||||
gridtolerance="10.0"
|
||||
guidetolerance="10.0"
|
||||
inkscape:pageshadow="0"
|
||||
showgrid="false" />
|
||||
<defs
|
||||
id="defs14">
|
||||
<inkscape:path-effect
|
||||
effect="dashed_stroke"
|
||||
id="path-effect4"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
numberdashes="3"
|
||||
holefactor="-0.16"
|
||||
splitsegments="true"
|
||||
halfextreme="false"
|
||||
unifysegment="false"
|
||||
message="Add <b>"Fill Between Many LPE"</b> to add fill." />
|
||||
<inkscape:path-effect
|
||||
effect="dashed_stroke"
|
||||
id="path-effect3"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
numberdashes="3"
|
||||
holefactor="0.18"
|
||||
splitsegments="true"
|
||||
halfextreme="false"
|
||||
unifysegment="false"
|
||||
message="Add <b>"Fill Between Many LPE"</b> to add fill." />
|
||||
<inkscape:path-effect
|
||||
effect="dashed_stroke"
|
||||
id="path-effect2"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
numberdashes="3"
|
||||
holefactor="0"
|
||||
splitsegments="true"
|
||||
halfextreme="false"
|
||||
unifysegment="true"
|
||||
message="Add <b>"Fill Between Many LPE"</b> to add fill." />
|
||||
<inkscape:path-effect
|
||||
effect="dashed_stroke"
|
||||
id="path-effect1"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
numberdashes="4"
|
||||
holefactor="0.11"
|
||||
splitsegments="true"
|
||||
halfextreme="false"
|
||||
unifysegment="true"
|
||||
message="Add <b>"Fill Between Many LPE"</b> to add fill." />
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient3836-9"
|
||||
id="linearGradient3801-7"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="-18"
|
||||
y1="18"
|
||||
x2="-22"
|
||||
y2="5"
|
||||
gradientTransform="translate(-90,-5.9999999)" />
|
||||
<linearGradient
|
||||
id="linearGradient3836-9">
|
||||
<stop
|
||||
style="stop-color:#a40000;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3838-8" />
|
||||
<stop
|
||||
style="stop-color:#ef2929;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3840-1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="5"
|
||||
x2="-22"
|
||||
y1="18"
|
||||
x1="-18"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3082-3"
|
||||
xlink:href="#linearGradient3836-9" />
|
||||
</defs>
|
||||
<g
|
||||
id="symbol"
|
||||
style="display:inline;fill:none;stroke:#cc0000;stroke-width:2"
|
||||
transform="translate(4,-2)">
|
||||
<circle
|
||||
cx="26.439085"
|
||||
cy="38.106495"
|
||||
r="4"
|
||||
id="circle4" />
|
||||
<circle
|
||||
cx="42.978943"
|
||||
cy="54.646351"
|
||||
r="4"
|
||||
id="circle4-9"
|
||||
style="display:inline;fill:none;stroke:#cc0000;stroke-width:2" />
|
||||
<circle
|
||||
cx="26.439085"
|
||||
cy="54.646351"
|
||||
r="4"
|
||||
id="circle4-9-7"
|
||||
style="display:inline;fill:none;stroke:#cc0000;stroke-width:2" />
|
||||
<path
|
||||
id="rect4"
|
||||
d="M 53.021065,54.646352 H 42.978943 c -16.539858,-16.539858 0,0 -16.539858,-16.539858 V 28.064372"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
</g>
|
||||
<g
|
||||
id="crosshair"
|
||||
style="stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter">
|
||||
<path
|
||||
d="m16,3v9m0,8v9m-13-13h9m8,0h9"
|
||||
id="path7" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
@@ -4161,7 +4161,8 @@ void ViewProviderSketch::generateContextMenu()
|
||||
<< "Separator"
|
||||
<< "Sketcher_ToggleConstruction"
|
||||
<< "Separator"
|
||||
<< "Sketcher_CreatePointFillet"
|
||||
<< "Sketcher_CreateFillet"
|
||||
<< "Sketcher_CreateChamfer"
|
||||
<< "Sketcher_Trimming"
|
||||
<< "Sketcher_Extend"
|
||||
<< "Separator"
|
||||
|
||||
@@ -375,8 +375,8 @@ void SketcherAddWorkspaceFillets(T& geom);
|
||||
template<>
|
||||
inline void SketcherAddWorkspaceFillets<Gui::MenuItem>(Gui::MenuItem& geom)
|
||||
{
|
||||
geom << "Sketcher_CreatePointFillet"
|
||||
<< "Sketcher_CreateFillet";
|
||||
geom << "Sketcher_CreateFillet"
|
||||
<< "Sketcher_CreateChamfer";
|
||||
}
|
||||
|
||||
template<>
|
||||
|
||||
Reference in New Issue
Block a user