[Sketcher] Add methods and tools for joining curves
Algorithm to join b-splines: The code simple concatenates the knots, poles, weights, and knot multiplicities together, removing data on the connection point of the second curve. Some further study is needed to see if/when it will give an exact/good connection. Icon courtesy @bitacovir.
This commit is contained in:
committed by
abdullahtahiriyo
parent
f79c66dc33
commit
01866dfbfc
@@ -3267,6 +3267,147 @@ int SketchObject::split(int GeoId, const Base::Vector3d &point)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int SketchObject::join(int geoId1, Sketcher::PointPos posId1,
|
||||
int geoId2, Sketcher::PointPos posId2)
|
||||
{
|
||||
// No need to check input data validity as this is an sketchobject managed operation
|
||||
|
||||
Base::StateLocker lock(managedoperation, true);
|
||||
|
||||
if (Sketcher::PointPos::start != posId1 && Sketcher::PointPos::end != posId1 &&
|
||||
Sketcher::PointPos::start != posId2 && Sketcher::PointPos::end != posId2) {
|
||||
THROWM(ValueError,"Invalid position(s): points must be start or end points of a curve.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (geoId1 == geoId2) {
|
||||
THROWM(ValueError,"Connecting the end points of the same curve is not yet supported.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (geoId1 < 0 || geoId1 > getHighestCurveIndex() ||
|
||||
geoId2 < 0 || geoId2 > getHighestCurveIndex()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// get the old splines
|
||||
auto* geo1 = getGeometry(geoId1);
|
||||
auto* geo2 = getGeometry(geoId2);
|
||||
|
||||
if (GeometryFacade::getConstruction(geo1) != GeometryFacade::getConstruction(geo2)) {
|
||||
THROWM(ValueError,"Cannot join construction and non-construction geometries.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO: make both curves b-splines here itself
|
||||
if (geo1->getTypeId() != Part::GeomBSplineCurve::getClassTypeId()) {
|
||||
THROWM(ValueError,"Please convert both curves to NURBS before attempting to join them.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (geo2->getTypeId() != Part::GeomBSplineCurve::getClassTypeId()) {
|
||||
THROWM(ValueError,"Please convert both curves to NURBS before attempting to join them.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO: is there a cleaner way to get our mutable bsp's?
|
||||
// we need the splines to be mutable because we may reverse them
|
||||
// and/or change their degree
|
||||
auto* constbsp1 = static_cast<const Part::GeomBSplineCurve *>(geo1);
|
||||
auto* constbsp2 = static_cast<const Part::GeomBSplineCurve *>(geo2);
|
||||
const Handle(Geom_BSplineCurve) curve1 = Handle(Geom_BSplineCurve)::DownCast(constbsp1->handle());
|
||||
const Handle(Geom_BSplineCurve) curve2 = Handle(Geom_BSplineCurve)::DownCast(constbsp2->handle());
|
||||
std::unique_ptr<Part::GeomBSplineCurve> bsp1(new Part::GeomBSplineCurve(curve1));
|
||||
std::unique_ptr<Part::GeomBSplineCurve> bsp2(new Part::GeomBSplineCurve(curve2));
|
||||
|
||||
if (bsp1->isPeriodic() || bsp2->isPeriodic()) {
|
||||
THROWM(ValueError,"It is only possible to join non-periodic curves.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// reverse the splines if needed: join end of 1st to start of 2nd
|
||||
if (Sketcher::PointPos::start == posId1)
|
||||
bsp1->reverse();
|
||||
if (Sketcher::PointPos::end == posId2)
|
||||
bsp2->reverse();
|
||||
|
||||
// ensure the degrees of both curves are the same
|
||||
if (bsp1->getDegree() < bsp2->getDegree())
|
||||
bsp1->increaseDegree(bsp2->getDegree());
|
||||
else if (bsp2->getDegree() < bsp1->getDegree())
|
||||
bsp2->increaseDegree(bsp1->getDegree());
|
||||
|
||||
// TODO: set up vectors for new poles, knots, mults
|
||||
std::vector<Base::Vector3d> poles1 = bsp1->getPoles();
|
||||
std::vector<double> weights1 = bsp1->getWeights();
|
||||
std::vector<double> knots1 = bsp1->getKnots();
|
||||
std::vector<int> mults1 = bsp1->getMultiplicities();
|
||||
std::vector<Base::Vector3d> poles2 = bsp2->getPoles();
|
||||
std::vector<double> weights2 = bsp2->getWeights();
|
||||
std::vector<double> knots2 = bsp2->getKnots();
|
||||
std::vector<int> mults2 = bsp2->getMultiplicities();
|
||||
|
||||
std::vector<Base::Vector3d> newPoles(std::move(poles1));
|
||||
std::vector<double> newWeights(std::move(weights1));
|
||||
std::vector<double> newKnots(std::move(knots1));
|
||||
std::vector<int> newMults(std::move(mults1));
|
||||
|
||||
poles2.erase(poles2.begin());
|
||||
newPoles.insert(newPoles.end(),
|
||||
std::make_move_iterator(poles2.begin()),
|
||||
std::make_move_iterator(poles2.end()));
|
||||
|
||||
// TODO: Weights might need to be scaled
|
||||
weights2.erase(weights2.begin());
|
||||
newWeights.insert(newWeights.end(),
|
||||
std::make_move_iterator(weights2.begin()),
|
||||
std::make_move_iterator(weights2.end()));
|
||||
|
||||
// knots of the second spline come after all of the first
|
||||
double offset = newKnots.back() - knots2.front();
|
||||
knots2.erase(knots2.begin());
|
||||
for (auto& knot : knots2)
|
||||
knot += offset;
|
||||
newKnots.insert(newKnots.end(),
|
||||
std::make_move_iterator(knots2.begin()),
|
||||
std::make_move_iterator(knots2.end()));
|
||||
|
||||
// end knots can have a multiplicity of (degree + 1)
|
||||
if (bsp1->getDegree() < newMults.back())
|
||||
newMults.back() = bsp1->getDegree();
|
||||
mults2.erase(mults2.begin());
|
||||
newMults.insert(newMults.end(),
|
||||
std::make_move_iterator(mults2.begin()),
|
||||
std::make_move_iterator(mults2.end()));
|
||||
|
||||
Part::GeomBSplineCurve* newSpline =
|
||||
new Part::GeomBSplineCurve(newPoles, newWeights, newKnots, newMults,
|
||||
bsp1->getDegree(), false, true);
|
||||
|
||||
int newGeoId = addGeometry(newSpline);
|
||||
|
||||
if (newGeoId < 0) {
|
||||
THROWM(ValueError,"Failed to create joined curve.");
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
exposeInternalGeometry(newGeoId);
|
||||
setConstruction(newGeoId, GeometryFacade::getConstruction(geo1));
|
||||
|
||||
// TODO: transfer constraints on the non-connected ends
|
||||
auto otherPosId1 = (Sketcher::PointPos::start == posId1) ? Sketcher::PointPos::end : Sketcher::PointPos::start;
|
||||
auto otherPosId2 = (Sketcher::PointPos::start == posId2) ? Sketcher::PointPos::end : Sketcher::PointPos::start;
|
||||
|
||||
transferConstraints(geoId1, otherPosId1, newGeoId, PointPos::start, true);
|
||||
transferConstraints(geoId2, otherPosId2, newGeoId, PointPos::end, true);
|
||||
|
||||
delGeometries({geoId1, geoId2});
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool SketchObject::isExternalAllowed(App::Document *pDoc, App::DocumentObject *pObj, eReasonList* rsn) const
|
||||
{
|
||||
if (rsn)
|
||||
|
||||
@@ -289,6 +289,14 @@ public:
|
||||
int extend(int geoId, double increment, PointPos endPoint);
|
||||
/// split a curve
|
||||
int split(int geoId, const Base::Vector3d &point);
|
||||
/*!
|
||||
\brief Join one or two curves at the given end points
|
||||
\details The combined curve will be a b-spline
|
||||
\param geoId1, posId1, geoId2, posId2: the end points to join
|
||||
\retval - 0 on success, -1 on failure
|
||||
*/
|
||||
int join(int geoId1, Sketcher::PointPos posId1,
|
||||
int geoId2, Sketcher::PointPos posId2);
|
||||
|
||||
/// adds symmetric geometric elements with respect to the refGeoId (line or point)
|
||||
int addSymmetric(const std::vector<int> &geoIdList, int refGeoId, Sketcher::PointPos refPosId=Sketcher::PointPos::none);
|
||||
|
||||
@@ -222,6 +222,11 @@ If there is no such constraint an exception is raised.
|
||||
<UserDocu>split a curve with a given id at a given reference point</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="join">
|
||||
<Documentation>
|
||||
<UserDocu>join two curves at the given end points</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="addSymmetric">
|
||||
<Documentation>
|
||||
<UserDocu>add a symmetric geometric objects to the sketch with respect to a reference point or line</UserDocu>
|
||||
|
||||
@@ -1169,6 +1169,28 @@ PyObject* SketchObjectPy::split(PyObject *args)
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyObject* SketchObjectPy::join(PyObject *args)
|
||||
{
|
||||
int GeoId1(Sketcher::GeoEnum::GeoUndef), GeoId2(Sketcher::GeoEnum::GeoUndef);
|
||||
int PosId1 = static_cast<int>(Sketcher::PointPos::none),
|
||||
PosId2 = static_cast<int>(Sketcher::PointPos::none);
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iiii", &GeoId1, &PosId1, &GeoId2, &PosId2))
|
||||
return 0;
|
||||
|
||||
if (this->getSketchObjectPtr()->join(GeoId1, (Sketcher::PointPos) PosId1,
|
||||
GeoId2, (Sketcher::PointPos) PosId2)) {
|
||||
std::stringstream str;
|
||||
str << "Not able to join the curves with end points: ("
|
||||
<< GeoId1 << ", " << PosId1 << "), ("
|
||||
<< GeoId2 << ", " << PosId2 << ")";
|
||||
PyErr_SetString(PyExc_ValueError, str.str().c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyObject* SketchObjectPy::addSymmetric(PyObject *args)
|
||||
{
|
||||
PyObject *pcObj;
|
||||
|
||||
@@ -1196,6 +1196,99 @@ bool CmdSketcherInsertKnot::isActive()
|
||||
return isSketcherBSplineActive(getActiveGuiDocument(), true);
|
||||
}
|
||||
|
||||
DEF_STD_CMD_A(CmdSketcherJoinCurves)
|
||||
|
||||
CmdSketcherJoinCurves::CmdSketcherJoinCurves()
|
||||
: Command("Sketcher_JoinCurves")
|
||||
{
|
||||
sAppModule = "Sketcher";
|
||||
sGroup = "Sketcher";
|
||||
sMenuText = QT_TR_NOOP("Join curves");
|
||||
sToolTipText = QT_TR_NOOP("Join two curves at selected end points");
|
||||
sWhatsThis = "Sketcher_JoinCurves";
|
||||
sStatusTip = sToolTipText;
|
||||
sPixmap = "Sketcher_JoinCurves";
|
||||
sAccel = "";
|
||||
eType = ForEdit;
|
||||
}
|
||||
|
||||
void CmdSketcherJoinCurves::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
|
||||
// TODO: confirm whether or not we need to check for OCC version
|
||||
#if OCC_VERSION_HEX < 0x060900
|
||||
QMessageBox::warning(Gui::getMainWindow(),
|
||||
QObject::tr("Wrong OCE/OCC version"),
|
||||
QObject::tr("This version of OCE/OCC "
|
||||
"does not support knot operation. "
|
||||
"You need 6.9.0 or higher"));
|
||||
return;
|
||||
#endif
|
||||
|
||||
// get the selection
|
||||
std::vector<Gui::SelectionObject> selection;
|
||||
selection = getSelection().getSelectionEx(0, Sketcher::SketchObject::getClassTypeId());
|
||||
|
||||
// only one sketch with its subelements are allowed to be selected
|
||||
if (selection.size() != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get the needed lists and objects
|
||||
const std::vector<std::string> &SubNames = selection[0].getSubNames();
|
||||
if (SubNames.size() == 0) {
|
||||
// Check that something is selected
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Selection is empty"),
|
||||
QObject::tr("Nothing is selected. Please select end points of curves."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (SubNames.size() != 2) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Two end points should be selected."));
|
||||
return;
|
||||
}
|
||||
|
||||
Sketcher::SketchObject* Obj = static_cast<Sketcher::SketchObject*>(selection[0].getObject());
|
||||
|
||||
|
||||
int GeoIds[2];
|
||||
Sketcher::PointPos PosIds[2];
|
||||
getIdsFromName(SubNames[0], Obj, GeoIds[0], PosIds[0]);
|
||||
getIdsFromName(SubNames[1], Obj, GeoIds[1], PosIds[1]);
|
||||
|
||||
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Join Curves"));
|
||||
bool applied = false;
|
||||
|
||||
try {
|
||||
Gui::cmdAppObjectArgs(selection[0].getObject(), "join(%d, %d, %d, %d) ",
|
||||
GeoIds[0], static_cast<int>(PosIds[0]),
|
||||
GeoIds[1], static_cast<int>(PosIds[1]));
|
||||
applied = true;
|
||||
|
||||
// Warning: GeoId list will have changed
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Error"),
|
||||
QObject::tr(getStrippedPythonExceptionString(e).c_str()));
|
||||
getSelection().clearSelection();
|
||||
}
|
||||
|
||||
if (applied)
|
||||
Gui::Command::commitCommand();
|
||||
else
|
||||
Gui::Command::abortCommand();
|
||||
|
||||
tryAutoRecomputeIfNotSolve(Obj);
|
||||
getSelection().clearSelection();
|
||||
}
|
||||
|
||||
bool CmdSketcherJoinCurves::isActive(void)
|
||||
{
|
||||
return isSketcherBSplineActive(getActiveGuiDocument(), true);
|
||||
}
|
||||
|
||||
void CreateSketcherCommandsBSpline()
|
||||
{
|
||||
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
|
||||
@@ -1213,4 +1306,5 @@ void CreateSketcherCommandsBSpline()
|
||||
rcCmdMgr.addCommand(new CmdSketcherDecreaseKnotMultiplicity());
|
||||
rcCmdMgr.addCommand(new CmdSketcherCompModifyKnotMultiplicity());
|
||||
rcCmdMgr.addCommand(new CmdSketcherInsertKnot());
|
||||
rcCmdMgr.addCommand(new CmdSketcherJoinCurves());
|
||||
}
|
||||
|
||||
@@ -216,6 +216,7 @@
|
||||
<file>icons/splines/Sketcher_BSplineIncreaseDegree.svg</file>
|
||||
<file>icons/splines/Sketcher_BSplineIncreaseKnotMultiplicity.svg</file>
|
||||
<file>icons/splines/Sketcher_BSplineInsertKnot.svg</file>
|
||||
<file>icons/splines/Sketcher_JoinCurves.svg</file>
|
||||
<file>icons/splines/Sketcher_BSplineKnotMultiplicity.svg</file>
|
||||
<file>icons/splines/Sketcher_BSplinePoleWeight.svg</file>
|
||||
<file>icons/splines/Sketcher_BSplinePolygon.svg</file>
|
||||
|
||||
@@ -0,0 +1,520 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
version="1.1"
|
||||
id="svg2918"
|
||||
height="64px"
|
||||
width="64px">
|
||||
<title
|
||||
id="title927">Sketcher_BSplineJoin</title>
|
||||
<defs
|
||||
id="defs2920">
|
||||
<linearGradient
|
||||
id="linearGradient3144">
|
||||
<stop
|
||||
id="stop3146"
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3148"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3144-3">
|
||||
<stop
|
||||
id="stop3146-1"
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3148-5"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="34.345188"
|
||||
fy="672.79736"
|
||||
fx="225.26402"
|
||||
cy="672.79736"
|
||||
cx="225.26402"
|
||||
gradientTransform="matrix(1,0,0,0.6985294,0,202.82863)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient3958"
|
||||
xlink:href="#linearGradient3144" />
|
||||
<radialGradient
|
||||
r="34.345188"
|
||||
fy="672.79736"
|
||||
fx="225.26402"
|
||||
cy="672.79736"
|
||||
cx="225.26402"
|
||||
gradientTransform="matrix(1,0,0,0.6985294,0,202.82863)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient3960"
|
||||
xlink:href="#linearGradient3144-3" />
|
||||
<radialGradient
|
||||
r="34.345188"
|
||||
fy="672.79736"
|
||||
fx="225.26402"
|
||||
cy="672.79736"
|
||||
cx="225.26402"
|
||||
gradientTransform="matrix(1,0,0,0.6985294,0,202.82863)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient3042"
|
||||
xlink:href="#linearGradient3144" />
|
||||
<radialGradient
|
||||
r="34.345188"
|
||||
fy="672.79736"
|
||||
fx="225.26402"
|
||||
cy="672.79736"
|
||||
cx="225.26402"
|
||||
gradientTransform="matrix(1,0,0,0.6985294,0,202.82863)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient3068"
|
||||
xlink:href="#linearGradient3144" />
|
||||
<radialGradient
|
||||
r="34.345188"
|
||||
fy="672.79736"
|
||||
fx="225.26402"
|
||||
cy="672.79736"
|
||||
cx="225.26402"
|
||||
gradientTransform="matrix(1,0,0,0.6985294,0,202.82863)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient3880"
|
||||
xlink:href="#linearGradient3144" />
|
||||
<radialGradient
|
||||
r="34.345188"
|
||||
fy="672.79736"
|
||||
fx="225.26402"
|
||||
cy="672.79736"
|
||||
cx="225.26402"
|
||||
gradientTransform="matrix(1,0,0,0.6985294,0,202.82863)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient4654"
|
||||
xlink:href="#linearGradient3144" />
|
||||
<radialGradient
|
||||
r="34.345188"
|
||||
fy="672.79736"
|
||||
fx="225.26402"
|
||||
cy="672.79736"
|
||||
cx="225.26402"
|
||||
gradientTransform="matrix(1,0,0,0.6985294,0,202.82863)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient4693"
|
||||
xlink:href="#linearGradient3144" />
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient3836-9-3-9"
|
||||
id="linearGradient3131-2"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="-18"
|
||||
y1="18"
|
||||
x2="-22"
|
||||
y2="5" />
|
||||
<linearGradient
|
||||
id="linearGradient3836-9-3-9">
|
||||
<stop
|
||||
id="stop3838-8-5-1"
|
||||
offset="0"
|
||||
style="stop-color:#a40000;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop3840-1-6-2"
|
||||
offset="1"
|
||||
style="stop-color:#ef2929;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient3836-9-3-6-0"
|
||||
id="linearGradient3171-7"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="-18"
|
||||
y1="18"
|
||||
x2="-22"
|
||||
y2="5" />
|
||||
<linearGradient
|
||||
id="linearGradient3836-9-3-6-0">
|
||||
<stop
|
||||
id="stop3838-8-5-7-9"
|
||||
offset="0"
|
||||
style="stop-color:#a40000;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop3840-1-6-5-3"
|
||||
offset="1"
|
||||
style="stop-color:#ef2929;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="5"
|
||||
x2="-22"
|
||||
y1="18"
|
||||
x1="-18"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3262"
|
||||
xlink:href="#linearGradient3836-9-3" />
|
||||
<linearGradient
|
||||
id="linearGradient3836-9-3">
|
||||
<stop
|
||||
id="stop3838-8-5"
|
||||
offset="0"
|
||||
style="stop-color:#a40000;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop3840-1-6"
|
||||
offset="1"
|
||||
style="stop-color:#ef2929;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3836-9-3-6">
|
||||
<stop
|
||||
id="stop3838-8-5-7"
|
||||
offset="0"
|
||||
style="stop-color:#a40000;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop3840-1-6-5"
|
||||
offset="1"
|
||||
style="stop-color:#ef2929;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientTransform="matrix(0.93724177,0,0,0.93725692,-1.2227671,0.70650014)"
|
||||
y2="5"
|
||||
x2="-22"
|
||||
y1="18"
|
||||
x1="-18"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3264-1"
|
||||
xlink:href="#linearGradient3836-9-3-6-7" />
|
||||
<linearGradient
|
||||
id="linearGradient3836-9-3-6-7">
|
||||
<stop
|
||||
id="stop3838-8-5-7-4"
|
||||
offset="0"
|
||||
style="stop-color:#a40000;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop3840-1-6-5-0"
|
||||
offset="1"
|
||||
style="stop-color:#ef2929;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientTransform="matrix(0.93724177,0,0,0.93725692,-1.2227671,0.70650014)"
|
||||
y2="5"
|
||||
x2="-22"
|
||||
y1="18"
|
||||
x1="-18"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3264-9"
|
||||
xlink:href="#linearGradient3836-9-3-6-4" />
|
||||
<linearGradient
|
||||
id="linearGradient3836-9-3-6-4">
|
||||
<stop
|
||||
id="stop3838-8-5-7-8"
|
||||
offset="0"
|
||||
style="stop-color:#a40000;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop3840-1-6-5-8"
|
||||
offset="1"
|
||||
style="stop-color:#ef2929;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientTransform="matrix(0.93724177,0,0,0.93725692,-1.2227671,0.70650014)"
|
||||
y2="5"
|
||||
x2="-22"
|
||||
y1="18"
|
||||
x1="-18"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3264-17"
|
||||
xlink:href="#linearGradient3836-9-3-6-1" />
|
||||
<linearGradient
|
||||
id="linearGradient3836-9-3-6-1">
|
||||
<stop
|
||||
id="stop3838-8-5-7-1"
|
||||
offset="0"
|
||||
style="stop-color:#a40000;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop3840-1-6-5-5"
|
||||
offset="1"
|
||||
style="stop-color:#ef2929;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientTransform="matrix(0.93724177,0,0,0.93725692,-1.2227671,0.70650014)"
|
||||
y2="5"
|
||||
x2="-22"
|
||||
y1="18"
|
||||
x1="-18"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3264-3"
|
||||
xlink:href="#linearGradient3836-9-3-6-2" />
|
||||
<linearGradient
|
||||
id="linearGradient3836-9-3-6-2">
|
||||
<stop
|
||||
id="stop3838-8-5-7-2"
|
||||
offset="0"
|
||||
style="stop-color:#a40000;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop3840-1-6-5-1"
|
||||
offset="1"
|
||||
style="stop-color:#ef2929;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="5"
|
||||
x2="-22"
|
||||
y1="18"
|
||||
x1="-18"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3262-5"
|
||||
xlink:href="#linearGradient3836-9-3-3" />
|
||||
<linearGradient
|
||||
id="linearGradient3836-9-3-3">
|
||||
<stop
|
||||
id="stop3838-8-5-5"
|
||||
offset="0"
|
||||
style="stop-color:#a40000;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop3840-1-6-6"
|
||||
offset="1"
|
||||
style="stop-color:#ef2929;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="5"
|
||||
x2="-22"
|
||||
y1="18"
|
||||
x1="-18"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3264"
|
||||
xlink:href="#linearGradient3836-9-3-6-29" />
|
||||
<linearGradient
|
||||
id="linearGradient3836-9-3-6-29">
|
||||
<stop
|
||||
id="stop3838-8-5-7-12"
|
||||
offset="0"
|
||||
style="stop-color:#a40000;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop3840-1-6-5-7"
|
||||
offset="1"
|
||||
style="stop-color:#ef2929;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient3836-9-3-9-9"
|
||||
id="linearGradient3131-2-0"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="-18"
|
||||
y1="18"
|
||||
x2="-22"
|
||||
y2="5" />
|
||||
<linearGradient
|
||||
id="linearGradient3836-9-3-9-9">
|
||||
<stop
|
||||
id="stop3838-8-5-1-3"
|
||||
offset="0"
|
||||
style="stop-color:#a40000;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop3840-1-6-2-6"
|
||||
offset="1"
|
||||
style="stop-color:#ef2929;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient3836-9-3-6-0-6"
|
||||
id="linearGradient3171-7-0"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="-18"
|
||||
y1="18"
|
||||
x2="-22"
|
||||
y2="5" />
|
||||
<linearGradient
|
||||
id="linearGradient3836-9-3-6-0-6">
|
||||
<stop
|
||||
id="stop3838-8-5-7-9-2"
|
||||
offset="0"
|
||||
style="stop-color:#a40000;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop3840-1-6-5-3-6"
|
||||
offset="1"
|
||||
style="stop-color:#ef2929;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientTransform="matrix(0.71441909,0,0,0.71408544,-5.531259,3.2604792)"
|
||||
y2="5"
|
||||
x2="-22"
|
||||
y1="18"
|
||||
x1="-18"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3931"
|
||||
xlink:href="#linearGradient3836-9-3-6-29" />
|
||||
<linearGradient
|
||||
y2="5"
|
||||
x2="-22"
|
||||
y1="18"
|
||||
x1="-18"
|
||||
gradientTransform="matrix(0.71441909,0,0,0.71408544,-5.531259,3.2604792)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3937-1"
|
||||
xlink:href="#linearGradient3836-9-3-6-29-8" />
|
||||
<linearGradient
|
||||
id="linearGradient3836-9-3-6-29-8">
|
||||
<stop
|
||||
id="stop3838-8-5-7-12-7"
|
||||
offset="0"
|
||||
style="stop-color:#a40000;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop3840-1-6-5-7-9"
|
||||
offset="1"
|
||||
style="stop-color:#ef2929;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3836-9-3-6-29-7">
|
||||
<stop
|
||||
id="stop3838-8-5-7-12-5"
|
||||
offset="0"
|
||||
style="stop-color:#a40000;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop3840-1-6-5-7-92"
|
||||
offset="1"
|
||||
style="stop-color:#ef2929;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3836-9-3-6-29-1">
|
||||
<stop
|
||||
id="stop3838-8-5-7-12-2"
|
||||
offset="0"
|
||||
style="stop-color:#a40000;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop3840-1-6-5-7-93"
|
||||
offset="1"
|
||||
style="stop-color:#ef2929;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="131.22015"
|
||||
x2="154.4444"
|
||||
y1="161.22015"
|
||||
x1="164.4444"
|
||||
id="linearGradient3850"
|
||||
xlink:href="#linearGradient3836" />
|
||||
<linearGradient
|
||||
id="linearGradient3836">
|
||||
<stop
|
||||
id="stop3838"
|
||||
offset="0"
|
||||
style="stop-color:#3465a4;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3840"
|
||||
offset="1"
|
||||
style="stop-color:#729fcf;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="131.22015"
|
||||
x2="154.4444"
|
||||
y1="161.22015"
|
||||
x1="164.4444"
|
||||
gradientTransform="translate(-188.44439,-101.22016)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3112"
|
||||
xlink:href="#linearGradient3836" />
|
||||
<linearGradient
|
||||
id="linearGradient3895">
|
||||
<stop
|
||||
id="stop3897"
|
||||
offset="0"
|
||||
style="stop-color:#729fcf;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3899"
|
||||
offset="1"
|
||||
style="stop-color:#204a87;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient3895"
|
||||
id="linearGradient989"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.52479408,0.00179447,0.00125537,-0.75015952,-9.0500601,39.653956)"
|
||||
x1="51.973827"
|
||||
y1="35.978416"
|
||||
x2="25.988253"
|
||||
y2="29.916241" />
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient3895"
|
||||
id="linearGradient1099"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.52479408,0.00179447,0.00125537,-0.75015952,-9.0500601,39.653956)"
|
||||
x1="51.973827"
|
||||
y1="35.978416"
|
||||
x2="25.988253"
|
||||
y2="29.916241" />
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata2923">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>Sketcher_BSplineJoin</dc:title>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>[bitacovir]</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:title>Sketcher_Create_Periodic_BSpline</dc:title>
|
||||
<dc:date>06-03-2022</dc:date>
|
||||
<dc:relation></dc:relation>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<dc:identifier />
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD LGPL2+</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<cc:license>https://www.gnu.org/copyleft/lesser.html</cc:license>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title />
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<path
|
||||
style="fill:none;stroke:#2e3436;stroke-width:12.5366;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 55.641578,8.1868685 C 57.288732,49.584802 17.403372,29.037685 8.2549696,55.500154"
|
||||
id="path3266" />
|
||||
<path
|
||||
style="fill:none;stroke:#d3d7cf;stroke-width:6.2683;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 55.641578,8.1868685 C 57.999108,48.322001 17.200318,29.50549 8.2549696,55.500154"
|
||||
id="path3266-9" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:3.13415;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 54.016393,8.1868685 C 57.606356,46.713599 15.172328,27.635191 6.6297851,55.651091"
|
||||
id="path3266-9-2" />
|
||||
<g
|
||||
transform="matrix(-0.14137236,0.07774155,-0.01888492,-0.10633123,99.823869,75.569613)"
|
||||
id="g3177" />
|
||||
<g
|
||||
transform="matrix(-0.14109247,0.07923086,-0.02087339,-0.10522619,77.138226,86.686164)"
|
||||
id="g3185" />
|
||||
<g
|
||||
id="g1068">
|
||||
<path
|
||||
id="path3343-20"
|
||||
d="m 13.547502,28.511064 v -7.501616 l -10.4959114,1e-6 V 10.507184 H 13.547502 V 3.005568 l 9.44632,12.752748 z"
|
||||
style="fill:url(#linearGradient989);fill-opacity:1;fill-rule:evenodd;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
id="path3343-2-9"
|
||||
d="m 15.03712,23.61475 -0.03666,-4.418275 -10.3125666,-0.08933 -0.036666,-6.608334 10.5325806,0.08933 -0.110007,-4.65436 5.722274,7.824535 z"
|
||||
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
<g
|
||||
id="g1068-6"
|
||||
transform="matrix(-1,0,0,1,45.987644,0)">
|
||||
<path
|
||||
style="fill:url(#linearGradient1099);fill-opacity:1;fill-rule:evenodd;stroke:#0b1521;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 13.547502,28.511064 v -7.501616 l -10.4959114,1e-6 V 10.507184 H 13.547502 V 3.005568 l 9.44632,12.752748 z"
|
||||
id="path3343-20-4" />
|
||||
<path
|
||||
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 15.03712,23.61475 -0.03666,-4.418275 -10.3125666,-0.08933 -0.036666,-6.608334 10.5325806,0.08933 -0.110007,-4.65436 5.722274,7.824535 z"
|
||||
id="path3343-2-9-3" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 16 KiB |
@@ -423,7 +423,8 @@ inline void SketcherAddWorkbenchBSplines<Gui::MenuItem>(Gui::MenuItem& bspline)
|
||||
<< "Sketcher_BSplineDecreaseDegree"
|
||||
<< "Sketcher_BSplineIncreaseKnotMultiplicity"
|
||||
<< "Sketcher_BSplineDecreaseKnotMultiplicity"
|
||||
<< "Sketcher_BSplineInsertKnot";
|
||||
<< "Sketcher_BSplineInsertKnot"
|
||||
<< "Sketcher_JoinCurves";
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -434,7 +435,8 @@ inline void SketcherAddWorkbenchBSplines<Gui::ToolBarItem>(Gui::ToolBarItem& bsp
|
||||
<< "Sketcher_BSplineIncreaseDegree"
|
||||
<< "Sketcher_BSplineDecreaseDegree"
|
||||
<< "Sketcher_CompModifyKnotMultiplicity"
|
||||
<< "Sketcher_BSplineInsertKnot";
|
||||
<< "Sketcher_BSplineInsertKnot"
|
||||
<< "Sketcher_JoinCurves";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
||||
Reference in New Issue
Block a user