Sketcher: Group dragging
This commit is contained in:
@@ -4765,307 +4765,260 @@ int Sketch::internalSolve(std::string& solvername, int level)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Sketch::initMove(int geoId, PointPos pos, bool fine)
|
||||
int Sketch::initMove(std::vector<GeoElementId> moved, bool fine)
|
||||
{
|
||||
isFine = fine;
|
||||
|
||||
geoId = checkGeoId(geoId);
|
||||
|
||||
clearTemporaryConstraints();
|
||||
|
||||
// don't try to move sketches that contain conflicting constraints
|
||||
if (hasConflicts()) {
|
||||
// don't try to move sketches that contain conflicting constraints
|
||||
isInitMove = false;
|
||||
return -1;
|
||||
}
|
||||
isFine = fine;
|
||||
|
||||
if (Geoms[geoId].type == Point) {
|
||||
if (pos == PointPos::start) {
|
||||
GCS::Point& point = Points[Geoms[geoId].startPointId];
|
||||
GCS::Point p0;
|
||||
MoveParameters.resize(2); // px,py
|
||||
p0.x = &MoveParameters[0];
|
||||
p0.y = &MoveParameters[1];
|
||||
*p0.x = *point.x;
|
||||
*p0.y = *point.y;
|
||||
GCSsys.addConstraintP2PCoincident(p0, point, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == Line) {
|
||||
if (pos == PointPos::start || pos == PointPos::end) {
|
||||
MoveParameters.resize(2); // x,y
|
||||
GCS::Point p0;
|
||||
p0.x = &MoveParameters[0];
|
||||
p0.y = &MoveParameters[1];
|
||||
if (pos == PointPos::start) {
|
||||
GCS::Point& p = Points[Geoms[geoId].startPointId];
|
||||
*p0.x = *p.x;
|
||||
*p0.y = *p.y;
|
||||
GCSsys.addConstraintP2PCoincident(p0, p, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
else if (pos == PointPos::end) {
|
||||
GCS::Point& p = Points[Geoms[geoId].endPointId];
|
||||
*p0.x = *p.x;
|
||||
*p0.y = *p.y;
|
||||
GCSsys.addConstraintP2PCoincident(p0, p, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
}
|
||||
else if (pos == PointPos::none || pos == PointPos::mid) {
|
||||
MoveParameters.resize(4); // x1,y1,x2,y2
|
||||
GCS::Point p1, p2;
|
||||
p1.x = &MoveParameters[0];
|
||||
p1.y = &MoveParameters[1];
|
||||
p2.x = &MoveParameters[2];
|
||||
p2.y = &MoveParameters[3];
|
||||
GCS::Line& l = Lines[Geoms[geoId].index];
|
||||
*p1.x = *l.p1.x;
|
||||
*p1.y = *l.p1.y;
|
||||
*p2.x = *l.p2.x;
|
||||
*p2.y = *l.p2.y;
|
||||
GCSsys.addConstraintP2PCoincident(p1, l.p1, GCS::DefaultTemporaryConstraint);
|
||||
GCSsys.addConstraintP2PCoincident(p2, l.p2, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == Circle) {
|
||||
GCS::Point& center = Points[Geoms[geoId].midPointId];
|
||||
GCS::Point p0, p1;
|
||||
if (pos == PointPos::mid) {
|
||||
MoveParameters.resize(2); // cx,cy
|
||||
p0.x = &MoveParameters[0];
|
||||
p0.y = &MoveParameters[1];
|
||||
*p0.x = *center.x;
|
||||
*p0.y = *center.y;
|
||||
GCSsys.addConstraintP2PCoincident(p0, center, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
else if (pos == PointPos::none) {
|
||||
// bool pole = GeometryFacade::isInternalType(Geoms[geoId].geo,
|
||||
// InternalType::BSplineControlPoint);
|
||||
MoveParameters.resize(4); // x,y,cx,cy - For poles blocking the center
|
||||
GCS::Circle& c = Circles[Geoms[geoId].index];
|
||||
p0.x = &MoveParameters[0];
|
||||
p0.y = &MoveParameters[1];
|
||||
*p0.x = *center.x;
|
||||
*p0.y = *center.y + *c.rad;
|
||||
GCSsys.addConstraintPointOnCircle(p0, c, GCS::DefaultTemporaryConstraint);
|
||||
p1.x = &MoveParameters[2];
|
||||
p1.y = &MoveParameters[3];
|
||||
*p1.x = *center.x;
|
||||
*p1.y = *center.y;
|
||||
int i = GCSsys.addConstraintP2PCoincident(p1, center, GCS::DefaultTemporaryConstraint);
|
||||
GCSsys.rescaleConstraint(i - 1, 0.01);
|
||||
GCSsys.rescaleConstraint(i, 0.01);
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == Ellipse) {
|
||||
clearTemporaryConstraints();
|
||||
|
||||
GCS::Point& center = Points[Geoms[geoId].midPointId];
|
||||
GCS::Point p0, p1;
|
||||
if (pos == PointPos::mid || pos == PointPos::none) {
|
||||
MoveParameters.resize(2); // cx,cy
|
||||
p0.x = &MoveParameters[0];
|
||||
p0.y = &MoveParameters[1];
|
||||
*p0.x = *center.x;
|
||||
*p0.y = *center.y;
|
||||
MoveParameters.clear();
|
||||
|
||||
GCSsys.addConstraintP2PCoincident(p0, center, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == ArcOfEllipse) {
|
||||
|
||||
GCS::Point& center = Points[Geoms[geoId].midPointId];
|
||||
GCS::Point p0, p1;
|
||||
if (pos == PointPos::mid || pos == PointPos::none) {
|
||||
MoveParameters.resize(2); // cx,cy
|
||||
p0.x = &MoveParameters[0];
|
||||
p0.y = &MoveParameters[1];
|
||||
*p0.x = *center.x;
|
||||
*p0.y = *center.y;
|
||||
GCSsys.addConstraintP2PCoincident(p0, center, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
else if (pos == PointPos::start || pos == PointPos::end) {
|
||||
|
||||
MoveParameters.resize(4); // x,y,cx,cy
|
||||
if (pos == PointPos::start || pos == PointPos::end) {
|
||||
GCS::Point& p = (pos == PointPos::start) ? Points[Geoms[geoId].startPointId]
|
||||
: Points[Geoms[geoId].endPointId];
|
||||
;
|
||||
p0.x = &MoveParameters[0];
|
||||
p0.y = &MoveParameters[1];
|
||||
*p0.x = *p.x;
|
||||
*p0.y = *p.y;
|
||||
|
||||
GCSsys.addConstraintP2PCoincident(p0, p, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
|
||||
p1.x = &MoveParameters[2];
|
||||
p1.y = &MoveParameters[3];
|
||||
*p1.x = *center.x;
|
||||
*p1.y = *center.y;
|
||||
|
||||
int i = GCSsys.addConstraintP2PCoincident(p1, center, GCS::DefaultTemporaryConstraint);
|
||||
GCSsys.rescaleConstraint(i - 1, 0.01);
|
||||
GCSsys.rescaleConstraint(i, 0.01);
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == ArcOfHyperbola) {
|
||||
|
||||
GCS::Point& center = Points[Geoms[geoId].midPointId];
|
||||
GCS::Point p0, p1;
|
||||
if (pos == PointPos::mid || pos == PointPos::none) {
|
||||
MoveParameters.resize(2); // cx,cy
|
||||
p0.x = &MoveParameters[0];
|
||||
p0.y = &MoveParameters[1];
|
||||
*p0.x = *center.x;
|
||||
*p0.y = *center.y;
|
||||
|
||||
GCSsys.addConstraintP2PCoincident(p0, center, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
else if (pos == PointPos::start || pos == PointPos::end) {
|
||||
|
||||
MoveParameters.resize(4); // x,y,cx,cy
|
||||
if (pos == PointPos::start || pos == PointPos::end) {
|
||||
GCS::Point& p = (pos == PointPos::start) ? Points[Geoms[geoId].startPointId]
|
||||
: Points[Geoms[geoId].endPointId];
|
||||
;
|
||||
p0.x = &MoveParameters[0];
|
||||
p0.y = &MoveParameters[1];
|
||||
*p0.x = *p.x;
|
||||
*p0.y = *p.y;
|
||||
|
||||
GCSsys.addConstraintP2PCoincident(p0, p, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
p1.x = &MoveParameters[2];
|
||||
p1.y = &MoveParameters[3];
|
||||
*p1.x = *center.x;
|
||||
*p1.y = *center.y;
|
||||
|
||||
int i = GCSsys.addConstraintP2PCoincident(p1, center, GCS::DefaultTemporaryConstraint);
|
||||
GCSsys.rescaleConstraint(i - 1, 0.01);
|
||||
GCSsys.rescaleConstraint(i, 0.01);
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == ArcOfParabola) {
|
||||
|
||||
GCS::Point& center = Points[Geoms[geoId].midPointId];
|
||||
GCS::Point p0, p1;
|
||||
if (pos == PointPos::mid || pos == PointPos::none) {
|
||||
MoveParameters.resize(2); // cx,cy
|
||||
p0.x = &MoveParameters[0];
|
||||
p0.y = &MoveParameters[1];
|
||||
*p0.x = *center.x;
|
||||
*p0.y = *center.y;
|
||||
|
||||
GCSsys.addConstraintP2PCoincident(p0, center, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
else if (pos == PointPos::start || pos == PointPos::end) {
|
||||
|
||||
MoveParameters.resize(4); // x,y,cx,cy
|
||||
if (pos == PointPos::start || pos == PointPos::end) {
|
||||
GCS::Point& p = (pos == PointPos::start) ? Points[Geoms[geoId].startPointId]
|
||||
: Points[Geoms[geoId].endPointId];
|
||||
;
|
||||
p0.x = &MoveParameters[0];
|
||||
p0.y = &MoveParameters[1];
|
||||
*p0.x = *p.x;
|
||||
*p0.y = *p.y;
|
||||
|
||||
GCSsys.addConstraintP2PCoincident(p0, p, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
p1.x = &MoveParameters[2];
|
||||
p1.y = &MoveParameters[3];
|
||||
*p1.x = *center.x;
|
||||
*p1.y = *center.y;
|
||||
|
||||
int i = GCSsys.addConstraintP2PCoincident(p1, center, GCS::DefaultTemporaryConstraint);
|
||||
GCSsys.rescaleConstraint(i - 1, 0.01);
|
||||
GCSsys.rescaleConstraint(i, 0.01);
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == BSpline) {
|
||||
if (pos == PointPos::start || pos == PointPos::end) {
|
||||
MoveParameters.resize(2); // x,y
|
||||
GCS::Point p0;
|
||||
p0.x = &MoveParameters[0];
|
||||
p0.y = &MoveParameters[1];
|
||||
if (pos == PointPos::start) {
|
||||
GCS::Point& p = Points[Geoms[geoId].startPointId];
|
||||
*p0.x = *p.x;
|
||||
*p0.y = *p.y;
|
||||
GCSsys.addConstraintP2PCoincident(p0, p, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
else if (pos == PointPos::end) {
|
||||
GCS::Point& p = Points[Geoms[geoId].endPointId];
|
||||
*p0.x = *p.x;
|
||||
*p0.y = *p.y;
|
||||
GCSsys.addConstraintP2PCoincident(p0, p, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
}
|
||||
else if (pos == PointPos::none || pos == PointPos::mid) {
|
||||
// We need to reserve enough size in the vec or the dynamic resizing
|
||||
// (emplace_back in the for loop below) will trigger reallocation.
|
||||
// Which will corrupt pointers we're storing.
|
||||
size_t reserveSize = 0;
|
||||
for (auto& pair : moved) {
|
||||
int geoId = checkGeoId(pair.GeoId);
|
||||
Sketcher::PointPos pos = pair.Pos;
|
||||
if (Geoms[geoId].type == BSpline && (pos == PointPos::none || pos == PointPos::mid)) {
|
||||
GCS::BSpline& bsp = BSplines[Geoms[geoId].index];
|
||||
MoveParameters.resize(bsp.poles.size() * 2); // x0,y0,x1,y1,....xp,yp
|
||||
|
||||
int mvindex = 0;
|
||||
for (std::vector<GCS::Point>::iterator it = bsp.poles.begin(); it != bsp.poles.end();
|
||||
it++, mvindex++) {
|
||||
GCS::Point p1;
|
||||
p1.x = &MoveParameters[mvindex];
|
||||
mvindex++;
|
||||
p1.y = &MoveParameters[mvindex];
|
||||
|
||||
*p1.x = *(*it).x;
|
||||
*p1.y = *(*it).y;
|
||||
|
||||
GCSsys.addConstraintP2PCoincident(p1, (*it), GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
reserveSize += bsp.poles.size() * 2;
|
||||
}
|
||||
else {
|
||||
reserveSize += 6; // 6 is the max case for all other cases.
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == Arc) {
|
||||
GCS::Point& center = Points[Geoms[geoId].midPointId];
|
||||
GCS::Point p0, p1;
|
||||
if (pos == PointPos::mid) {
|
||||
MoveParameters.resize(2); // cx,cy
|
||||
p0.x = &MoveParameters[0];
|
||||
p0.y = &MoveParameters[1];
|
||||
*p0.x = *center.x;
|
||||
*p0.y = *center.y;
|
||||
GCSsys.addConstraintP2PCoincident(p0, center, GCS::DefaultTemporaryConstraint);
|
||||
MoveParameters.reserve(reserveSize);
|
||||
|
||||
for (auto& pair : moved) {
|
||||
int geoId = checkGeoId(pair.GeoId);
|
||||
Sketcher::PointPos pos = pair.Pos;
|
||||
|
||||
if (Geoms[geoId].type == Point) {
|
||||
if (pos == PointPos::start) {
|
||||
GCS::Point& point = Points[Geoms[geoId].startPointId];
|
||||
GCS::Point p0;
|
||||
p0.x = &MoveParameters.emplace_back(*point.x);
|
||||
p0.y = &MoveParameters.emplace_back(*point.y);
|
||||
GCSsys.addConstraintP2PCoincident(p0, point, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
}
|
||||
else if (pos == PointPos::start || pos == PointPos::end || pos == PointPos::none) {
|
||||
MoveParameters.resize(4); // x,y,cx,cy
|
||||
else if (Geoms[geoId].type == Line) {
|
||||
if (pos == PointPos::start || pos == PointPos::end) {
|
||||
GCS::Point& p = (pos == PointPos::start) ? Points[Geoms[geoId].startPointId]
|
||||
: Points[Geoms[geoId].endPointId];
|
||||
;
|
||||
p0.x = &MoveParameters[0];
|
||||
p0.y = &MoveParameters[1];
|
||||
*p0.x = *p.x;
|
||||
*p0.y = *p.y;
|
||||
GCS::Point p0;
|
||||
GCS::Point& p = pos == PointPos::start ? Points[Geoms[geoId].startPointId]
|
||||
: Points[Geoms[geoId].endPointId];
|
||||
p0.x = &MoveParameters.emplace_back(*p.x);
|
||||
p0.y = &MoveParameters.emplace_back(*p.y);
|
||||
GCSsys.addConstraintP2PCoincident(p0, p, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
else if (pos == PointPos::none || pos == PointPos::mid) {
|
||||
GCS::Point p1, p2;
|
||||
GCS::Line& l = Lines[Geoms[geoId].index];
|
||||
p1.x = &MoveParameters.emplace_back(*l.p1.x);
|
||||
p1.y = &MoveParameters.emplace_back(*l.p1.y);
|
||||
p2.x = &MoveParameters.emplace_back(*l.p2.x);
|
||||
p2.y = &MoveParameters.emplace_back(*l.p2.y);
|
||||
GCSsys.addConstraintP2PCoincident(p1, l.p1, GCS::DefaultTemporaryConstraint);
|
||||
GCSsys.addConstraintP2PCoincident(p2, l.p2, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == Circle) {
|
||||
GCS::Point& center = Points[Geoms[geoId].midPointId];
|
||||
GCS::Point p0, p1;
|
||||
if (pos == PointPos::mid) {
|
||||
p0.x = &MoveParameters.emplace_back(*center.x);
|
||||
p0.y = &MoveParameters.emplace_back(*center.y);
|
||||
GCSsys.addConstraintP2PCoincident(p0, center, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
else if (pos == PointPos::none) {
|
||||
GCS::Arc& a = Arcs[Geoms[geoId].index];
|
||||
p0.x = &MoveParameters[0];
|
||||
p0.y = &MoveParameters[1];
|
||||
*p0.x = *center.x;
|
||||
*p0.y = *center.y + *a.rad;
|
||||
GCSsys.addConstraintPointOnArc(p0, a, GCS::DefaultTemporaryConstraint);
|
||||
// bool pole = GeometryFacade::isInternalType(Geoms[geoId].geo,
|
||||
// InternalType::BSplineControlPoint);
|
||||
GCS::Circle& c = Circles[Geoms[geoId].index];
|
||||
p0.x = &MoveParameters.emplace_back(*center.x);
|
||||
p0.y = &MoveParameters.emplace_back(*center.y + *c.rad);
|
||||
GCSsys.addConstraintPointOnCircle(p0, c, GCS::DefaultTemporaryConstraint);
|
||||
p1.x = &MoveParameters.emplace_back(*center.x);
|
||||
p1.y = &MoveParameters.emplace_back(*center.y);
|
||||
int i =
|
||||
GCSsys.addConstraintP2PCoincident(p1, center, GCS::DefaultTemporaryConstraint);
|
||||
GCSsys.rescaleConstraint(i - 1, 0.01);
|
||||
GCSsys.rescaleConstraint(i, 0.01);
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == Ellipse) {
|
||||
if (pos == PointPos::mid || pos == PointPos::none) {
|
||||
GCS::Point& center = Points[Geoms[geoId].midPointId];
|
||||
GCS::Point p0;
|
||||
p0.x = &MoveParameters.emplace_back(*center.x);
|
||||
p0.y = &MoveParameters.emplace_back(*center.y);
|
||||
GCSsys.addConstraintP2PCoincident(p0, center, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == ArcOfEllipse) {
|
||||
|
||||
GCS::Point& center = Points[Geoms[geoId].midPointId];
|
||||
GCS::Point p0, p1;
|
||||
if (pos == PointPos::mid || pos == PointPos::none) {
|
||||
p0.x = &MoveParameters.emplace_back(*center.x);
|
||||
p0.y = &MoveParameters.emplace_back(*center.y);
|
||||
GCSsys.addConstraintP2PCoincident(p0, center, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
else if (pos == PointPos::start || pos == PointPos::end) {
|
||||
if (pos == PointPos::start || pos == PointPos::end) {
|
||||
GCS::Point& p = (pos == PointPos::start) ? Points[Geoms[geoId].startPointId]
|
||||
: Points[Geoms[geoId].endPointId];
|
||||
|
||||
p0.x = &MoveParameters.emplace_back(*p.x);
|
||||
p0.y = &MoveParameters.emplace_back(*p.y);
|
||||
GCSsys.addConstraintP2PCoincident(p0, p, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
|
||||
p1.x = &MoveParameters.emplace_back(*center.x);
|
||||
p1.y = &MoveParameters.emplace_back(*center.y);
|
||||
|
||||
int i =
|
||||
GCSsys.addConstraintP2PCoincident(p1, center, GCS::DefaultTemporaryConstraint);
|
||||
GCSsys.rescaleConstraint(i - 1, 0.01);
|
||||
GCSsys.rescaleConstraint(i, 0.01);
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == ArcOfHyperbola) {
|
||||
GCS::Point& center = Points[Geoms[geoId].midPointId];
|
||||
GCS::Point p0, p1;
|
||||
if (pos == PointPos::mid || pos == PointPos::none) {
|
||||
p0.x = &MoveParameters.emplace_back(*center.x);
|
||||
p0.y = &MoveParameters.emplace_back(*center.y);
|
||||
GCSsys.addConstraintP2PCoincident(p0, center, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
else if (pos == PointPos::start || pos == PointPos::end) {
|
||||
GCS::Point& p = (pos == PointPos::start) ? Points[Geoms[geoId].startPointId]
|
||||
: Points[Geoms[geoId].endPointId];
|
||||
p0.x = &MoveParameters.emplace_back(*p.x);
|
||||
p0.y = &MoveParameters.emplace_back(*p.y);
|
||||
GCSsys.addConstraintP2PCoincident(p0, p, GCS::DefaultTemporaryConstraint);
|
||||
p1.x = &MoveParameters.emplace_back(*center.x);
|
||||
p1.y = &MoveParameters.emplace_back(*center.y);
|
||||
int i =
|
||||
GCSsys.addConstraintP2PCoincident(p1, center, GCS::DefaultTemporaryConstraint);
|
||||
GCSsys.rescaleConstraint(i - 1, 0.01);
|
||||
GCSsys.rescaleConstraint(i, 0.01);
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == ArcOfParabola) {
|
||||
GCS::Point& center = Points[Geoms[geoId].midPointId];
|
||||
GCS::Point p0, p1;
|
||||
if (pos == PointPos::mid || pos == PointPos::none) {
|
||||
p0.x = &MoveParameters.emplace_back(*center.x);
|
||||
p0.y = &MoveParameters.emplace_back(*center.y);
|
||||
GCSsys.addConstraintP2PCoincident(p0, center, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
else if (pos == PointPos::start || pos == PointPos::end) {
|
||||
GCS::Point& p = (pos == PointPos::start) ? Points[Geoms[geoId].startPointId]
|
||||
: Points[Geoms[geoId].endPointId];
|
||||
p0.x = &MoveParameters.emplace_back(*p.x);
|
||||
p0.y = &MoveParameters.emplace_back(*p.y);
|
||||
GCSsys.addConstraintP2PCoincident(p0, p, GCS::DefaultTemporaryConstraint);
|
||||
p1.x = &MoveParameters.emplace_back(*center.x);
|
||||
p1.y = &MoveParameters.emplace_back(*center.y);
|
||||
int i =
|
||||
GCSsys.addConstraintP2PCoincident(p1, center, GCS::DefaultTemporaryConstraint);
|
||||
GCSsys.rescaleConstraint(i - 1, 0.01);
|
||||
GCSsys.rescaleConstraint(i, 0.01);
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == BSpline) {
|
||||
if (pos == PointPos::start || pos == PointPos::end) {
|
||||
GCS::Point p0;
|
||||
GCS::Point& p = pos == PointPos::start ? Points[Geoms[geoId].startPointId]
|
||||
: Points[Geoms[geoId].endPointId];
|
||||
p0.x = &MoveParameters.emplace_back(*p.x);
|
||||
p0.y = &MoveParameters.emplace_back(*p.y);
|
||||
GCSsys.addConstraintP2PCoincident(p0, p, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
else if (pos == PointPos::none || pos == PointPos::mid) {
|
||||
GCS::BSpline& bsp = BSplines[Geoms[geoId].index];
|
||||
for (auto pole : bsp.poles) {
|
||||
GCS::Point p1;
|
||||
p1.x = &MoveParameters.emplace_back(*pole.x);
|
||||
p1.y = &MoveParameters.emplace_back(*pole.y);
|
||||
GCSsys.addConstraintP2PCoincident(p1, pole, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == Arc) {
|
||||
GCS::Point& center = Points[Geoms[geoId].midPointId];
|
||||
GCS::Point p0, p1;
|
||||
if (pos == PointPos::mid) {
|
||||
p0.x = &MoveParameters.emplace_back(*center.x);
|
||||
p0.y = &MoveParameters.emplace_back(*center.y);
|
||||
GCSsys.addConstraintP2PCoincident(p0, center, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
else if (pos == PointPos::none && moved.size() > 1) {
|
||||
// When group dragging, arcs should move without modification.
|
||||
GCS::Point p2;
|
||||
GCS::Point& sp = Points[Geoms[geoId].startPointId];
|
||||
GCS::Point& ep = Points[Geoms[geoId].endPointId];
|
||||
p0.x = &MoveParameters.emplace_back(*sp.x);
|
||||
p0.y = &MoveParameters.emplace_back(*sp.y);
|
||||
GCSsys.addConstraintP2PCoincident(p0, sp, GCS::DefaultTemporaryConstraint);
|
||||
|
||||
p2.x = &MoveParameters.emplace_back(*ep.x);
|
||||
p2.y = &MoveParameters.emplace_back(*ep.y);
|
||||
GCSsys.addConstraintP2PCoincident(p2, ep, GCS::DefaultTemporaryConstraint);
|
||||
|
||||
p1.x = &MoveParameters.emplace_back(*center.x);
|
||||
p1.y = &MoveParameters.emplace_back(*center.y);
|
||||
int i =
|
||||
GCSsys.addConstraintP2PCoincident(p1, center, GCS::DefaultTemporaryConstraint);
|
||||
GCSsys.rescaleConstraint(i - 2, 0.01);
|
||||
GCSsys.rescaleConstraint(i - 1, 0.01);
|
||||
GCSsys.rescaleConstraint(i, 0.01);
|
||||
}
|
||||
else if (pos == PointPos::start || pos == PointPos::end || pos == PointPos::none) {
|
||||
if (pos == PointPos::start || pos == PointPos::end) {
|
||||
GCS::Point& p = (pos == PointPos::start) ? Points[Geoms[geoId].startPointId]
|
||||
: Points[Geoms[geoId].endPointId];
|
||||
p0.x = &MoveParameters.emplace_back(*p.x);
|
||||
p0.y = &MoveParameters.emplace_back(*p.y);
|
||||
GCSsys.addConstraintP2PCoincident(p0, p, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
else if (pos == PointPos::none) {
|
||||
GCS::Arc& a = Arcs[Geoms[geoId].index];
|
||||
p0.x = &MoveParameters.emplace_back(*center.x);
|
||||
p0.y = &MoveParameters.emplace_back(*center.y + *a.rad);
|
||||
GCSsys.addConstraintPointOnArc(p0, a, GCS::DefaultTemporaryConstraint);
|
||||
}
|
||||
|
||||
p1.x = &MoveParameters.emplace_back(*center.x);
|
||||
p1.y = &MoveParameters.emplace_back(*center.y);
|
||||
int i =
|
||||
GCSsys.addConstraintP2PCoincident(p1, center, GCS::DefaultTemporaryConstraint);
|
||||
GCSsys.rescaleConstraint(i - 1, 0.01);
|
||||
GCSsys.rescaleConstraint(i, 0.01);
|
||||
}
|
||||
p1.x = &MoveParameters[2];
|
||||
p1.y = &MoveParameters[3];
|
||||
*p1.x = *center.x;
|
||||
*p1.y = *center.y;
|
||||
int i = GCSsys.addConstraintP2PCoincident(p1, center, GCS::DefaultTemporaryConstraint);
|
||||
GCSsys.rescaleConstraint(i - 1, 0.01);
|
||||
GCSsys.rescaleConstraint(i, 0.01);
|
||||
}
|
||||
}
|
||||
|
||||
InitParameters = MoveParameters;
|
||||
|
||||
GCSsys.initSolution();
|
||||
isInitMove = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Sketch::initMove(int geoId, PointPos pos, bool fine)
|
||||
{
|
||||
std::vector<GeoElementId> moved = {GeoElementId(geoId, pos)};
|
||||
return initMove(moved, fine);
|
||||
}
|
||||
|
||||
void Sketch::resetInitMove()
|
||||
{
|
||||
isInitMove = false;
|
||||
@@ -5140,17 +5093,15 @@ int Sketch::initBSplinePieceMove(int geoId,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Sketch::movePoint(int geoId, PointPos pos, Base::Vector3d toPoint, bool relative)
|
||||
int Sketch::movePoint(std::vector<GeoElementId> moved, Base::Vector3d toPoint, bool relative)
|
||||
{
|
||||
geoId = checkGeoId(geoId);
|
||||
|
||||
// don't try to move sketches that contain conflicting constraints
|
||||
if (hasConflicts()) {
|
||||
// don't try to move sketches that contain conflicting constraints
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!isInitMove) {
|
||||
initMove(geoId, pos);
|
||||
initMove(moved);
|
||||
initToPoint = toPoint;
|
||||
moveStep = 0;
|
||||
}
|
||||
@@ -5162,7 +5113,7 @@ int Sketch::movePoint(int geoId, PointPos pos, Base::Vector3d toPoint, bool rela
|
||||
else {
|
||||
// I am getting too far away from the original solution so reinit the solution
|
||||
if ((toPoint - initToPoint).Length() > 20 * moveStep) {
|
||||
initMove(geoId, pos);
|
||||
initMove(moved);
|
||||
initToPoint = toPoint;
|
||||
}
|
||||
}
|
||||
@@ -5170,92 +5121,82 @@ int Sketch::movePoint(int geoId, PointPos pos, Base::Vector3d toPoint, bool rela
|
||||
}
|
||||
|
||||
if (relative) {
|
||||
for (int i = 0; i < int(MoveParameters.size() - 1); i += 2) {
|
||||
for (size_t i = 0; i < MoveParameters.size() - 1; i += 2) {
|
||||
MoveParameters[i] = InitParameters[i] + toPoint.x;
|
||||
MoveParameters[i + 1] = InitParameters[i + 1] + toPoint.y;
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == Point) {
|
||||
if (pos == PointPos::start) {
|
||||
MoveParameters[0] = toPoint.x;
|
||||
MoveParameters[1] = toPoint.y;
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == Line) {
|
||||
if (pos == PointPos::start || pos == PointPos::end) {
|
||||
MoveParameters[0] = toPoint.x;
|
||||
MoveParameters[1] = toPoint.y;
|
||||
}
|
||||
else if (pos == PointPos::none || pos == PointPos::mid) {
|
||||
double dx = (InitParameters[2] - InitParameters[0]) / 2;
|
||||
double dy = (InitParameters[3] - InitParameters[1]) / 2;
|
||||
MoveParameters[0] = toPoint.x - dx;
|
||||
MoveParameters[1] = toPoint.y - dy;
|
||||
MoveParameters[2] = toPoint.x + dx;
|
||||
MoveParameters[3] = toPoint.y + dy;
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == Circle) {
|
||||
if (pos == PointPos::mid || pos == PointPos::none) {
|
||||
MoveParameters[0] = toPoint.x;
|
||||
MoveParameters[1] = toPoint.y;
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == Arc) {
|
||||
if (pos == PointPos::start || pos == PointPos::end || pos == PointPos::mid
|
||||
|| pos == PointPos::none) {
|
||||
MoveParameters[0] = toPoint.x;
|
||||
MoveParameters[1] = toPoint.y;
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == Ellipse) {
|
||||
if (pos == PointPos::mid || pos == PointPos::none) {
|
||||
MoveParameters[0] = toPoint.x;
|
||||
MoveParameters[1] = toPoint.y;
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == ArcOfEllipse) {
|
||||
if (pos == PointPos::start || pos == PointPos::end || pos == PointPos::mid
|
||||
|| pos == PointPos::none) {
|
||||
MoveParameters[0] = toPoint.x;
|
||||
MoveParameters[1] = toPoint.y;
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == ArcOfHyperbola) {
|
||||
if (pos == PointPos::start || pos == PointPos::end || pos == PointPos::mid
|
||||
|| pos == PointPos::none) {
|
||||
MoveParameters[0] = toPoint.x;
|
||||
MoveParameters[1] = toPoint.y;
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == ArcOfParabola) {
|
||||
if (pos == PointPos::start || pos == PointPos::end || pos == PointPos::mid
|
||||
|| pos == PointPos::none) {
|
||||
MoveParameters[0] = toPoint.x;
|
||||
MoveParameters[1] = toPoint.y;
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == BSpline) {
|
||||
if (pos == PointPos::start || pos == PointPos::end) {
|
||||
MoveParameters[0] = toPoint.x;
|
||||
MoveParameters[1] = toPoint.y;
|
||||
}
|
||||
else if (pos == PointPos::none || pos == PointPos::mid) {
|
||||
GCS::BSpline& bsp = BSplines[Geoms[geoId].index];
|
||||
|
||||
double cx = 0, cy = 0; // geometric center
|
||||
for (int i = 0; i < int(InitParameters.size() - 1); i += 2) {
|
||||
cx += InitParameters[i];
|
||||
cy += InitParameters[i + 1];
|
||||
else {
|
||||
size_t i = 0;
|
||||
for (auto& pair : moved) {
|
||||
if (i >= MoveParameters.size()) {
|
||||
break;
|
||||
}
|
||||
int geoId = checkGeoId(pair.GeoId);
|
||||
Sketcher::PointPos pos = pair.Pos;
|
||||
|
||||
cx /= bsp.poles.size();
|
||||
cy /= bsp.poles.size();
|
||||
if (Geoms[geoId].type == Point) {
|
||||
if (pos == PointPos::start) {
|
||||
MoveParameters[i] = toPoint.x;
|
||||
MoveParameters[i + 1] = toPoint.y;
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == Line) {
|
||||
if (pos == PointPos::start || pos == PointPos::end) {
|
||||
MoveParameters[i] = toPoint.x;
|
||||
MoveParameters[i + 1] = toPoint.y;
|
||||
i += 2;
|
||||
}
|
||||
else if (pos == PointPos::none || pos == PointPos::mid) {
|
||||
double dx = (InitParameters[i + 2] - InitParameters[i]) * 0.5;
|
||||
double dy = (InitParameters[i + 3] - InitParameters[i + 1]) * 0.5;
|
||||
MoveParameters[i] = toPoint.x - dx;
|
||||
MoveParameters[i + 1] = toPoint.y - dy;
|
||||
MoveParameters[i + 2] = toPoint.x + dx;
|
||||
MoveParameters[i + 3] = toPoint.y + dy;
|
||||
i += 4;
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == Circle || Geoms[geoId].type == Ellipse) {
|
||||
if (pos == PointPos::mid || pos == PointPos::none) {
|
||||
MoveParameters[i] = toPoint.x;
|
||||
MoveParameters[i + 1] = toPoint.y;
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
else if (Geoms[geoId].type == Arc || Geoms[geoId].type == ArcOfEllipse
|
||||
|| Geoms[geoId].type == ArcOfHyperbola || Geoms[geoId].type == ArcOfParabola) {
|
||||
MoveParameters[i] = toPoint.x;
|
||||
MoveParameters[i + 1] = toPoint.y;
|
||||
i += 2;
|
||||
}
|
||||
else if (Geoms[geoId].type == BSpline) {
|
||||
if (pos == PointPos::start || pos == PointPos::end) {
|
||||
MoveParameters[i] = toPoint.x;
|
||||
MoveParameters[i + 1] = toPoint.y;
|
||||
i += 2;
|
||||
}
|
||||
else if (pos == PointPos::none || pos == PointPos::mid) {
|
||||
GCS::BSpline& bsp = BSplines[Geoms[geoId].index];
|
||||
|
||||
for (int i = 0; i < int(MoveParameters.size() - 1); i += 2) {
|
||||
double cx = 0, cy = 0; // geometric center
|
||||
for (size_t j = 0; j < bsp.poles.size() * 2; j += 2) {
|
||||
cx += InitParameters[i + j];
|
||||
cy += InitParameters[i + j + 1];
|
||||
j += 2;
|
||||
}
|
||||
|
||||
MoveParameters[i] = toPoint.x + InitParameters[i] - cx;
|
||||
MoveParameters[i + 1] = toPoint.y + InitParameters[i + 1] - cy;
|
||||
cx /= bsp.poles.size();
|
||||
cy /= bsp.poles.size();
|
||||
|
||||
for (size_t j = 0; j < bsp.poles.size() * 2; j += 2) {
|
||||
MoveParameters[i + j] = toPoint.x + InitParameters[i + j] - cx;
|
||||
MoveParameters[i + j + 1] = toPoint.y + InitParameters[i + j + 1] - cy;
|
||||
j += 2;
|
||||
}
|
||||
i += bsp.poles.size() * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5263,6 +5204,12 @@ int Sketch::movePoint(int geoId, PointPos pos, Base::Vector3d toPoint, bool rela
|
||||
return solve();
|
||||
}
|
||||
|
||||
int Sketch::movePoint(int geoId, PointPos pos, Base::Vector3d toPoint, bool relative)
|
||||
{
|
||||
std::vector<GeoElementId> moved = {GeoElementId(geoId, pos)};
|
||||
return movePoint(moved, toPoint, relative);
|
||||
}
|
||||
|
||||
int Sketch::setDatum(int /*constrId*/, double /*value*/)
|
||||
{
|
||||
return -1;
|
||||
|
||||
@@ -161,6 +161,7 @@ public:
|
||||
/** initializes a point (or curve) drag by setting the current
|
||||
* sketch status as a reference
|
||||
*/
|
||||
int initMove(std::vector<GeoElementId> moved, bool fine = true);
|
||||
int initMove(int geoId, PointPos pos, bool fine = true);
|
||||
|
||||
/** Initializes a B-spline piece drag by setting the current
|
||||
@@ -184,6 +185,7 @@ public:
|
||||
* a condition for satisfying the new point location!
|
||||
* The relative flag permits moving relatively to the current position
|
||||
*/
|
||||
int movePoint(std::vector<GeoElementId> moved, Base::Vector3d toPoint, bool relative = false);
|
||||
int movePoint(int geoId, PointPos pos, Base::Vector3d toPoint, bool relative = false);
|
||||
|
||||
/**
|
||||
|
||||
@@ -1340,9 +1340,10 @@ int SketchObject::diagnoseAdditionalConstraints(
|
||||
return lastDoF;
|
||||
}
|
||||
|
||||
int SketchObject::movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toPoint, bool relative,
|
||||
int SketchObject::movePoint(std::vector<GeoElementId> moved, const Base::Vector3d& toPoint, bool relative,
|
||||
bool updateGeoBeforeMoving)
|
||||
{
|
||||
|
||||
// no need to check input data validity as this is an sketchobject managed operation.
|
||||
Base::StateLocker lock(managedoperation, true);
|
||||
|
||||
@@ -1369,7 +1370,7 @@ int SketchObject::movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toP
|
||||
return -1;
|
||||
|
||||
// move the point and solve
|
||||
lastSolverStatus = solvedSketch.movePoint(GeoId, PosId, toPoint, relative);
|
||||
lastSolverStatus = solvedSketch.movePoint(moved, toPoint, relative);
|
||||
|
||||
// moving the point can not result in a conflict that we did not have
|
||||
// or a redundancy that we did not have before, or a change of DoF
|
||||
@@ -1378,10 +1379,10 @@ int SketchObject::movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toP
|
||||
std::vector<Part::Geometry*> geomlist = solvedSketch.extractGeometry();
|
||||
Geometry.setValues(geomlist);
|
||||
// Constraints.acceptGeometry(getCompleteGeometry());
|
||||
for (std::vector<Part::Geometry*>::iterator it = geomlist.begin(); it != geomlist.end();
|
||||
++it) {
|
||||
if (*it)
|
||||
delete *it;
|
||||
for (auto* geo : geomlist) {
|
||||
if (geo){
|
||||
delete geo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1390,6 +1391,13 @@ int SketchObject::movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toP
|
||||
return lastSolverStatus;
|
||||
}
|
||||
|
||||
int SketchObject::movePoint(int geoId, PointPos pos, const Base::Vector3d& toPoint, bool relative,
|
||||
bool updateGeoBeforeMoving)
|
||||
{
|
||||
std::vector<GeoElementId> moved = { GeoElementId(geoId, pos) };
|
||||
return movePoint(moved, toPoint, relative, updateGeoBeforeMoving);
|
||||
}
|
||||
|
||||
template <>
|
||||
Base::Vector3d SketchObject::getPointForGeometry<>(const Part::GeomPoint *geomPoint, PointPos PosId)
|
||||
{
|
||||
|
||||
@@ -352,6 +352,10 @@ public:
|
||||
/// toggle the driving status of this constraint
|
||||
int toggleVirtualSpace(int ConstrId);
|
||||
/// move this point to a new location and solve
|
||||
int movePoint(std::vector<GeoElementId> moved,
|
||||
const Base::Vector3d& toPoint,
|
||||
bool relative = false,
|
||||
bool updateGeoBeforeMoving = false);
|
||||
int movePoint(int GeoId,
|
||||
PointPos PosId,
|
||||
const Base::Vector3d& toPoint,
|
||||
@@ -687,6 +691,8 @@ public: /* Solver exposed interface */
|
||||
}
|
||||
/// Forwards a request for a temporary initMove to the solver using the current sketch state as
|
||||
/// a reference (enables dragging)
|
||||
|
||||
inline int initTemporaryMove(std::vector<GeoElementId> moved, bool fine = true);
|
||||
inline int initTemporaryMove(int geoId, PointPos pos, bool fine = true);
|
||||
/// Forwards a request for a temporary initBSplinePieceMove to the solver using the current
|
||||
/// sketch state as a reference (enables dragging)
|
||||
@@ -698,6 +704,9 @@ public: /* Solver exposed interface */
|
||||
* state as a reference (enables dragging). NOTE: A temporary move operation must always be
|
||||
* preceded by a initTemporaryMove() operation.
|
||||
*/
|
||||
inline int moveTemporaryPoint(std::vector<GeoElementId> moved,
|
||||
Base::Vector3d toPoint,
|
||||
bool relative = false);
|
||||
inline int
|
||||
moveTemporaryPoint(int geoId, PointPos pos, Base::Vector3d toPoint, bool relative = false);
|
||||
/// forwards a request to update an extension of a geometry of the solver to the solver.
|
||||
@@ -1061,16 +1070,19 @@ private:
|
||||
mutable std::map<std::string, std::string> internalElementMap;
|
||||
};
|
||||
|
||||
inline int SketchObject::initTemporaryMove(int geoId, PointPos pos, bool fine /*=true*/)
|
||||
inline int SketchObject::initTemporaryMove(std::vector<GeoElementId> moved, bool fine /*=true*/)
|
||||
{
|
||||
// if a previous operation did not update the geometry (including geometry extensions)
|
||||
// or constraints (including any deleted pointer, as in renameConstraint) of the solver,
|
||||
// here we update them before starting a temporary operation.
|
||||
if (solverNeedsUpdate) {
|
||||
solve();
|
||||
}
|
||||
|
||||
return solvedSketch.initMove(geoId, pos, fine);
|
||||
return solvedSketch.initMove(moved, fine);
|
||||
}
|
||||
|
||||
inline int SketchObject::initTemporaryMove(int geoId, PointPos pos, bool fine /*=true*/)
|
||||
{
|
||||
std::vector<GeoElementId> moved = {GeoElementId(geoId, pos)};
|
||||
return initTemporaryMove(moved, fine);
|
||||
}
|
||||
|
||||
inline int SketchObject::initTemporaryBSplinePieceMove(int geoId,
|
||||
@@ -1088,12 +1100,19 @@ inline int SketchObject::initTemporaryBSplinePieceMove(int geoId,
|
||||
return solvedSketch.initBSplinePieceMove(geoId, pos, firstPoint, fine);
|
||||
}
|
||||
|
||||
inline int SketchObject::moveTemporaryPoint(std::vector<GeoElementId> moved,
|
||||
Base::Vector3d toPoint,
|
||||
bool relative /*=false*/)
|
||||
{
|
||||
return solvedSketch.movePoint(moved, toPoint, relative);
|
||||
}
|
||||
inline int SketchObject::moveTemporaryPoint(int geoId,
|
||||
PointPos pos,
|
||||
Base::Vector3d toPoint,
|
||||
bool relative /*=false*/)
|
||||
{
|
||||
return solvedSketch.movePoint(geoId, pos, toPoint, relative);
|
||||
std::vector<GeoElementId> moved = {GeoElementId(geoId, pos)};
|
||||
return moveTemporaryPoint(moved, toPoint, relative);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -528,6 +528,22 @@ setLabelDistance(constraintIndex:int, value:float)
|
||||
</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="moveGeometries">
|
||||
<Documentation>
|
||||
<UserDocu>
|
||||
moveGeometries(Geos,Vector,[relative]) - move given points and curves
|
||||
to another location.
|
||||
It moves the specified points and curves to the given location by adding some
|
||||
temporary weak constraints and solve the sketch.
|
||||
This method is mostly used to allow the user to drag some portions of the sketch
|
||||
in real time by e.g. the mouse and it works only for underconstrained portions of
|
||||
the sketch.
|
||||
The argument 'relative', if present, states if the new location is given
|
||||
relatively to the current one. For group dragging this is enforced.
|
||||
Geos is a vector of pairs of geoId and posId.
|
||||
</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getPoint" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>
|
||||
|
||||
@@ -1167,6 +1167,58 @@ PyObject* SketchObjectPy::setLabelDistance(PyObject* args)
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyObject* SketchObjectPy::moveGeometries(PyObject* args)
|
||||
{
|
||||
PyObject* pyList;
|
||||
PyObject* pcObj;
|
||||
int relative = 0;
|
||||
|
||||
// Parse arguments: list of pairs, Base::VectorPy, optional relative flag
|
||||
if (!PyArg_ParseTuple(args,
|
||||
"O!O!|i",
|
||||
&PyList_Type,
|
||||
&pyList, // List of pairs (geoId, pointPos)
|
||||
&(Base::VectorPy::Type),
|
||||
&pcObj, // Target vector
|
||||
&relative)) { // Optional relative flag
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Convert Python list to std::vector<GeoElementId>
|
||||
std::vector<GeoElementId> moved;
|
||||
Py_ssize_t listSize = PyList_Size(pyList);
|
||||
|
||||
for (Py_ssize_t i = 0; i < listSize; ++i) {
|
||||
PyObject* pyPair = PyList_GetItem(pyList, i); // Borrowed reference
|
||||
|
||||
if (!PyTuple_Check(pyPair) || PyTuple_Size(pyPair) != 2) {
|
||||
PyErr_SetString(PyExc_ValueError, "List must contain pairs (geoId, pointPos).");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int geoId = PyLong_AsLong(PyTuple_GetItem(pyPair, 0));
|
||||
int pointPos = PyLong_AsLong(PyTuple_GetItem(pyPair, 1));
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_SetString(PyExc_ValueError, "Invalid geoId or pointPos in the list.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
moved.emplace_back(GeoElementId(geoId, static_cast<Sketcher::PointPos>(pointPos)));
|
||||
}
|
||||
|
||||
// Convert Python vector to Base::Vector3d
|
||||
Base::Vector3d v1 = static_cast<Base::VectorPy*>(pcObj)->value();
|
||||
|
||||
// Call the C++ method
|
||||
if (this->getSketchObjectPtr()->movePoint(moved, v1, (relative > 0))) {
|
||||
PyErr_SetString(PyExc_ValueError, "Failed to move geometries.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyObject* SketchObjectPy::movePoint(PyObject* args)
|
||||
{
|
||||
PyObject* pcObj;
|
||||
|
||||
@@ -715,8 +715,8 @@ void ViewProviderSketch::ensureFocus()
|
||||
void ViewProviderSketch::preselectAtPoint(Base::Vector2d point)
|
||||
{
|
||||
if (Mode != STATUS_SELECT_Point && Mode != STATUS_SELECT_Edge
|
||||
&& Mode != STATUS_SELECT_Constraint && Mode != STATUS_SKETCH_DragPoint
|
||||
&& Mode != STATUS_SKETCH_DragCurve && Mode != STATUS_SKETCH_DragConstraint
|
||||
&& Mode != STATUS_SELECT_Constraint && Mode != STATUS_SKETCH_Drag
|
||||
&& Mode != STATUS_SKETCH_DragConstraint
|
||||
&& Mode != STATUS_SKETCH_UseRubberBand) {
|
||||
|
||||
Gui::MDIView* mdi = this->getActiveView();
|
||||
@@ -766,24 +766,9 @@ bool ViewProviderSketch::keyPressed(bool pressed, int key)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (isInEditMode() && drag.isDragCurveValid()) {
|
||||
if (isInEditMode() && !drag.Dragged.empty()) {
|
||||
if (!pressed) {
|
||||
getSketchObject()->movePoint(
|
||||
drag.DragCurve, Sketcher::PointPos::none, Base::Vector3d(0, 0, 0), true);
|
||||
drag.DragCurve = Drag::InvalidCurve;
|
||||
resetPositionText();
|
||||
Mode = STATUS_NONE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (isInEditMode() && drag.isDragPointValid()) {
|
||||
if (!pressed) {
|
||||
int GeoId;
|
||||
Sketcher::PointPos PosId;
|
||||
getSketchObject()->getGeoVertexIndex(drag.DragPoint, GeoId, PosId);
|
||||
getSketchObject()->movePoint(GeoId, PosId, Base::Vector3d(0, 0, 0), true);
|
||||
drag.DragPoint = Drag::InvalidPoint;
|
||||
resetPositionText();
|
||||
commitDragMove(drag.xInit, drag.yInit);
|
||||
Mode = STATUS_NONE;
|
||||
}
|
||||
return true;
|
||||
@@ -1053,111 +1038,8 @@ bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVe
|
||||
}
|
||||
Mode = STATUS_NONE;
|
||||
return true;
|
||||
case STATUS_SKETCH_DragPoint:
|
||||
if (drag.isDragPointValid()) {
|
||||
int GeoId;
|
||||
Sketcher::PointPos PosId;
|
||||
|
||||
getSketchObject()->getGeoVertexIndex(drag.DragPoint, GeoId, PosId);
|
||||
|
||||
if (GeoId != Sketcher::GeoEnum::GeoUndef
|
||||
&& PosId != Sketcher::PointPos::none) {
|
||||
getDocument()->openCommand(QT_TRANSLATE_NOOP("Command", "Drag Point"));
|
||||
try {
|
||||
Gui::cmdAppObjectArgs(getObject(),
|
||||
"movePoint(%d,%d,App.Vector(%f,%f,0),%d)",
|
||||
GeoId,
|
||||
static_cast<int>(PosId),
|
||||
x - drag.xInit,
|
||||
y - drag.yInit,
|
||||
0);
|
||||
|
||||
getDocument()->commitCommand();
|
||||
|
||||
tryAutoRecomputeIfNotSolve(getSketchObject());
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
getDocument()->abortCommand();
|
||||
Base::Console().DeveloperError(
|
||||
"ViewProviderSketch", "Drag point: %s\n", e.what());
|
||||
}
|
||||
}
|
||||
setPreselectPoint(drag.DragPoint);
|
||||
drag.DragPoint = Drag::InvalidPoint;
|
||||
}
|
||||
resetPositionText();
|
||||
Mode = STATUS_NONE;
|
||||
return true;
|
||||
case STATUS_SKETCH_DragCurve:
|
||||
if (drag.isDragCurveValid()) {
|
||||
const Part::Geometry* geo = getSketchObject()->getGeometry(drag.DragCurve);
|
||||
if (geo->is<Part::GeomLineSegment>()
|
||||
|| geo->is<Part::GeomArcOfCircle>()
|
||||
|| geo->is<Part::GeomCircle>()
|
||||
|| geo->is<Part::GeomEllipse>()
|
||||
|| geo->is<Part::GeomArcOfEllipse>()
|
||||
|| geo->is<Part::GeomArcOfParabola>()
|
||||
|| geo->is<Part::GeomArcOfHyperbola>()
|
||||
|| geo->is<Part::GeomBSplineCurve>()) {
|
||||
getDocument()->openCommand(QT_TRANSLATE_NOOP("Command", "Drag Curve"));
|
||||
|
||||
auto geo = getSketchObject()->getGeometry(drag.DragCurve);
|
||||
auto gf = GeometryFacade::getFacade(geo);
|
||||
|
||||
Base::Vector3d vec(x - drag.xInit, y - drag.yInit, 0);
|
||||
|
||||
// BSpline weights have a radius corresponding to the weight value
|
||||
// However, in order for them proportional to the B-Spline size,
|
||||
// the scenograph has a size scalefactor times the weight
|
||||
// This code normalizes the information sent to the solver.
|
||||
if (gf->getInternalType() == InternalType::BSplineControlPoint) {
|
||||
auto circle = static_cast<const Part::GeomCircle*>(geo);
|
||||
Base::Vector3d center = circle->getCenter();
|
||||
|
||||
Base::Vector3d dir = vec - center;
|
||||
|
||||
double scalefactor = 1.0;
|
||||
|
||||
if (circle->hasExtension(
|
||||
SketcherGui::ViewProviderSketchGeometryExtension::
|
||||
getClassTypeId())) {
|
||||
auto vpext = std::static_pointer_cast<
|
||||
const SketcherGui::ViewProviderSketchGeometryExtension>(
|
||||
circle
|
||||
->getExtension(
|
||||
SketcherGui::ViewProviderSketchGeometryExtension::
|
||||
getClassTypeId())
|
||||
.lock());
|
||||
|
||||
scalefactor = vpext->getRepresentationFactor();
|
||||
}
|
||||
|
||||
vec = center + dir / scalefactor;
|
||||
}
|
||||
|
||||
try {
|
||||
Gui::cmdAppObjectArgs(getObject(),
|
||||
"movePoint(%d,%d,App.Vector(%f,%f,0),%d)",
|
||||
drag.DragCurve,
|
||||
static_cast<int>(Sketcher::PointPos::none),
|
||||
vec.x,
|
||||
vec.y,
|
||||
drag.relative ? 1 : 0);
|
||||
|
||||
getDocument()->commitCommand();
|
||||
|
||||
tryAutoRecomputeIfNotSolve(getSketchObject());
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
getDocument()->abortCommand();
|
||||
Base::Console().DeveloperError(
|
||||
"ViewProviderSketch", "Drag curve: %s\n", e.what());
|
||||
}
|
||||
}
|
||||
preselection.PreselectCurve = drag.DragCurve;
|
||||
drag.DragCurve = Drag::InvalidCurve;
|
||||
}
|
||||
resetPositionText();
|
||||
case STATUS_SKETCH_Drag:
|
||||
commitDragMove(x, y);
|
||||
Mode = STATUS_NONE;
|
||||
return true;
|
||||
case STATUS_SKETCH_DragConstraint:
|
||||
@@ -1313,8 +1195,7 @@ bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVe
|
||||
generateContextMenu();
|
||||
return true;
|
||||
}
|
||||
case STATUS_SKETCH_DragPoint:
|
||||
case STATUS_SKETCH_DragCurve:
|
||||
case STATUS_SKETCH_Drag:
|
||||
case STATUS_SKETCH_DragConstraint:
|
||||
case STATUS_SKETCH_StartRubberBand:
|
||||
case STATUS_SKETCH_UseRubberBand:
|
||||
@@ -1487,9 +1368,8 @@ bool ViewProviderSketch::mouseMove(const SbVec2s& cursorPos, Gui::View3DInventor
|
||||
|
||||
bool preselectChanged = false;
|
||||
if (Mode != STATUS_SELECT_Point && Mode != STATUS_SELECT_Edge
|
||||
&& Mode != STATUS_SELECT_Constraint && Mode != STATUS_SKETCH_DragPoint
|
||||
&& Mode != STATUS_SKETCH_DragCurve && Mode != STATUS_SKETCH_DragConstraint
|
||||
&& Mode != STATUS_SKETCH_UseRubberBand) {
|
||||
&& Mode != STATUS_SELECT_Constraint && Mode != STATUS_SKETCH_Drag
|
||||
&& Mode != STATUS_SKETCH_DragConstraint && Mode != STATUS_SKETCH_UseRubberBand) {
|
||||
|
||||
std::unique_ptr<SoPickedPoint> Point(this->getPointOnRay(cursorPos, viewer));
|
||||
|
||||
@@ -1505,19 +1385,12 @@ bool ViewProviderSketch::mouseMove(const SbVec2s& cursorPos, Gui::View3DInventor
|
||||
}
|
||||
return false;
|
||||
case STATUS_SELECT_Point:
|
||||
if (!getSolvedSketch().hasConflicts() && preselection.isPreselectPointValid()
|
||||
&& drag.DragPoint != preselection.PreselectPoint) {
|
||||
Mode = STATUS_SKETCH_DragPoint;
|
||||
drag.DragPoint = preselection.PreselectPoint;
|
||||
int GeoId;
|
||||
Sketcher::PointPos PosId;
|
||||
if (!getSolvedSketch().hasConflicts() && preselection.isPreselectPointValid()) {
|
||||
int geoId;
|
||||
Sketcher::PointPos pos;
|
||||
getSketchObject()->getGeoVertexIndex(preselection.PreselectPoint, geoId, pos);
|
||||
|
||||
getSketchObject()->getGeoVertexIndex(drag.DragPoint, GeoId, PosId);
|
||||
|
||||
if (GeoId != Sketcher::GeoEnum::GeoUndef && PosId != Sketcher::PointPos::none) {
|
||||
getSketchObject()->initTemporaryMove(GeoId, PosId, false);
|
||||
drag.resetVector();
|
||||
}
|
||||
initDragging(geoId, pos, viewer);
|
||||
}
|
||||
else {
|
||||
Mode = STATUS_NONE;
|
||||
@@ -1525,107 +1398,11 @@ bool ViewProviderSketch::mouseMove(const SbVec2s& cursorPos, Gui::View3DInventor
|
||||
resetPreselectPoint();
|
||||
return true;
|
||||
case STATUS_SELECT_Edge:
|
||||
if (!getSolvedSketch().hasConflicts() && preselection.isPreselectCurveValid()
|
||||
&& drag.DragCurve != preselection.PreselectCurve) {
|
||||
Mode = STATUS_SKETCH_DragCurve;
|
||||
drag.DragCurve = preselection.PreselectCurve;
|
||||
const Part::Geometry* geo = getSketchObject()->getGeometry(drag.DragCurve);
|
||||
if (!getSolvedSketch().hasConflicts() && preselection.isPreselectCurveValid()) {
|
||||
int geoId = preselection.PreselectCurve;
|
||||
Sketcher::PointPos pos = Sketcher::PointPos::none;
|
||||
|
||||
// BSpline Control points are edge draggable only if their radius is movable
|
||||
// This is because dragging gives unwanted cosmetic results due to the scale ratio.
|
||||
// This is an heuristic as it does not check all indirect routes.
|
||||
if (GeometryFacade::isInternalType(geo, InternalType::BSplineControlPoint)) {
|
||||
if (geo->hasExtension(Sketcher::SolverGeometryExtension::getClassTypeId())) {
|
||||
auto solvext =
|
||||
std::static_pointer_cast<const Sketcher::SolverGeometryExtension>(
|
||||
geo->getExtension(
|
||||
Sketcher::SolverGeometryExtension::getClassTypeId())
|
||||
.lock());
|
||||
|
||||
// Edge parameters are Independent, so weight won't move
|
||||
if (solvext->getEdge() == Sketcher::SolverGeometryExtension::Independent) {
|
||||
Mode = STATUS_NONE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// The B-Spline is constrained to be non-rational (equal weights), moving
|
||||
// produces a bad effect because OCCT will normalize the values of the
|
||||
// weights.
|
||||
auto grp = getSolvedSketch().getDependencyGroup(drag.DragCurve,
|
||||
Sketcher::PointPos::none);
|
||||
|
||||
int bsplinegeoid = -1;
|
||||
|
||||
std::vector<int> polegeoids;
|
||||
|
||||
for (auto c : getSketchObject()->Constraints.getValues()) {
|
||||
if (c->Type == Sketcher::InternalAlignment
|
||||
&& c->AlignmentType == BSplineControlPoint
|
||||
&& c->First == drag.DragCurve) {
|
||||
|
||||
bsplinegeoid = c->Second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bsplinegeoid == -1) {
|
||||
Mode = STATUS_NONE;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto c : getSketchObject()->Constraints.getValues()) {
|
||||
if (c->Type == Sketcher::InternalAlignment
|
||||
&& c->AlignmentType == BSplineControlPoint
|
||||
&& c->Second == bsplinegeoid) {
|
||||
|
||||
polegeoids.push_back(c->First);
|
||||
}
|
||||
}
|
||||
|
||||
bool allingroup = true;
|
||||
|
||||
for (auto polegeoid : polegeoids) {
|
||||
std::pair<int, Sketcher::PointPos> thispole =
|
||||
std::make_pair(polegeoid, Sketcher::PointPos::none);
|
||||
|
||||
if (grp.find(thispole) == grp.end())// not found
|
||||
allingroup = false;
|
||||
}
|
||||
|
||||
if (allingroup) {// it is constrained to be non-rational
|
||||
Mode = STATUS_NONE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (geo->is<Part::GeomLineSegment>()
|
||||
|| geo->is<Part::GeomBSplineCurve>()) {
|
||||
drag.relative = true;
|
||||
|
||||
// Since the cursor moved from where it was clicked, and this is a relative
|
||||
// move, calculate the click position and use it as initial point.
|
||||
SbLine line2;
|
||||
getProjectingLine(DoubleClick::prvCursorPos, viewer, line2);
|
||||
getCoordsOnSketchPlane(
|
||||
line2.getPosition(), line2.getDirection(), drag.xInit, drag.yInit);
|
||||
snapManager->snap(drag.xInit, drag.yInit);
|
||||
}
|
||||
else {
|
||||
drag.resetVector();
|
||||
}
|
||||
|
||||
if (geo->is<Part::GeomBSplineCurve>()) {
|
||||
getSketchObject()->initTemporaryBSplinePieceMove(
|
||||
drag.DragCurve,
|
||||
Sketcher::PointPos::none,
|
||||
Base::Vector3d(drag.xInit, drag.yInit, 0.0),
|
||||
false);
|
||||
}
|
||||
else {
|
||||
getSketchObject()->initTemporaryMove(
|
||||
drag.DragCurve, Sketcher::PointPos::none, false);
|
||||
}
|
||||
initDragging(geoId, pos, viewer);
|
||||
}
|
||||
else {
|
||||
Mode = STATUS_NONE;
|
||||
@@ -1639,64 +1416,10 @@ bool ViewProviderSketch::mouseMove(const SbVec2s& cursorPos, Gui::View3DInventor
|
||||
drag.yInit = y;
|
||||
resetPreselectPoint();
|
||||
return true;
|
||||
case STATUS_SKETCH_DragPoint:
|
||||
if (drag.isDragPointValid()) {
|
||||
// Base::Console().Log("Drag Point:%d\n",edit->DragPoint);
|
||||
int GeoId;
|
||||
Sketcher::PointPos PosId;
|
||||
getSketchObject()->getGeoVertexIndex(drag.DragPoint, GeoId, PosId);
|
||||
Base::Vector3d vec(x, y, 0);
|
||||
|
||||
if (GeoId != Sketcher::GeoEnum::GeoUndef && PosId != Sketcher::PointPos::none) {
|
||||
if (getSketchObject()->moveTemporaryPoint(GeoId, PosId, vec, false) == 0) {
|
||||
setPositionText(Base::Vector2d(x, y));
|
||||
draw(true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case STATUS_SKETCH_DragCurve:
|
||||
if (drag.isDragCurveValid()) {
|
||||
auto geo = getSketchObject()->getGeometry(drag.DragCurve);
|
||||
auto gf = GeometryFacade::getFacade(geo);
|
||||
|
||||
Base::Vector3d vec(x - drag.xInit, y - drag.yInit, 0);
|
||||
|
||||
// BSpline weights have a radius corresponding to the weight value
|
||||
// However, in order for them proportional to the B-Spline size,
|
||||
// the scenograph has a size scalefactor times the weight
|
||||
// This code normalizes the information sent to the solver.
|
||||
if (gf->getInternalType() == InternalType::BSplineControlPoint) {
|
||||
auto circle = static_cast<const Part::GeomCircle*>(geo);
|
||||
Base::Vector3d center = circle->getCenter();
|
||||
|
||||
Base::Vector3d dir = vec - center;
|
||||
|
||||
double scalefactor = 1.0;
|
||||
|
||||
if (circle->hasExtension(
|
||||
SketcherGui::ViewProviderSketchGeometryExtension::getClassTypeId())) {
|
||||
auto vpext = std::static_pointer_cast<
|
||||
const SketcherGui::ViewProviderSketchGeometryExtension>(
|
||||
circle
|
||||
->getExtension(SketcherGui::ViewProviderSketchGeometryExtension::
|
||||
getClassTypeId())
|
||||
.lock());
|
||||
|
||||
scalefactor = vpext->getRepresentationFactor();
|
||||
}
|
||||
|
||||
vec = center + dir / scalefactor;
|
||||
}
|
||||
|
||||
if (getSketchObject()->moveTemporaryPoint(
|
||||
drag.DragCurve, Sketcher::PointPos::none, vec, drag.relative)
|
||||
== 0) {
|
||||
setPositionText(Base::Vector2d(x, y));
|
||||
draw(true, false);
|
||||
}
|
||||
}
|
||||
case STATUS_SKETCH_Drag: {
|
||||
doDragStep(x, y);
|
||||
return true;
|
||||
}
|
||||
case STATUS_SKETCH_DragConstraint:
|
||||
if (!drag.DragConstraintSet.empty()) {
|
||||
auto idset = drag.DragConstraintSet;
|
||||
@@ -1738,6 +1461,291 @@ bool ViewProviderSketch::mouseMove(const SbVec2s& cursorPos, Gui::View3DInventor
|
||||
return false;
|
||||
}
|
||||
|
||||
void ViewProviderSketch::initDragging(int geoId, Sketcher::PointPos pos, Gui::View3DInventorViewer* viewer)
|
||||
{
|
||||
if (geoId < 0) {
|
||||
return; // don't drag externals
|
||||
}
|
||||
|
||||
drag.reset();
|
||||
Mode = STATUS_SKETCH_Drag;
|
||||
drag.Dragged.push_back(GeoElementId(geoId, pos));
|
||||
|
||||
// Adding selected geos that should be dragged as well.
|
||||
for (auto& geoIdi : selection.SelCurvSet) {
|
||||
if (geoIdi < 0) {
|
||||
continue; //skip externals
|
||||
}
|
||||
|
||||
if (geoIdi == geoId) {
|
||||
// geoId is already added because it was the preselected.
|
||||
// 2 cases : either the edge was added or a point of it.
|
||||
// If its a point then we replace it by the edge.
|
||||
// If it's the edge it's replaced by itself so it's ok.
|
||||
drag.Dragged[0].Pos = Sketcher::PointPos::none;
|
||||
}
|
||||
else {
|
||||
// For group dragging, we skip the internal geos.
|
||||
const Part::Geometry* geo = getSketchObject()->getGeometry(geoId);
|
||||
if (!GeometryFacade::isInternalAligned(geo)) {
|
||||
drag.Dragged.push_back(GeoElementId(geoIdi));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto& pointId : selection.SelPointSet) {
|
||||
int geoIdi;
|
||||
Sketcher::PointPos posi;
|
||||
getSketchObject()->getGeoVertexIndex(pointId, geoIdi, posi);
|
||||
if (geoIdi < 0) {
|
||||
continue; //skip externals
|
||||
}
|
||||
|
||||
bool add = true;
|
||||
for (auto& pair : drag.Dragged) {
|
||||
int geoIdj = pair.GeoId;
|
||||
Sketcher::PointPos posj = pair.Pos;
|
||||
if (geoIdi == geoIdj && (posi == posj || posj == Sketcher::PointPos::none)) {
|
||||
add = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (add) {
|
||||
drag.Dragged.push_back(GeoElementId(geoIdi, posi));
|
||||
}
|
||||
}
|
||||
|
||||
auto setRelative = [&]() {
|
||||
drag.relative = true;
|
||||
|
||||
// Calculate the click position and use it as the initial point
|
||||
SbLine line2;
|
||||
getProjectingLine(DoubleClick::prvCursorPos, viewer, line2);
|
||||
getCoordsOnSketchPlane(
|
||||
line2.getPosition(), line2.getDirection(), drag.xInit, drag.yInit);
|
||||
snapManager->snap(drag.xInit, drag.yInit);
|
||||
};
|
||||
|
||||
if (drag.Dragged.size() == 1 && pos == Sketcher::PointPos::none) {
|
||||
const Part::Geometry* geo = getSketchObject()->getGeometry(geoId);
|
||||
|
||||
// BSpline Control points are edge draggable only if their radius is movable
|
||||
// This is because dragging gives unwanted cosmetic results due to the scale ratio.
|
||||
// This is an heuristic as it does not check all indirect routes.
|
||||
if (GeometryFacade::isInternalType(geo, InternalType::BSplineControlPoint)) {
|
||||
if (geo->hasExtension(Sketcher::SolverGeometryExtension::getClassTypeId())) {
|
||||
auto solvext =
|
||||
std::static_pointer_cast<const Sketcher::SolverGeometryExtension>(
|
||||
geo->getExtension(
|
||||
Sketcher::SolverGeometryExtension::getClassTypeId())
|
||||
.lock());
|
||||
|
||||
// Edge parameters are Independent, so weight won't move
|
||||
if (solvext->getEdge() == Sketcher::SolverGeometryExtension::Independent) {
|
||||
Mode = STATUS_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
// The B-Spline is constrained to be non-rational (equal weights), moving
|
||||
// produces a bad effect because OCCT will normalize the values of the
|
||||
// weights.
|
||||
auto grp = getSolvedSketch().getDependencyGroup(geoId,
|
||||
Sketcher::PointPos::none);
|
||||
|
||||
int bsplinegeoid = -1;
|
||||
|
||||
std::vector<int> polegeoids;
|
||||
|
||||
for (auto c : getSketchObject()->Constraints.getValues()) {
|
||||
if (c->Type == Sketcher::InternalAlignment
|
||||
&& c->AlignmentType == BSplineControlPoint
|
||||
&& c->First == geoId) {
|
||||
|
||||
bsplinegeoid = c->Second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bsplinegeoid == -1) {
|
||||
Mode = STATUS_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto c : getSketchObject()->Constraints.getValues()) {
|
||||
if (c->Type == Sketcher::InternalAlignment
|
||||
&& c->AlignmentType == BSplineControlPoint
|
||||
&& c->Second == bsplinegeoid) {
|
||||
|
||||
polegeoids.push_back(c->First);
|
||||
}
|
||||
}
|
||||
|
||||
bool allingroup = true;
|
||||
|
||||
for (auto polegeoid : polegeoids) {
|
||||
std::pair<int, Sketcher::PointPos> thispole =
|
||||
std::make_pair(polegeoid, Sketcher::PointPos::none);
|
||||
|
||||
if (grp.find(thispole) == grp.end())// not found
|
||||
allingroup = false;
|
||||
}
|
||||
|
||||
if (allingroup) {// it is constrained to be non-rational
|
||||
Mode = STATUS_NONE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (geo->is<Part::GeomLineSegment>() || geo->is<Part::GeomBSplineCurve>()) {
|
||||
setRelative();
|
||||
}
|
||||
|
||||
if (geo->is<Part::GeomBSplineCurve>()) {
|
||||
getSketchObject()->initTemporaryBSplinePieceMove(
|
||||
geoId,
|
||||
Sketcher::PointPos::none,
|
||||
Base::Vector3d(drag.xInit, drag.yInit, 0.0),
|
||||
false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (drag.Dragged.size() > 1) {
|
||||
setRelative();
|
||||
}
|
||||
|
||||
getSketchObject()->initTemporaryMove(drag.Dragged, false);
|
||||
}
|
||||
|
||||
void ViewProviderSketch::doDragStep(double x, double y)
|
||||
{
|
||||
Base::Vector3d vec(x - drag.xInit, y - drag.yInit, 0);
|
||||
|
||||
if (drag.Dragged.size() == 1) {
|
||||
// special single bspline point handling.
|
||||
Sketcher::PointPos PosId = drag.Dragged[0].Pos;
|
||||
|
||||
if (PosId == Sketcher::PointPos::none) {
|
||||
int GeoId = drag.Dragged[0].GeoId;
|
||||
auto geo = getSketchObject()->getGeometry(GeoId);
|
||||
auto gf = GeometryFacade::getFacade(geo);
|
||||
|
||||
// BSpline weights have a radius corresponding to the weight value
|
||||
// However, in order for them proportional to the B-Spline size,
|
||||
// the scenograph has a size scalefactor times the weight
|
||||
// This code normalizes the information sent to the solver.
|
||||
if (gf->getInternalType() == InternalType::BSplineControlPoint) {
|
||||
auto circle = static_cast<const Part::GeomCircle*>(geo);
|
||||
Base::Vector3d center = circle->getCenter();
|
||||
|
||||
Base::Vector3d dir = vec - center;
|
||||
|
||||
double scalefactor = 1.0;
|
||||
|
||||
if (circle->hasExtension(
|
||||
SketcherGui::ViewProviderSketchGeometryExtension::getClassTypeId())) {
|
||||
auto vpext = std::static_pointer_cast<
|
||||
const SketcherGui::ViewProviderSketchGeometryExtension>(
|
||||
circle
|
||||
->getExtension(SketcherGui::ViewProviderSketchGeometryExtension::
|
||||
getClassTypeId())
|
||||
.lock());
|
||||
|
||||
scalefactor = vpext->getRepresentationFactor();
|
||||
}
|
||||
|
||||
vec = center + dir / scalefactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getSketchObject()->moveTemporaryPoint(drag.Dragged, vec, drag.relative) == 0) {
|
||||
setPositionText(Base::Vector2d(x, y));
|
||||
draw(true, false);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewProviderSketch::commitDragMove(double x, double y)
|
||||
{
|
||||
const char* cmdName = (drag.Dragged.size() == 1) ?
|
||||
(drag.Dragged[0].Pos == Sketcher::PointPos::none ?
|
||||
QT_TRANSLATE_NOOP("Command", "Drag Curve") : QT_TRANSLATE_NOOP("Command", "Drag Point"))
|
||||
: QT_TRANSLATE_NOOP("Command", "Drag geometries");
|
||||
|
||||
getDocument()->openCommand(cmdName);
|
||||
|
||||
Base::Vector3d vec(x - drag.xInit, y - drag.yInit, 0);
|
||||
|
||||
if (drag.Dragged.size() == 1) {
|
||||
// special single bspline point handling.
|
||||
Sketcher::PointPos PosId = drag.Dragged[0].Pos;
|
||||
|
||||
if (PosId == Sketcher::PointPos::none) {
|
||||
int GeoId = drag.Dragged[0].GeoId;
|
||||
auto geo = getSketchObject()->getGeometry(GeoId);
|
||||
auto gf = GeometryFacade::getFacade(geo);
|
||||
|
||||
// BSpline weights have a radius corresponding to the weight value
|
||||
// However, in order for them proportional to the B-Spline size,
|
||||
// the scenograph has a size scalefactor times the weight
|
||||
// This code normalizes the information sent to the solver.
|
||||
if (gf->getInternalType() == InternalType::BSplineControlPoint) {
|
||||
auto circle = static_cast<const Part::GeomCircle*>(geo);
|
||||
Base::Vector3d center = circle->getCenter();
|
||||
|
||||
Base::Vector3d dir = vec - center;
|
||||
|
||||
double scalefactor = 1.0;
|
||||
|
||||
if (circle->hasExtension(
|
||||
SketcherGui::ViewProviderSketchGeometryExtension::
|
||||
getClassTypeId())) {
|
||||
auto vpext = std::static_pointer_cast<
|
||||
const SketcherGui::ViewProviderSketchGeometryExtension>(
|
||||
circle
|
||||
->getExtension(
|
||||
SketcherGui::ViewProviderSketchGeometryExtension::
|
||||
getClassTypeId())
|
||||
.lock());
|
||||
|
||||
scalefactor = vpext->getRepresentationFactor();
|
||||
}
|
||||
|
||||
vec = center + dir / scalefactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::stringstream cmd;
|
||||
cmd << "moveGeometries(";
|
||||
cmd << "[";
|
||||
for (size_t i = 0; i < drag.Dragged.size(); ++i) {
|
||||
if (i > 0) {
|
||||
cmd << ", ";
|
||||
}
|
||||
cmd << "(" << drag.Dragged[i].GeoId << ", " << static_cast<int>(drag.Dragged[i].Pos) << ")";
|
||||
}
|
||||
cmd << "], App.Vector(" << vec.x << ", " << vec.y << ", 0)";
|
||||
|
||||
if (drag.relative) {
|
||||
cmd << ", True";
|
||||
}
|
||||
cmd << ")";
|
||||
|
||||
try {
|
||||
Gui::cmdAppObjectArgs(getObject(), cmd.str().c_str());
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
getDocument()->abortCommand();
|
||||
Base::Console().DeveloperError("ViewProviderSketch", "Drag: %s\n", e.what());
|
||||
}
|
||||
|
||||
getDocument()->commitCommand();
|
||||
|
||||
tryAutoRecomputeIfNotSolve(getSketchObject());
|
||||
drag.reset();
|
||||
resetPositionText();
|
||||
}
|
||||
|
||||
void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2d& toPos)
|
||||
{
|
||||
if (auto constr = getConstraint(constNum)) {
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <Mod/Part/Gui/ViewProviderAttachExtension.h>
|
||||
#include <Mod/Part/Gui/ViewProviderGridExtension.h>
|
||||
#include <Mod/Sketcher/App/GeoList.h>
|
||||
#include <Mod/Sketcher/App/GeoEnum.h>
|
||||
|
||||
#include "PropertyVisualLayerList.h"
|
||||
|
||||
@@ -261,13 +262,12 @@ private:
|
||||
class Drag
|
||||
{
|
||||
public:
|
||||
enum SpecialValues
|
||||
{
|
||||
InvalidPoint = -1,
|
||||
InvalidCurve = -1
|
||||
};
|
||||
|
||||
Drag()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
resetVector();
|
||||
resetIds();
|
||||
@@ -282,28 +282,15 @@ private:
|
||||
|
||||
void resetIds()
|
||||
{
|
||||
DragPoint = InvalidPoint;
|
||||
DragCurve = InvalidCurve;
|
||||
Dragged.clear();
|
||||
DragConstraintSet.clear();
|
||||
}
|
||||
|
||||
bool isDragPointValid()
|
||||
{
|
||||
return DragPoint > InvalidPoint;
|
||||
}
|
||||
bool isDragCurveValid()
|
||||
{
|
||||
return DragCurve > InvalidCurve;
|
||||
}
|
||||
|
||||
double xInit, yInit; // starting point of the dragging operation
|
||||
bool relative; // whether the dragging move vector is relative or absolute
|
||||
|
||||
|
||||
int DragPoint; // dragged point id (only positive integers)
|
||||
int DragCurve; // dragged curve id (only positive integers), negative external curves
|
||||
// cannot be dragged.
|
||||
std::set<int> DragConstraintSet; // dragged constraints ids
|
||||
std::vector<Sketcher::GeoElementId> Dragged; // dragged geometries
|
||||
std::set<int> DragConstraintSet; // dragged constraints ids
|
||||
};
|
||||
|
||||
// TODO: Selection and Preselection should use a same structure. Probably Drag should use the
|
||||
@@ -553,8 +540,7 @@ public:
|
||||
STATUS_SELECT_Constraint, /**< enum value a constraint was selected. */
|
||||
STATUS_SELECT_Cross, /**< enum value the base coordinate system was selected. */
|
||||
STATUS_SELECT_Wire, /**< enum value and edge was double clicked. */
|
||||
STATUS_SKETCH_DragPoint, /**< enum value while dragging a point. */
|
||||
STATUS_SKETCH_DragCurve, /**< enum value while dragging a curve. */
|
||||
STATUS_SKETCH_Drag, /**< enum value while dragging curves and or points. */
|
||||
STATUS_SKETCH_DragConstraint, /**< enum value while dragging a compatible constraint. */
|
||||
STATUS_SKETCH_UseHandler, /**< enum value a DrawSketchHandler is in control. */
|
||||
STATUS_SKETCH_StartRubberBand, /**< enum value for initiating a rubber band selection */
|
||||
@@ -792,6 +778,15 @@ private:
|
||||
bool setPreselect(const std::string& subNameSuffix, float x = 0, float y = 0, float z = 0);
|
||||
//@}
|
||||
|
||||
/** @name dragging functions */
|
||||
//@{
|
||||
/// dragging helpers
|
||||
void initDragging(int geoId, Sketcher::PointPos pos, Gui::View3DInventorViewer* viewer);
|
||||
void doDragStep(double x, double y);
|
||||
void commitDragMove(double x, double y);
|
||||
|
||||
//@}
|
||||
|
||||
/** @name Selection functions */
|
||||
//@{
|
||||
/// box selection method
|
||||
|
||||
Reference in New Issue
Block a user