Sketcher: Box Selection - refactor
================================== Full refactor of this function without change of functionality (hopefully).
This commit is contained in:
committed by
abdullahtahiriyo
parent
811da8bb09
commit
55639df573
@@ -95,6 +95,20 @@ T getSketcherGeneralParameter(const std::string& string, T defaultvalue)
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T getPreferencesViewParameter(const std::string& string, T defaultvalue)
|
||||
{
|
||||
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/View");
|
||||
|
||||
if constexpr (std::is_same_v<decltype(defaultvalue), unsigned int>) {
|
||||
return static_cast<unsigned int>(hGrp->GetUnsigned(string.c_str(), defaultvalue));
|
||||
}
|
||||
else if constexpr (std::is_same_v<decltype(defaultvalue), int>) {
|
||||
return static_cast<int>(hGrp->GetInt(string.c_str(), defaultvalue));
|
||||
}
|
||||
}
|
||||
|
||||
ViewProviderSketch::ParameterObserver::ParameterObserver(ViewProviderSketch& client)
|
||||
: Client(client)
|
||||
{}
|
||||
@@ -343,6 +357,13 @@ void ViewProviderSketch::ParameterObserver::initParameters()
|
||||
Client.setGridDivLineColor(color);
|
||||
},
|
||||
nullptr}},
|
||||
{"SegmentsPerGeometry",
|
||||
{[this, packedDefaultGridColor](const std::string& string,
|
||||
[[maybe_unused]] App::Property* property) {
|
||||
auto v = getPreferencesViewParameter(string, 50);
|
||||
Client.viewProviderParameters.stdCountSegments = v;
|
||||
},
|
||||
nullptr}},
|
||||
};
|
||||
|
||||
for (auto& val : parameterMap) {
|
||||
@@ -2304,10 +2325,15 @@ void ViewProviderSketch::doBoxSelection(const SbVec2s& startPos, const SbVec2s&
|
||||
assert(int(geomlist.size()) == extGeoCount + intGeoCount);
|
||||
assert(int(geomlist.size()) >= 2);
|
||||
|
||||
Base::Vector3d pnt0, pnt1, pnt2, pnt;
|
||||
int VertexId =
|
||||
-1;// the loop below should be in sync with the main loop in ViewProviderSketch::draw
|
||||
// so that the vertex indices are calculated correctly
|
||||
auto inBBCoords = [&Plm, &proj](const Base::Vector3d & point) {
|
||||
Base::Vector3d pnt;
|
||||
Plm.multVec(point, pnt);
|
||||
return proj(pnt);
|
||||
};
|
||||
|
||||
int VertexId = -1; // the loop below should be in sync with the main loop in
|
||||
// ViewProviderSketch::draw so that the vertex indices are calculated
|
||||
// correctly
|
||||
int GeoId = 0;
|
||||
|
||||
bool touchMode = false;
|
||||
@@ -2316,6 +2342,58 @@ void ViewProviderSketch::doBoxSelection(const SbVec2s& startPos, const SbVec2s&
|
||||
if (corners[0].getValue()[0] > corners[1].getValue()[0])
|
||||
touchMode = true;
|
||||
|
||||
auto selectVertex = [this](int vertexid) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << vertexid;
|
||||
addSelection2(ss.str());
|
||||
};
|
||||
|
||||
auto selectEdge = [this](int edgeid) {
|
||||
std::stringstream ss;
|
||||
ss << "Edge" << edgeid;
|
||||
addSelection2(ss.str());
|
||||
};
|
||||
|
||||
auto selectVertexIfInsideBox = [&polygon, &VertexId, &selectVertex](const Base::Vector3d & point) {
|
||||
if (polygon.Contains(Base::Vector2d(point.x, point.y))) {
|
||||
selectVertex( VertexId + 1);
|
||||
return true; // inside
|
||||
}
|
||||
|
||||
return false; // outside
|
||||
};
|
||||
|
||||
auto selectEdgeIfInsideBox = [&touchMode, &polygon, &GeoId, &inBBCoords, &selectEdge,
|
||||
numSegments = viewProviderParameters.stdCountSegments](auto geo){
|
||||
|
||||
if constexpr (std::is_same<decltype(geo), Part::GeomBSplineCurve>::value) {
|
||||
numSegments *= geo->countKnots(); // one less segments than knots
|
||||
}
|
||||
|
||||
double segment = (geo->getLastParameter() - geo->getFirstParameter()) / numSegments;
|
||||
|
||||
bool bpolyInside = true;
|
||||
|
||||
for (int i = 0; i < numSegments; i++) {
|
||||
Base::Vector3d pnt = geo->value(geo->getFirstParameter() + i * segment);
|
||||
pnt = inBBCoords(pnt);
|
||||
if (!polygon.Contains(Base::Vector2d(pnt.x, pnt.y))) {
|
||||
bpolyInside = false;
|
||||
if (!touchMode) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (touchMode) {
|
||||
bpolyInside = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bpolyInside) {
|
||||
selectEdge(GeoId+1);
|
||||
}
|
||||
};
|
||||
|
||||
for (std::vector<Part::Geometry*>::const_iterator it = geomlist.begin();
|
||||
it != geomlist.end() - 2;
|
||||
++it, ++GeoId) {
|
||||
@@ -2326,43 +2404,28 @@ void ViewProviderSketch::doBoxSelection(const SbVec2s& startPos, const SbVec2s&
|
||||
if ((*it)->is<Part::GeomPoint>()) {
|
||||
// ----- Check if single point lies inside box selection -----/
|
||||
const Part::GeomPoint* point = static_cast<const Part::GeomPoint*>(*it);
|
||||
Plm.multVec(point->getPoint(), pnt0);
|
||||
pnt0 = proj(pnt0);
|
||||
VertexId += 1;
|
||||
Base::Vector3d pnt0 = inBBCoords(point->getPoint());
|
||||
VertexId++;
|
||||
|
||||
if (polygon.Contains(Base::Vector2d(pnt0.x, pnt0.y))) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId + 1;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
selectVertexIfInsideBox(pnt0);
|
||||
}
|
||||
else if ((*it)->is<Part::GeomLineSegment>()) {
|
||||
// ----- Check if line segment lies inside box selection -----/
|
||||
const Part::GeomLineSegment* lineSeg = static_cast<const Part::GeomLineSegment*>(*it);
|
||||
Plm.multVec(lineSeg->getStartPoint(), pnt1);
|
||||
Plm.multVec(lineSeg->getEndPoint(), pnt2);
|
||||
pnt1 = proj(pnt1);
|
||||
pnt2 = proj(pnt2);
|
||||
VertexId += 2;
|
||||
Base::Vector3d pnt1 = inBBCoords(lineSeg->getStartPoint());
|
||||
Base::Vector3d pnt2 = inBBCoords(lineSeg->getEndPoint());
|
||||
|
||||
bool pnt1Inside = polygon.Contains(Base::Vector2d(pnt1.x, pnt1.y));
|
||||
bool pnt2Inside = polygon.Contains(Base::Vector2d(pnt2.x, pnt2.y));
|
||||
if (pnt1Inside) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
VertexId++;
|
||||
bool pnt1Inside = selectVertexIfInsideBox(pnt1);
|
||||
|
||||
VertexId++;
|
||||
bool pnt2Inside = selectVertexIfInsideBox(pnt2);
|
||||
polygon.Contains(Base::Vector2d(pnt1.x, pnt1.y));
|
||||
polygon.Contains(Base::Vector2d(pnt2.x, pnt2.y));
|
||||
|
||||
if (pnt2Inside) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId + 1;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
|
||||
if ((pnt1Inside && pnt2Inside) && !touchMode) {
|
||||
std::stringstream ss;
|
||||
ss << "Edge" << GeoId + 1;
|
||||
addSelection2(ss.str());
|
||||
selectEdge(GeoId+1);
|
||||
}
|
||||
// check if line intersects with polygon
|
||||
else if (touchMode) {
|
||||
@@ -2372,488 +2435,66 @@ void ViewProviderSketch::doBoxSelection(const SbVec2s& startPos, const SbVec2s&
|
||||
std::list<Base::Polygon2d> resultList;
|
||||
polygon.Intersect(lineAsPolygon, resultList);
|
||||
if (!resultList.empty()) {
|
||||
std::stringstream ss;
|
||||
ss << "Edge" << GeoId + 1;
|
||||
addSelection2(ss.str());
|
||||
selectEdge(GeoId+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((*it)->is<Part::GeomCircle>()) {
|
||||
else if ((*it)->isDerivedFrom<Part::GeomConic>()) {
|
||||
// ----- Check if circle lies inside box selection -----/
|
||||
/// TODO: Make it impossible to miss the circle if it's big and the selection pretty
|
||||
/// TODO: Make it impossible to miss the conic if it's big and the selection pretty
|
||||
/// thin.
|
||||
const Part::GeomCircle* circle = static_cast<const Part::GeomCircle*>(*it);
|
||||
pnt0 = circle->getCenter();
|
||||
VertexId += 1;
|
||||
const Part::GeomConic* circle = static_cast<const Part::GeomConic*>(*it);
|
||||
Base::Vector3d pnt0 = inBBCoords(circle->getCenter());
|
||||
VertexId++;
|
||||
|
||||
Plm.multVec(pnt0, pnt0);
|
||||
pnt0 = proj(pnt0);
|
||||
bool pnt0Inside = selectVertexIfInsideBox(pnt0);
|
||||
|
||||
if (polygon.Contains(Base::Vector2d(pnt0.x, pnt0.y)) || touchMode) {
|
||||
if (polygon.Contains(Base::Vector2d(pnt0.x, pnt0.y))) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId + 1;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
int countSegments = 12;
|
||||
if (touchMode)
|
||||
countSegments = 36;
|
||||
|
||||
float segment = float(2 * M_PI) / countSegments;
|
||||
|
||||
// circumscribed polygon radius
|
||||
float radius = float(circle->getRadius()) / cos(segment / 2);
|
||||
|
||||
bool bpolyInside = true;
|
||||
pnt0 = circle->getCenter();
|
||||
float angle = 0.f;
|
||||
for (int i = 0; i < countSegments; ++i, angle += segment) {
|
||||
pnt = Base::Vector3d(
|
||||
pnt0.x + radius * cos(angle), pnt0.y + radius * sin(angle), 0.f);
|
||||
Plm.multVec(pnt, pnt);
|
||||
pnt = proj(pnt);
|
||||
if (!polygon.Contains(Base::Vector2d(pnt.x, pnt.y))) {
|
||||
bpolyInside = false;
|
||||
if (!touchMode)
|
||||
break;
|
||||
}
|
||||
else if (touchMode) {
|
||||
bpolyInside = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bpolyInside) {
|
||||
std::stringstream ss;
|
||||
ss << "Edge" << GeoId + 1;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
if (pnt0Inside || touchMode) {
|
||||
selectEdgeIfInsideBox(circle);
|
||||
}
|
||||
}
|
||||
else if ((*it)->is<Part::GeomEllipse>()) {
|
||||
// ----- Check if ellipse lies inside box selection -----/
|
||||
const Part::GeomEllipse* ellipse = static_cast<const Part::GeomEllipse*>(*it);
|
||||
pnt0 = ellipse->getCenter();
|
||||
VertexId += 1;
|
||||
|
||||
Plm.multVec(pnt0, pnt0);
|
||||
pnt0 = proj(pnt0);
|
||||
|
||||
if (polygon.Contains(Base::Vector2d(pnt0.x, pnt0.y)) || touchMode) {
|
||||
if (polygon.Contains(Base::Vector2d(pnt0.x, pnt0.y))) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId + 1;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
|
||||
int countSegments = 12;
|
||||
if (touchMode)
|
||||
countSegments = 24;
|
||||
double segment = (2 * M_PI) / countSegments;
|
||||
|
||||
// circumscribed polygon radius
|
||||
double a = (ellipse->getMajorRadius()) / cos(segment / 2);
|
||||
double b = (ellipse->getMinorRadius()) / cos(segment / 2);
|
||||
Base::Vector3d majdir = ellipse->getMajorAxisDir();
|
||||
Base::Vector3d mindir = Base::Vector3d(-majdir.y, majdir.x, 0.0);
|
||||
|
||||
bool bpolyInside = true;
|
||||
pnt0 = ellipse->getCenter();
|
||||
double angle = 0.;
|
||||
for (int i = 0; i < countSegments; ++i, angle += segment) {
|
||||
pnt = pnt0 + (cos(angle) * a) * majdir + sin(angle) * b * mindir;
|
||||
Plm.multVec(pnt, pnt);
|
||||
pnt = proj(pnt);
|
||||
if (!polygon.Contains(Base::Vector2d(pnt.x, pnt.y))) {
|
||||
bpolyInside = false;
|
||||
if (!touchMode)
|
||||
break;
|
||||
}
|
||||
else if (touchMode) {
|
||||
bpolyInside = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bpolyInside) {
|
||||
std::stringstream ss;
|
||||
ss << "Edge" << GeoId + 1;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((*it)->is<Part::GeomArcOfCircle>()) {
|
||||
else if ((*it)->isDerivedFrom<Part::GeomArcOfConic>()) {
|
||||
// Check if arc lies inside box selection
|
||||
const Part::GeomArcOfCircle* aoc = static_cast<const Part::GeomArcOfCircle*>(*it);
|
||||
const Part::GeomArcOfConic* aoc = static_cast<const Part::GeomArcOfConic*>(*it);
|
||||
|
||||
pnt0 = aoc->getStartPoint(/*emulateCCW=*/true);
|
||||
pnt1 = aoc->getEndPoint(/*emulateCCW=*/true);
|
||||
pnt2 = aoc->getCenter();
|
||||
VertexId += 3;
|
||||
Base::Vector3d pnt0 = inBBCoords(aoc->getStartPoint(/*emulateCCW=*/true));
|
||||
VertexId++;
|
||||
bool pnt0Inside = selectVertexIfInsideBox(pnt0);
|
||||
|
||||
Plm.multVec(pnt0, pnt0);
|
||||
Plm.multVec(pnt1, pnt1);
|
||||
Plm.multVec(pnt2, pnt2);
|
||||
pnt0 = proj(pnt0);
|
||||
pnt1 = proj(pnt1);
|
||||
pnt2 = proj(pnt2);
|
||||
Base::Vector3d pnt1 = inBBCoords(aoc->getEndPoint(/*emulateCCW=*/true));
|
||||
VertexId++;
|
||||
bool pnt1Inside = selectVertexIfInsideBox(pnt1);
|
||||
|
||||
bool pnt0Inside = polygon.Contains(Base::Vector2d(pnt0.x, pnt0.y));
|
||||
bool pnt1Inside = polygon.Contains(Base::Vector2d(pnt1.x, pnt1.y));
|
||||
bool bpolyInside = true;
|
||||
Base::Vector3d pnt2 = inBBCoords(aoc->getCenter());
|
||||
VertexId++;
|
||||
selectVertexIfInsideBox(pnt2);
|
||||
|
||||
if ((pnt0Inside && pnt1Inside) || touchMode) {
|
||||
double startangle, endangle;
|
||||
aoc->getRange(startangle, endangle, /*emulateCCW=*/true);
|
||||
|
||||
if (startangle > endangle)// if arc is reversed
|
||||
std::swap(startangle, endangle);
|
||||
|
||||
double range = endangle - startangle;
|
||||
int countSegments = std::max(2, int(12.0 * range / (2 * M_PI)));
|
||||
if (touchMode)
|
||||
countSegments = countSegments * 2.5;
|
||||
float segment = float(range) / countSegments;
|
||||
|
||||
// circumscribed polygon radius
|
||||
float radius = float(aoc->getRadius()) / cos(segment / 2);
|
||||
|
||||
pnt0 = aoc->getCenter();
|
||||
float angle = float(startangle) + segment / 2;
|
||||
for (int i = 0; i < countSegments; ++i, angle += segment) {
|
||||
pnt = Base::Vector3d(
|
||||
pnt0.x + radius * cos(angle), pnt0.y + radius * sin(angle), 0.f);
|
||||
Plm.multVec(pnt, pnt);
|
||||
pnt = proj(pnt);
|
||||
if (!polygon.Contains(Base::Vector2d(pnt.x, pnt.y))) {
|
||||
bpolyInside = false;
|
||||
if (!touchMode)
|
||||
break;
|
||||
}
|
||||
else if (touchMode) {
|
||||
bpolyInside = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bpolyInside) {
|
||||
std::stringstream ss;
|
||||
ss << "Edge" << GeoId + 1;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
if (pnt0Inside) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId - 1;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
|
||||
if (pnt1Inside) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
|
||||
if (polygon.Contains(Base::Vector2d(pnt2.x, pnt2.y))) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId + 1;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
}
|
||||
else if ((*it)->is<Part::GeomArcOfEllipse>()) {
|
||||
// Check if arc lies inside box selection
|
||||
const Part::GeomArcOfEllipse* aoe = static_cast<const Part::GeomArcOfEllipse*>(*it);
|
||||
|
||||
pnt0 = aoe->getStartPoint(/*emulateCCW=*/true);
|
||||
pnt1 = aoe->getEndPoint(/*emulateCCW=*/true);
|
||||
pnt2 = aoe->getCenter();
|
||||
|
||||
VertexId += 3;
|
||||
|
||||
Plm.multVec(pnt0, pnt0);
|
||||
Plm.multVec(pnt1, pnt1);
|
||||
Plm.multVec(pnt2, pnt2);
|
||||
pnt0 = proj(pnt0);
|
||||
pnt1 = proj(pnt1);
|
||||
pnt2 = proj(pnt2);
|
||||
|
||||
bool pnt0Inside = polygon.Contains(Base::Vector2d(pnt0.x, pnt0.y));
|
||||
bool pnt1Inside = polygon.Contains(Base::Vector2d(pnt1.x, pnt1.y));
|
||||
bool bpolyInside = true;
|
||||
|
||||
if ((pnt0Inside && pnt1Inside) || touchMode) {
|
||||
double startangle, endangle;
|
||||
aoe->getRange(startangle, endangle, /*emulateCCW=*/true);
|
||||
|
||||
if (startangle > endangle)// if arc is reversed
|
||||
std::swap(startangle, endangle);
|
||||
|
||||
double range = endangle - startangle;
|
||||
int countSegments = std::max(2, int(12.0 * range / (2 * M_PI)));
|
||||
if (touchMode)
|
||||
countSegments = countSegments * 2.5;
|
||||
double segment = (range) / countSegments;
|
||||
|
||||
// circumscribed polygon radius
|
||||
double a = (aoe->getMajorRadius()) / cos(segment / 2);
|
||||
double b = (aoe->getMinorRadius()) / cos(segment / 2);
|
||||
Base::Vector3d majdir = aoe->getMajorAxisDir();
|
||||
Base::Vector3d mindir = Base::Vector3d(-majdir.y, majdir.x, 0.0);
|
||||
|
||||
pnt0 = aoe->getCenter();
|
||||
double angle = (startangle) + segment / 2;
|
||||
for (int i = 0; i < countSegments; ++i, angle += segment) {
|
||||
pnt = pnt0 + cos(angle) * a * majdir + sin(angle) * b * mindir;
|
||||
|
||||
Plm.multVec(pnt, pnt);
|
||||
pnt = proj(pnt);
|
||||
if (!polygon.Contains(Base::Vector2d(pnt.x, pnt.y))) {
|
||||
bpolyInside = false;
|
||||
if (!touchMode)
|
||||
break;
|
||||
}
|
||||
else if (touchMode) {
|
||||
bpolyInside = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bpolyInside) {
|
||||
std::stringstream ss;
|
||||
ss << "Edge" << GeoId + 1;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
}
|
||||
if (pnt0Inside) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId - 1;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
|
||||
if (pnt1Inside) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
|
||||
if (polygon.Contains(Base::Vector2d(pnt2.x, pnt2.y))) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId + 1;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
}
|
||||
else if ((*it)->is<Part::GeomArcOfHyperbola>()) {
|
||||
// Check if arc lies inside box selection
|
||||
const Part::GeomArcOfHyperbola* aoh = static_cast<const Part::GeomArcOfHyperbola*>(*it);
|
||||
pnt0 = aoh->getStartPoint();
|
||||
pnt1 = aoh->getEndPoint();
|
||||
pnt2 = aoh->getCenter();
|
||||
|
||||
VertexId += 3;
|
||||
|
||||
Plm.multVec(pnt0, pnt0);
|
||||
Plm.multVec(pnt1, pnt1);
|
||||
Plm.multVec(pnt2, pnt2);
|
||||
pnt0 = proj(pnt0);
|
||||
pnt1 = proj(pnt1);
|
||||
pnt2 = proj(pnt2);
|
||||
|
||||
bool pnt0Inside = polygon.Contains(Base::Vector2d(pnt0.x, pnt0.y));
|
||||
bool pnt1Inside = polygon.Contains(Base::Vector2d(pnt1.x, pnt1.y));
|
||||
bool bpolyInside = true;
|
||||
|
||||
if ((pnt0Inside && pnt1Inside) || touchMode) {
|
||||
double startangle, endangle;
|
||||
|
||||
aoh->getRange(startangle, endangle, /*emulateCCW=*/true);
|
||||
|
||||
if (startangle > endangle)// if arc is reversed
|
||||
std::swap(startangle, endangle);
|
||||
|
||||
double range = endangle - startangle;
|
||||
int countSegments = std::max(2, int(12.0 * range / (2 * M_PI)));
|
||||
if (touchMode)
|
||||
countSegments = countSegments * 2.5;
|
||||
|
||||
float segment = float(range) / countSegments;
|
||||
|
||||
// circumscribed polygon radius
|
||||
float a = float(aoh->getMajorRadius()) / cos(segment / 2);
|
||||
float b = float(aoh->getMinorRadius()) / cos(segment / 2);
|
||||
float phi = float(aoh->getAngleXU());
|
||||
|
||||
pnt0 = aoh->getCenter();
|
||||
float angle = float(startangle) + segment / 2;
|
||||
for (int i = 0; i < countSegments; ++i, angle += segment) {
|
||||
pnt = Base::Vector3d(
|
||||
pnt0.x + a * cosh(angle) * cos(phi) - b * sinh(angle) * sin(phi),
|
||||
pnt0.y + a * cosh(angle) * sin(phi) + b * sinh(angle) * cos(phi),
|
||||
0.f);
|
||||
|
||||
Plm.multVec(pnt, pnt);
|
||||
pnt = proj(pnt);
|
||||
if (!polygon.Contains(Base::Vector2d(pnt.x, pnt.y))) {
|
||||
bpolyInside = false;
|
||||
if (!touchMode)
|
||||
break;
|
||||
}
|
||||
else if (touchMode) {
|
||||
bpolyInside = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bpolyInside) {
|
||||
std::stringstream ss;
|
||||
ss << "Edge" << GeoId + 1;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
}
|
||||
if (pnt0Inside) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId - 1;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
|
||||
if (pnt1Inside) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
|
||||
if (polygon.Contains(Base::Vector2d(pnt2.x, pnt2.y))) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId + 1;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
}
|
||||
else if ((*it)->is<Part::GeomArcOfParabola>()) {
|
||||
// Check if arc lies inside box selection
|
||||
const Part::GeomArcOfParabola* aop = static_cast<const Part::GeomArcOfParabola*>(*it);
|
||||
|
||||
pnt0 = aop->getStartPoint();
|
||||
pnt1 = aop->getEndPoint();
|
||||
pnt2 = aop->getCenter();
|
||||
|
||||
VertexId += 3;
|
||||
|
||||
Plm.multVec(pnt0, pnt0);
|
||||
Plm.multVec(pnt1, pnt1);
|
||||
Plm.multVec(pnt2, pnt2);
|
||||
pnt0 = proj(pnt0);
|
||||
pnt1 = proj(pnt1);
|
||||
pnt2 = proj(pnt2);
|
||||
|
||||
bool pnt0Inside = polygon.Contains(Base::Vector2d(pnt0.x, pnt0.y));
|
||||
bool pnt1Inside = polygon.Contains(Base::Vector2d(pnt1.x, pnt1.y));
|
||||
bool bpolyInside = true;
|
||||
|
||||
if ((pnt0Inside && pnt1Inside) || touchMode) {
|
||||
double startangle, endangle;
|
||||
|
||||
aop->getRange(startangle, endangle, /*emulateCCW=*/true);
|
||||
|
||||
if (startangle > endangle)// if arc is reversed
|
||||
std::swap(startangle, endangle);
|
||||
|
||||
double range = endangle - startangle;
|
||||
int countSegments = std::max(2, int(12.0 * range / (2 * M_PI)));
|
||||
if (touchMode)
|
||||
countSegments = countSegments * 2.5;
|
||||
|
||||
float segment = float(range) / countSegments;
|
||||
// In local coordinate system, value() of parabola is:
|
||||
// P(U) = O + U*U/(4.*F)*XDir + U*YDir
|
||||
// circumscribed polygon radius
|
||||
float focal = float(aop->getFocal()) / cos(segment / 2);
|
||||
float phi = float(aop->getAngleXU());
|
||||
|
||||
pnt0 = aop->getCenter();
|
||||
float angle = float(startangle) + segment / 2;
|
||||
for (int i = 0; i < countSegments; ++i, angle += segment) {
|
||||
pnt = Base::Vector3d(
|
||||
pnt0.x + angle * angle / 4 / focal * cos(phi) - angle * sin(phi),
|
||||
pnt0.y + angle * angle / 4 / focal * sin(phi) + angle * cos(phi),
|
||||
0.f);
|
||||
|
||||
Plm.multVec(pnt, pnt);
|
||||
pnt = proj(pnt);
|
||||
if (!polygon.Contains(Base::Vector2d(pnt.x, pnt.y))) {
|
||||
bpolyInside = false;
|
||||
if (!touchMode)
|
||||
break;
|
||||
}
|
||||
else if (touchMode) {
|
||||
bpolyInside = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bpolyInside) {
|
||||
std::stringstream ss;
|
||||
ss << "Edge" << GeoId + 1;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
if (pnt0Inside) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId - 1;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
|
||||
if (pnt1Inside) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
|
||||
if (polygon.Contains(Base::Vector2d(pnt2.x, pnt2.y))) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId + 1;
|
||||
addSelection2(ss.str());
|
||||
selectEdgeIfInsideBox(aoc);
|
||||
}
|
||||
}
|
||||
else if ((*it)->is<Part::GeomBSplineCurve>()) {
|
||||
const Part::GeomBSplineCurve* spline = static_cast<const Part::GeomBSplineCurve*>(*it);
|
||||
// std::vector<Base::Vector3d> poles = spline->getPoles();
|
||||
VertexId += 2;
|
||||
|
||||
Plm.multVec(spline->getStartPoint(), pnt1);
|
||||
Plm.multVec(spline->getEndPoint(), pnt2);
|
||||
pnt1 = proj(pnt1);
|
||||
pnt2 = proj(pnt2);
|
||||
Base::Vector3d pnt1 = inBBCoords(spline->getStartPoint());
|
||||
VertexId++;
|
||||
bool pnt1Inside = selectVertexIfInsideBox(pnt1);
|
||||
|
||||
bool pnt1Inside = polygon.Contains(Base::Vector2d(pnt1.x, pnt1.y));
|
||||
bool pnt2Inside = polygon.Contains(Base::Vector2d(pnt2.x, pnt2.y));
|
||||
if (pnt1Inside || (touchMode && pnt2Inside)) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
|
||||
if (pnt2Inside || (touchMode && pnt1Inside)) {
|
||||
std::stringstream ss;
|
||||
ss << "Vertex" << VertexId + 1;
|
||||
addSelection2(ss.str());
|
||||
}
|
||||
|
||||
// This is a rather approximated approach. No it does not guarantee that the whole curve
|
||||
// is boxed, specially for periodic curves, but it works reasonably well. Including all
|
||||
// poles, which could be done, generally forces the user to select much more than the
|
||||
// curve (all the poles) and it would not select the curve in cases where it is indeed
|
||||
// comprised in the box. The implementation of the touch mode is also far from a
|
||||
// desirable "touch" as it only recognizes touched points not the curve itself
|
||||
if ((pnt1Inside && pnt2Inside) || (touchMode && (pnt1Inside || pnt2Inside))) {
|
||||
std::stringstream ss;
|
||||
ss << "Edge" << GeoId + 1;
|
||||
addSelection2(ss.str());
|
||||
Base::Vector3d pnt2 = inBBCoords(spline->getEndPoint());
|
||||
VertexId++;
|
||||
bool pnt2Inside = selectVertexIfInsideBox(pnt2);
|
||||
|
||||
if ((pnt1Inside && pnt2Inside) || touchMode) {
|
||||
selectEdgeIfInsideBox(spline);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Base::Console().DeveloperError("ViewProviderSketch::doBoxSelection",
|
||||
"Geometry type is unsupported. Selection may be unsynchronised and fail.");
|
||||
}
|
||||
}
|
||||
|
||||
pnt0 = proj(Plm.getPosition());
|
||||
Base::Vector3d pnt0 = proj(Plm.getPosition());
|
||||
if (polygon.Contains(Base::Vector2d(pnt0.x, pnt0.y))) {
|
||||
std::stringstream ss;
|
||||
ss << "RootPoint";
|
||||
|
||||
@@ -461,6 +461,9 @@ private:
|
||||
false; // indicates whether the present virtual space view is the
|
||||
// Real Space or the Virtual Space (virtual space 1 or 2)
|
||||
bool buttonPress = false;
|
||||
|
||||
int stdCountSegments =
|
||||
50; // preferences controlled default geometry sampling for selection
|
||||
};
|
||||
|
||||
/** @brief Private struct grouping ViewProvider and RenderManager node, to be used as SoNode
|
||||
|
||||
Reference in New Issue
Block a user