Sketcher New Feature: Ellipse support

- Ellipse introduction button via (center,majaxis extreme, a point in edge), ellipse is always CCW so that Z axis goes in the positive direction of the sketch
- Backwards compatibility with files of previous versions of ellipse not defining a phi angle
- Art by Jim (all the icons you see and the XPMs shown on creation of an ellipse)
- Element Widget support for ellipses
- Box selection for ellipses
- Point on Ellipse constraint based on the gardener's method based on Ulrich's function proposal (radcan simplified, i.e. with simplify_radical sage function)
- Tangent: Ellipse to Line based on DeepSOIC's geometric formulation (radcan simplified)

Sketcher New Feature: Internal Alignment Constraint
- The element to which internal alignment is applied has to be selected last.
- All other elements are added in the order of priority, taking into account existing elements
- Art by Jim (beautiful icons).

Sketcher New Feature: Tool to show/hide/restore the internal geometry of an element
- New functionality for show/hide internal geometry:
  toggles between hiding all unused internal geometry elements and showing all internal geometry.
  The restore function is implicit to the showing all internal geometry

Sketcher New Feature: Arc of Ellipse support
- Part::Geometry + Python implementation
- ArcOfEllipse creation method
- Art by Jim (all the icons you see and the XPMs shown on creation of arc of ellipse elements)
- Sketcher Element widget for ArcOfEllipse.

Bug fix: Select elements associated to constraints works now for foci internal alignment constraints
This commit is contained in:
Abdullah Tahiri
2014-11-11 19:29:45 +01:00
committed by wmayer
parent 6eec2e9851
commit a458c3e6d2
33 changed files with 5024 additions and 147 deletions

View File

@@ -28,6 +28,7 @@
# include <Poly_Polygon3D.hxx>
# include <Geom_BSplineCurve.hxx>
# include <Geom_Circle.hxx>
# include <Geom_Ellipse.hxx>
# include <Geom_TrimmedCurve.hxx>
# include <Inventor/actions/SoGetBoundingBoxAction.h>
# include <Inventor/SoPath.h>
@@ -715,7 +716,9 @@ bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVe
const Part::Geometry *geo = getSketchObject()->getGeometry(edit->DragCurve);
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId() ||
geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
geo->getTypeId() == Part::GeomCircle::getClassTypeId()) {
geo->getTypeId() == Part::GeomCircle::getClassTypeId() ||
geo->getTypeId() == Part::GeomEllipse::getClassTypeId()||
geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) { // TODO: ellipse
Gui::Command::openCommand("Drag Curve");
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.movePoint(%i,%i,App.Vector(%f,%f,0),%i)"
,getObject()->getNameInDocument()
@@ -912,8 +915,10 @@ void ViewProviderSketch::editDoubleClicked(void)
// if its the right constraint
if (Constr->Type == Sketcher::Distance ||
Constr->Type == Sketcher::DistanceX || Constr->Type == Sketcher::DistanceY ||
Constr->Type == Sketcher::Radius || Constr->Type == Sketcher::Angle) {
Constr->Type == Sketcher::DistanceX ||
Constr->Type == Sketcher::DistanceY ||
Constr->Type == Sketcher::Radius ||
Constr->Type == Sketcher::Angle) {
// Coin's SoIdleSensor causes problems on some platform while Qt seems to work properly (#0001517)
EditDatumDialog *editDatumDialog = new EditDatumDialog(this, *it);
@@ -1161,14 +1166,15 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2D &toPo
p1 = arc->getCenter();
p2 = p1 + radius * Base::Vector3d(cos(angle),sin(angle),0.);
}
else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) {
else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) {
const Part::GeomCircle *circle = dynamic_cast<const Part::GeomCircle *>(geo);
double radius = circle->getRadius();
p1 = circle->getCenter();
Base::Vector3d tmpDir = Base::Vector3d(toPos.fX, toPos.fY, 0) - p1;
double angle = atan2(tmpDir.y, tmpDir.x);
p2 = p1 + radius * Base::Vector3d(cos(angle),sin(angle),0.);
} else
}
else
return;
} else
return;
@@ -1815,7 +1821,7 @@ void ViewProviderSketch::doBoxSelection(const SbVec2s &startPos, const SbVec2s &
Gui::Selection().addSelection(doc->getName(), sketchObject->getNameInDocument(), ss.str().c_str());
}
} else if ((*it)->getTypeId() == Part::GeomCircle::getClassTypeId()) {
} else if ((*it)->getTypeId() == Part::GeomCircle::getClassTypeId()) {
// ----- Check if circle lies inside box selection -----/
const Part::GeomCircle *circle = dynamic_cast<const Part::GeomCircle *>(*it);
pnt0 = circle->getCenter();
@@ -1850,6 +1856,50 @@ void ViewProviderSketch::doBoxSelection(const SbVec2s &startPos, const SbVec2s &
}
}
if (bpolyInside) {
ss.clear();
ss.str("");
ss << "Edge" << GeoId + 1;
Gui::Selection().addSelection(doc->getName(), sketchObject->getNameInDocument(),ss.str().c_str());
}
}
} else if ((*it)->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
// ----- Check if circle lies inside box selection -----/
const Part::GeomEllipse *ellipse = dynamic_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))) {
std::stringstream ss;
ss << "Vertex" << VertexId + 1;
Gui::Selection().addSelection(doc->getName(), sketchObject->getNameInDocument(), ss.str().c_str());
int countSegments = 12;
float segment = float(2 * M_PI) / countSegments;
// circumscribed polygon radius
float a = float(ellipse->getMajorRadius()) / cos(segment/2);
float b = float(ellipse->getMinorRadius()) / cos(segment/2);
float phi = float(ellipse->getAngleXU());
bool bpolyInside = true;
pnt0 = ellipse->getCenter();
float angle = 0.f;
for (int i = 0; i < countSegments; ++i, angle += segment) {
pnt = Base::Vector3d(pnt0.x + a * cos(angle) * cos(phi) - b * sin(angle) * sin(phi),
pnt0.y + a * cos(angle) * sin(phi) + b * sin(angle) * cos(phi),
0.f);
Plm.multVec(pnt, pnt);
pnt = proj(pnt);
if (!polygon.Contains(Base::Vector2D(pnt.x, pnt.y))) {
bpolyInside = false;
break;
}
}
if (bpolyInside) {
ss.clear();
ss.str("");
@@ -2082,7 +2132,7 @@ void ViewProviderSketch::updateColor(void)
bool hasMaterial = false;
SoMaterial *m;
if (!hasDatumLabel && type != Sketcher::Coincident) {
if (!hasDatumLabel && type != Sketcher::Coincident && type !=InternalAlignment) {
hasMaterial = true;
m = dynamic_cast<SoMaterial *>(s->getChild(CONSTRAINT_SEPARATOR_INDEX_MATERIAL_OR_DATUMLABEL));
}
@@ -2095,9 +2145,9 @@ void ViewProviderSketch::updateColor(void)
m->diffuseColor = SelectColor;
} else if (type == Sketcher::Coincident) {
int index;
index = edit->ActSketch.getPointId(constraint->First, constraint->FirstPos) + 1;
index = edit->ActSketch.getVisiblePointId(constraint->First, constraint->FirstPos) + 1;
if (index >= 0 && index < PtNum) pcolor[index] = SelectColor;
index = edit->ActSketch.getPointId(constraint->Second, constraint->SecondPos) + 1;
index = edit->ActSketch.getVisiblePointId(constraint->Second, constraint->SecondPos) + 1;
if (index >= 0 && index < PtNum) pcolor[index] = SelectColor;
}
} else if (edit->PreselectConstraintSet.count(i)) {
@@ -2735,6 +2785,25 @@ void ViewProviderSketch::draw(bool temp)
edit->CurvIdToGeoId.push_back(GeoId);
Points.push_back(center);
}
else if ((*it)->getTypeId() == Part::GeomEllipse::getClassTypeId()) { // add an ellipse
const Part::GeomEllipse *ellipse = dynamic_cast<const Part::GeomEllipse *>(*it);
Handle_Geom_Ellipse curve = Handle_Geom_Ellipse::DownCast(ellipse->handle());
int countSegments = 50;
Base::Vector3d center = ellipse->getCenter();
double segment = (2 * M_PI) / countSegments;
for (int i=0; i < countSegments; i++) {
gp_Pnt pnt = curve->Value(i*segment);
Coords.push_back(Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z()));
}
gp_Pnt pnt = curve->Value(0);
Coords.push_back(Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z()));
Index.push_back(countSegments+1);
edit->CurvIdToGeoId.push_back(GeoId);
Points.push_back(center);
}
else if ((*it)->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { // add an arc
const Part::GeomArcOfCircle *arc = dynamic_cast<const Part::GeomArcOfCircle *>(*it);
Handle_Geom_TrimmedCurve curve = Handle_Geom_TrimmedCurve::DownCast(arc->handle());
@@ -2768,6 +2837,39 @@ void ViewProviderSketch::draw(bool temp)
Points.push_back(end);
Points.push_back(center);
}
else if ((*it)->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) { // add an arc
const Part::GeomArcOfEllipse *arc = dynamic_cast<const Part::GeomArcOfEllipse *>(*it);
Handle_Geom_TrimmedCurve curve = Handle_Geom_TrimmedCurve::DownCast(arc->handle());
double startangle, endangle;
arc->getRange(startangle, endangle);
if (startangle > endangle) // if arc is reversed
std::swap(startangle, endangle);
double range = endangle-startangle;
int countSegments = std::max(6, int(50.0 * range / (2 * M_PI)));
double segment = range / countSegments;
Base::Vector3d center = arc->getCenter();
Base::Vector3d start = arc->getStartPoint();
Base::Vector3d end = arc->getEndPoint();
for (int i=0; i < countSegments; i++) {
gp_Pnt pnt = curve->Value(startangle);
Coords.push_back(Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z()));
startangle += segment;
}
// end point
gp_Pnt pnt = curve->Value(endangle);
Coords.push_back(Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z()));
Index.push_back(countSegments+1);
edit->CurvIdToGeoId.push_back(GeoId);
Points.push_back(start);
Points.push_back(end);
Points.push_back(center);
}
else if ((*it)->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) { // add a bspline
const Part::GeomBSplineCurve *spline = dynamic_cast<const Part::GeomBSplineCurve *>(*it);
Handle_Geom_BSplineCurve curve = Handle_Geom_BSplineCurve::DownCast(spline->handle());
@@ -2875,7 +2977,8 @@ Restart:
// root separator for this constraint
SoSeparator *sep = dynamic_cast<SoSeparator *>(edit->constrGroup->getChild(i));
const Constraint *Constr = *it;
bool major_radius = false; // this is checked in the radius to reuse code
// distinquish different constraint types to build up
switch (Constr->Type) {
case Horizontal: // write the new position of the Horizontal constraint Same as vertical position.
@@ -2929,7 +3032,7 @@ Restart:
norm1 = Base::Vector3d(cos(midangle),sin(midangle),0);
dir1 = Base::Vector3d(-norm1.y,norm1.x,0);
midpos1 = arc->getCenter() + arc->getRadius() * norm1;
} else if (geo1->getTypeId() == Part::GeomCircle::getClassTypeId()) {
} else if (geo1->getTypeId() == Part::GeomCircle::getClassTypeId()) { // TODO: ellipse
const Part::GeomCircle *circle = dynamic_cast<const Part::GeomCircle *>(geo1);
norm1 = Base::Vector3d(cos(M_PI/4),sin(M_PI/4),0);
dir1 = Base::Vector3d(-norm1.y,norm1.x,0);
@@ -2950,7 +3053,7 @@ Restart:
norm2 = Base::Vector3d(cos(midangle),sin(midangle),0);
dir2 = Base::Vector3d(-norm2.y,norm2.x,0);
midpos2 = arc->getCenter() + arc->getRadius() * norm2;
} else if (geo2->getTypeId() == Part::GeomCircle::getClassTypeId()) {
} else if (geo2->getTypeId() == Part::GeomCircle::getClassTypeId()) { // TODO: ellipse
const Part::GeomCircle *circle = dynamic_cast<const Part::GeomCircle *>(geo2);
norm2 = Base::Vector3d(cos(M_PI/4),sin(M_PI/4),0);
dir2 = Base::Vector3d(-norm2.y,norm2.x,0);
@@ -2996,7 +3099,7 @@ Restart:
geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId()) {
if (Constr->Type == Equal) {
double r1,r2,angle1,angle2;
if (geo1->getTypeId() == Part::GeomCircle::getClassTypeId()) {
if (geo1->getTypeId() == Part::GeomCircle::getClassTypeId()) { // TODO: ellipse
const Part::GeomCircle *circle = dynamic_cast<const Part::GeomCircle *>(geo1);
r1 = circle->getRadius();
angle1 = M_PI/4;
@@ -3008,10 +3111,16 @@ Restart:
arc->getRange(startangle, endangle);
angle1 = (startangle + endangle)/2;
midpos1 = arc->getCenter();
} else if (geo1->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
// TODO: ellipse
const Part::GeomEllipse *ellipse = dynamic_cast<const Part::GeomEllipse *>(geo1);
r1 = ellipse->getMajorRadius();
angle1 = -ellipse->getAngleXU();
midpos1 = ellipse->getCenter();
} else
break;
if (geo2->getTypeId() == Part::GeomCircle::getClassTypeId()) {
if (geo2->getTypeId() == Part::GeomCircle::getClassTypeId()) { // TODO: ellipse
const Part::GeomCircle *circle = dynamic_cast<const Part::GeomCircle *>(geo2);
r2 = circle->getRadius();
angle2 = M_PI/4;
@@ -3023,7 +3132,14 @@ Restart:
arc->getRange(startangle, endangle);
angle2 = (startangle + endangle)/2;
midpos2 = arc->getCenter();
} else
} else if (geo2->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
// TODO: ellipse
const Part::GeomEllipse *ellipse = dynamic_cast<const Part::GeomEllipse *>(geo2);
r2 = ellipse->getMajorRadius();
angle2 = -ellipse->getAngleXU();
midpos2 = ellipse->getCenter();
}
else
break;
norm1 = Base::Vector3d(cos(angle1),sin(angle1),0);
@@ -3196,7 +3312,7 @@ Restart:
const Part::GeomLineSegment *lineSeg = dynamic_cast<const Part::GeomLineSegment *>(geo1);
Base::Vector3d dir = (lineSeg->getEndPoint() - lineSeg->getStartPoint()).Normalize();
Base::Vector3d norm(-dir.y, dir.x, 0);
if (geo2->getTypeId()== Part::GeomCircle::getClassTypeId()) {
if (geo2->getTypeId()== Part::GeomCircle::getClassTypeId()) { // TODO: ellipse
const Part::GeomCircle *circle = dynamic_cast<const Part::GeomCircle *>(geo2);
// tangency between a line and a circle
float length = (circle->getCenter() - lineSeg->getStartPoint())*dir;
@@ -3204,6 +3320,24 @@ Restart:
pos = lineSeg->getStartPoint() + dir * length;
relPos = norm * 1; //TODO Huh?
}
else if (geo2->getTypeId()== Part::GeomEllipse::getClassTypeId() ||
geo2->getTypeId()== Part::GeomArcOfEllipse::getClassTypeId()) { // TODO: ellipse
Base::Vector3d center;
if(geo2->getTypeId()== Part::GeomEllipse::getClassTypeId()){
const Part::GeomEllipse *ellipse = dynamic_cast<const Part::GeomEllipse *>(geo2);
center=ellipse->getCenter();
} else {
const Part::GeomArcOfEllipse *aoc = dynamic_cast<const Part::GeomArcOfEllipse *>(geo2);
center=aoc->getCenter();
}
// tangency between a line and an ellipse
float length = (center - lineSeg->getStartPoint())*dir;
pos = lineSeg->getStartPoint() + dir * length;
relPos = norm * 1;
}
else if (geo2->getTypeId()== Part::GeomArcOfCircle::getClassTypeId()) {
const Part::GeomArcOfCircle *arc = dynamic_cast<const Part::GeomArcOfCircle *>(geo2);
// tangency between a line and an arc
@@ -3214,7 +3348,7 @@ Restart:
}
}
if (geo1->getTypeId()== Part::GeomCircle::getClassTypeId() &&
if (geo1->getTypeId()== Part::GeomCircle::getClassTypeId() && // TODO: ellipse
geo2->getTypeId()== Part::GeomCircle::getClassTypeId()) {
const Part::GeomCircle *circle1 = dynamic_cast<const Part::GeomCircle *>(geo1);
const Part::GeomCircle *circle2 = dynamic_cast<const Part::GeomCircle *>(geo2);
@@ -3223,12 +3357,12 @@ Restart:
pos = circle1->getCenter() + dir * circle1->getRadius();
relPos = dir * 1;
}
else if (geo2->getTypeId()== Part::GeomCircle::getClassTypeId()) {
else if (geo2->getTypeId()== Part::GeomCircle::getClassTypeId()) { // TODO: ellipse
std::swap(geo1,geo2);
}
if (geo1->getTypeId()== Part::GeomCircle::getClassTypeId() &&
geo2->getTypeId()== Part::GeomArcOfCircle::getClassTypeId()) {
geo2->getTypeId()== Part::GeomArcOfCircle::getClassTypeId()) { // TODO: ellipse
const Part::GeomCircle *circle = dynamic_cast<const Part::GeomCircle *>(geo1);
const Part::GeomArcOfCircle *arc = dynamic_cast<const Part::GeomArcOfCircle *>(geo2);
// tangency between a circle and an arc
@@ -3368,7 +3502,7 @@ Restart:
asciiText->pnts.finishEditing();
}
break;
break;
case Radius:
{
assert(Constr->First >= -extGeoCount && Constr->First < intGeoCount);
@@ -3386,13 +3520,14 @@ Restart:
pnt1 = arc->getCenter();
pnt2 = pnt1 + radius * Base::Vector3d(cos(angle),sin(angle),0.);
}
else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) {
else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) {
const Part::GeomCircle *circle = dynamic_cast<const Part::GeomCircle *>(geo);
double radius = circle->getRadius();
double angle = (double) Constr->LabelPosition;
pnt1 = circle->getCenter();
pnt2 = pnt1 + radius * Base::Vector3d(cos(angle),sin(angle),0.);
} else
}
else
break;
} else
break;
@@ -3584,6 +3719,12 @@ void ViewProviderSketch::rebuildConstraintsVisual(void)
edit->vConstrType.push_back((*it)->Type);
}
break;
case InternalAlignment:
{
// TODO: Implement visual representation (if any)
edit->vConstrType.push_back((*it)->Type);
}
break;
default:
edit->vConstrType.push_back(None);
}