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

@@ -66,6 +66,7 @@
#include "EllipsePy.h"
#include "ArcPy.h"
#include "ArcOfCirclePy.h"
#include "ArcOfEllipsePy.h"
#include "BezierCurvePy.h"
#include "BSplineCurvePy.h"
#include "HyperbolaPy.h"
@@ -172,6 +173,7 @@ void PartExport initPart()
Base::Interpreter().addType(&Part::ParabolaPy ::Type,partModule,"Parabola");
Base::Interpreter().addType(&Part::ArcPy ::Type,partModule,"Arc");
Base::Interpreter().addType(&Part::ArcOfCirclePy ::Type,partModule,"ArcOfCircle");
Base::Interpreter().addType(&Part::ArcOfEllipsePy ::Type,partModule,"ArcOfEllipse");
Base::Interpreter().addType(&Part::BezierCurvePy ::Type,partModule,"BezierCurve");
Base::Interpreter().addType(&Part::BSplineCurvePy ::Type,partModule,"BSplineCurve");
Base::Interpreter().addType(&Part::OffsetCurvePy ::Type,partModule,"OffsetCurve");
@@ -261,6 +263,7 @@ void PartExport initPart()
Part::GeomBSplineCurve ::init();
Part::GeomCircle ::init();
Part::GeomArcOfCircle ::init();
Part::GeomArcOfEllipse ::init();
Part::GeomEllipse ::init();
Part::GeomHyperbola ::init();
Part::GeomParabola ::init();

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="GeometryCurvePy"
Name="ArcOfEllipsePy"
Twin="GeomArcOfEllipse"
TwinPointer="GeomArcOfEllipse"
Include="Mod/Part/App/Geometry.h"
Namespace="Part"
FatherInclude="Mod/Part/App/GeometryCurvePy.h"
FatherNamespace="Part"
Constructor="true">
<Documentation>
<Author Licence="LGPL" Name="Abdullah Tahiri" EMail="abdullah.tahiri.yo[at]gmail.com" />
<UserDocu>Describes a portion of an ellipse</UserDocu>
</Documentation>
<Attribute Name="MajorRadius" ReadOnly="false">
<Documentation>
<UserDocu>The major radius of the ellipse.</UserDocu>
</Documentation>
<Parameter Name="MajorRadius" Type="Float"/>
</Attribute>
<Attribute Name="MinorRadius" ReadOnly="false">
<Documentation>
<UserDocu>The minor radius of the ellipse.</UserDocu>
</Documentation>
<Parameter Name="MinorRadius" Type="Float"/>
</Attribute>
<Attribute Name="AngleXU" ReadOnly="false">
<Documentation>
<UserDocu>The angle between the X axis and the major axis of the ellipse.</UserDocu>
</Documentation>
<Parameter Name="AngleXU" Type="Float"/>
</Attribute>
<Attribute Name="Center" ReadOnly="false">
<Documentation>
<UserDocu>Center of the ellipse.</UserDocu>
</Documentation>
<Parameter Name="Center" Type="Object"/>
</Attribute>
<Attribute Name="Axis" ReadOnly="false">
<Documentation>
<UserDocu>The axis direction of the ellipse</UserDocu>
</Documentation>
<Parameter Name="Axis" Type="Object"/>
</Attribute>
<Attribute Name="Ellipse" ReadOnly="true">
<Documentation>
<UserDocu>The internal ellipse representation</UserDocu>
</Documentation>
<Parameter Name="Ellipse" Type="Object"/>
</Attribute>
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,233 @@
/***************************************************************************
* Copyright (c) 2014 Abdullah Tahiri <abdullah.tahiri.yo@gmail.com *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <gp_Elips.hxx>
# include <Geom_Ellipse.hxx>
# include <GC_MakeArcOfEllipse.hxx>
# include <GC_MakeEllipse.hxx>
# include <Geom_TrimmedCurve.hxx>
#endif
#include "Mod/Part/App/Geometry.h"
#include "ArcOfEllipsePy.h"
#include "ArcOfEllipsePy.cpp"
#include "EllipsePy.h"
#include "OCCError.h"
#include <Base/GeometryPyCXX.h>
#include <Base/VectorPy.h>
using namespace Part;
extern const char* gce_ErrorStatusText(gce_ErrorType et);
// returns a string which represents the object e.g. when printed in python
std::string ArcOfEllipsePy::representation(void) const
{
Handle_Geom_TrimmedCurve trim = Handle_Geom_TrimmedCurve::DownCast
(getGeomArcOfEllipsePtr()->handle());
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(trim->BasisCurve());
gp_Ax1 axis = ellipse->Axis();
gp_Dir dir = axis.Direction();
gp_Pnt loc = axis.Location();
Standard_Real fMajRad = ellipse->MajorRadius();
Standard_Real fMinRad = ellipse->MinorRadius();
Standard_Real u1 = trim->FirstParameter();
Standard_Real u2 = trim->LastParameter();
gp_Dir normal = ellipse->Axis().Direction();
gp_Dir xdir = ellipse->XAxis().Direction();
gp_Ax2 xdirref(loc, normal); // this is a reference XY for the ellipse
Standard_Real fAngleXU = -xdir.AngleWithRef(xdirref.XDirection(),normal);
std::stringstream str;
str << "ArcOfEllipse (";
str << "MajorRadius : " << fMajRad << ", ";
str << "MinorRadius : " << fMinRad << ", ";
str << "AngleXU : " << fAngleXU << ", ";
str << "Position : (" << loc.X() << ", "<< loc.Y() << ", "<< loc.Z() << "), ";
str << "Direction : (" << dir.X() << ", "<< dir.Y() << ", "<< dir.Z() << "), ";
str << "Parameter : (" << u1 << ", " << u2 << ")";
str << ")";
return str.str();
}
PyObject *ArcOfEllipsePy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
{
// create a new instance of ArcOfEllipsePy and the Twin object
return new ArcOfEllipsePy(new GeomArcOfEllipse);
}
// constructor method
int ArcOfEllipsePy::PyInit(PyObject* args, PyObject* kwds)
{
PyObject* o;
double u1, u2;
PyObject *sense=Py_True;
if (PyArg_ParseTuple(args, "O!dd|O!", &(Part::EllipsePy::Type), &o, &u1, &u2, &PyBool_Type, &sense)) {
try {
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast
(static_cast<EllipsePy*>(o)->getGeomEllipsePtr()->handle());
GC_MakeArcOfEllipse arc(ellipse->Elips(), u1, u2, PyObject_IsTrue(sense) ? Standard_True : Standard_False);
if (!arc.IsDone()) {
PyErr_SetString(PartExceptionOCCError, gce_ErrorStatusText(arc.Status()));
return -1;
}
getGeomArcOfEllipsePtr()->setHandle(arc.Value());
return 0;
}
catch (Standard_Failure) {
Handle_Standard_Failure e = Standard_Failure::Caught();
PyErr_SetString(PartExceptionOCCError, e->GetMessageString());
return -1;
}
catch (...) {
PyErr_SetString(PartExceptionOCCError, "creation of arc failed");
return -1;
}
}
// All checks failed
PyErr_SetString(PyExc_TypeError,
"ArcOfEllipse constructor expects an ellipse curve and a parameter range");
return -1;
}
Py::Float ArcOfEllipsePy::getMajorRadius(void) const
{
return Py::Float(getGeomArcOfEllipsePtr()->getMajorRadius());
}
void ArcOfEllipsePy::setMajorRadius(Py::Float arg)
{
getGeomArcOfEllipsePtr()->setMajorRadius((double)arg);
}
Py::Float ArcOfEllipsePy::getMinorRadius(void) const
{
return Py::Float(getGeomArcOfEllipsePtr()->getMinorRadius());
}
void ArcOfEllipsePy::setMinorRadius(Py::Float arg)
{
getGeomArcOfEllipsePtr()->setMinorRadius((double)arg);
}
Py::Float ArcOfEllipsePy::getAngleXU(void) const
{
return Py::Float(getGeomArcOfEllipsePtr()->getAngleXU());
}
void ArcOfEllipsePy::setAngleXU(Py::Float arg)
{
getGeomArcOfEllipsePtr()->setAngleXU((double)arg);
}
Py::Object ArcOfEllipsePy::getCenter(void) const
{
return Py::Vector(getGeomArcOfEllipsePtr()->getCenter());
}
void ArcOfEllipsePy::setCenter(Py::Object arg)
{
PyObject* p = arg.ptr();
if (PyObject_TypeCheck(p, &(Base::VectorPy::Type))) {
Base::Vector3d loc = static_cast<Base::VectorPy*>(p)->value();
getGeomArcOfEllipsePtr()->setCenter(loc);
}
else if (PyObject_TypeCheck(p, &PyTuple_Type)) {
Base::Vector3d loc = Base::getVectorFromTuple<double>(p);
getGeomArcOfEllipsePtr()->setCenter(loc);
}
else {
std::string error = std::string("type must be 'Vector', not ");
error += p->ob_type->tp_name;
throw Py::TypeError(error);
}
}
Py::Object ArcOfEllipsePy::getAxis(void) const
{
Handle_Geom_TrimmedCurve trim = Handle_Geom_TrimmedCurve::DownCast
(getGeomArcOfEllipsePtr()->handle());
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(trim->BasisCurve());
gp_Ax1 axis = ellipse->Axis();
gp_Dir dir = axis.Direction();
return Py::Vector(Base::Vector3d(dir.X(), dir.Y(), dir.Z()));
}
void ArcOfEllipsePy::setAxis(Py::Object arg)
{
PyObject* p = arg.ptr();
Base::Vector3d val;
if (PyObject_TypeCheck(p, &(Base::VectorPy::Type))) {
val = static_cast<Base::VectorPy*>(p)->value();
}
else if (PyTuple_Check(p)) {
val = Base::getVectorFromTuple<double>(p);
}
else {
std::string error = std::string("type must be 'Vector', not ");
error += p->ob_type->tp_name;
throw Py::TypeError(error);
}
Handle_Geom_TrimmedCurve trim = Handle_Geom_TrimmedCurve::DownCast
(getGeomArcOfEllipsePtr()->handle());
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(trim->BasisCurve());
try {
gp_Ax1 axis;
axis.SetLocation(ellipse->Location());
axis.SetDirection(gp_Dir(val.x, val.y, val.z));
ellipse->SetAxis(axis);
}
catch (Standard_Failure) {
throw Py::Exception("cannot set axis");
}
}
Py::Object ArcOfEllipsePy::getEllipse(void) const
{
Handle_Geom_TrimmedCurve trim = Handle_Geom_TrimmedCurve::DownCast
(getGeomArcOfEllipsePtr()->handle());
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(trim->BasisCurve());
return Py::Object(new EllipsePy(new GeomEllipse(ellipse)), true);
}
PyObject *ArcOfEllipsePy::getCustomAttributes(const char* attr) const
{
return 0;
}
int ArcOfEllipsePy::setCustomAttributes(const char* attr, PyObject *obj)
{
return 0;
}

View File

@@ -21,5 +21,12 @@
const Geom_Circle &amp; value(void) const {return *getGeom_CirclePtr();}
</ClassDeclarations>
-->
<!--
<ClassDeclarations>public:
ArcPy(const Geom_Ellipse &amp; circ, PyTypeObject *T = &amp;Type)
:PyObjectBase(new Geom_Ellipse(circ),T){}
const Geom_Ellipse &amp; value(void) const {return *getGeom_EllipsePtr();}
</ClassDeclarations>
-->
</PythonExport>
</GenerateModel>

View File

@@ -40,6 +40,7 @@ endif(FREETYPE_FOUND)
generate_from_xml(ArcPy)
generate_from_xml(ArcOfCirclePy)
generate_from_xml(CirclePy)
generate_from_xml(ArcOfEllipsePy)
generate_from_xml(EllipsePy)
generate_from_xml(HyperbolaPy)
generate_from_xml(ParabolaPy)
@@ -148,6 +149,8 @@ SET(Python_SRCS
ArcOfCirclePyImp.cpp
CirclePy.xml
CirclePyImp.cpp
ArcOfEllipsePy.xml
ArcOfEllipsePyImp.cpp
EllipsePy.xml
EllipsePyImp.cpp
HyperbolaPy.xml

View File

@@ -46,6 +46,12 @@
</Documentation>
<Parameter Name="MinorRadius" Type="Float"/>
</Attribute>
<Attribute Name="AngleXU" ReadOnly="false">
<Documentation>
<UserDocu>The angle between the X axis and the major axis of the ellipse.</UserDocu>
</Documentation>
<Parameter Name="AngleXU" Type="Float"/>
</Attribute>
<Attribute Name="Eccentricity" ReadOnly="true">
<Documentation>
<UserDocu>The eccentricity of the ellipse.</UserDocu>

View File

@@ -151,6 +151,38 @@ void EllipsePy::setMinorRadius(Py::Float arg)
ellipse->SetMinorRadius((double)arg);
}
Py::Float EllipsePy::getAngleXU(void) const
{
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(getGeomEllipsePtr()->handle());
gp_Pnt center = ellipse->Axis().Location();
gp_Dir normal = ellipse->Axis().Direction();
gp_Dir xdir = ellipse->XAxis().Direction();
gp_Ax2 xdirref(center, normal); // this is a reference system, might be CCW or CW depending on the creation method
return Py::Float(-xdir.AngleWithRef(xdirref.XDirection(),normal));
}
void EllipsePy::setAngleXU(Py::Float arg)
{
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(getGeomEllipsePtr()->handle());
gp_Pnt center = ellipse->Axis().Location();
gp_Dir normal = ellipse->Axis().Direction();
gp_Ax1 normaxis(center, normal);
gp_Ax2 xdirref(center, normal);
xdirref.Rotate(normaxis,arg);
ellipse->SetPosition(xdirref);
}
Py::Float EllipsePy::getEccentricity(void) const
{
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(getGeomEllipsePtr()->handle());

View File

@@ -78,6 +78,7 @@
# include <Geom_TrimmedCurve.hxx>
# include <GC_MakeArcOfCircle.hxx>
# include <GC_MakeCircle.hxx>
# include <GC_MakeArcOfEllipse.hxx>
# include <GC_MakeEllipse.hxx>
# include <GC_MakeLine.hxx>
# include <GC_MakeSegment.hxx>
@@ -91,6 +92,7 @@
#include "EllipsePy.h"
#include "ArcPy.h"
#include "ArcOfCirclePy.h"
#include "ArcOfEllipsePy.h"
#include "BezierCurvePy.h"
#include "BSplineCurvePy.h"
#include "HyperbolaPy.h"
@@ -888,6 +890,44 @@ void GeomEllipse::setMinorRadius(double Radius)
}
}
double GeomEllipse::getAngleXU(void) const
{
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(handle());
gp_Pnt center = this->myCurve->Axis().Location();
gp_Dir normal = this->myCurve->Axis().Direction();
gp_Dir xdir = this->myCurve->XAxis().Direction();
gp_Ax2 xdirref(center, normal); // this is a reference system, might be CCW or CW depending on the creation method
return -xdir.AngleWithRef(xdirref.XDirection(),normal);
}
void GeomEllipse::setAngleXU(double angle)
{
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(handle());
try {
gp_Pnt center = this->myCurve->Axis().Location();
gp_Dir normal = this->myCurve->Axis().Direction();
gp_Ax1 normaxis(center, normal);
gp_Ax2 xdirref(center, normal);
xdirref.Rotate(normaxis,angle);
this->myCurve->SetPosition(xdirref);
}
catch (Standard_Failure) {
Handle_Standard_Failure e = Standard_Failure::Caught();
throw Base::Exception(e->GetMessageString());
}
}
// Persistence implementer
unsigned int GeomEllipse::getMemSize (void) const
{
@@ -901,7 +941,13 @@ void GeomEllipse::Save(Base::Writer& writer) const
gp_Pnt center = this->myCurve->Axis().Location();
gp_Dir normal = this->myCurve->Axis().Direction();
gp_Dir xdir = this->myCurve->XAxis().Direction();
gp_Ax2 xdirref(center, normal); // this is a reference XY for the ellipse
double AngleXU = -xdir.AngleWithRef(xdirref.XDirection(),normal);
writer.Stream()
<< writer.ind()
<< "<Ellipse "
@@ -913,6 +959,7 @@ void GeomEllipse::Save(Base::Writer& writer) const
<< "NormalZ=\"" << normal.Z() << "\" "
<< "MajorRadius=\"" << this->myCurve->MajorRadius() << "\" "
<< "MinorRadius=\"" << this->myCurve->MinorRadius() << "\" "
<< "AngleXU=\"" << AngleXU << "\" "
<< "/>" << endl;
}
@@ -921,7 +968,7 @@ void GeomEllipse::Restore(Base::XMLReader& reader)
// read the attributes of the father class
GeomCurve::Restore(reader);
double CenterX,CenterY,CenterZ,NormalX,NormalY,NormalZ,MajorRadius,MinorRadius;
double CenterX,CenterY,CenterZ,NormalX,NormalY,NormalZ,MajorRadius,MinorRadius,AngleXU;
// read my Element
reader.readElement("Ellipse");
// get the value of my Attribute
@@ -933,12 +980,25 @@ void GeomEllipse::Restore(Base::XMLReader& reader)
NormalZ = reader.getAttributeAsFloat("NormalZ");
MajorRadius = reader.getAttributeAsFloat("MajorRadius");
MinorRadius = reader.getAttributeAsFloat("MinorRadius");
// This is for backwards compatibility
if(reader.hasAttribute("AngleXU"))
AngleXU = reader.getAttributeAsFloat("AngleXU");
else
AngleXU = 0;
// set the read geometry
gp_Pnt p1(CenterX,CenterY,CenterZ);
gp_Dir norm(NormalX,NormalY,NormalZ);
gp_Ax1 normaxis(p1,norm);
gp_Ax2 xdir(p1, norm);
xdir.Rotate(normaxis,AngleXU);
try {
GC_MakeEllipse mc(gp_Ax2(p1, norm), MajorRadius, MinorRadius);
GC_MakeEllipse mc(xdir, MajorRadius, MinorRadius);
if (!mc.IsDone())
throw Base::Exception(gce_ErrorStatusText(mc.Status()));
@@ -955,6 +1015,271 @@ PyObject *GeomEllipse::getPyObject(void)
return new EllipsePy((GeomEllipse*)this->clone());
}
// -------------------------------------------------
TYPESYSTEM_SOURCE(Part::GeomArcOfEllipse,Part::GeomCurve);
GeomArcOfEllipse::GeomArcOfEllipse()
{
Handle_Geom_Ellipse e = new Geom_Ellipse(gp_Elips());
this->myCurve = new Geom_TrimmedCurve(e, e->FirstParameter(),e->LastParameter());
}
GeomArcOfEllipse::GeomArcOfEllipse(const Handle_Geom_Ellipse& e)
{
this->myCurve = new Geom_TrimmedCurve(e, e->FirstParameter(),e->LastParameter());
}
GeomArcOfEllipse::~GeomArcOfEllipse()
{
}
void GeomArcOfEllipse::setHandle(const Handle_Geom_TrimmedCurve& c)
{
Handle_Geom_Ellipse basis = Handle_Geom_Ellipse::DownCast(c->BasisCurve());
if (basis.IsNull())
Standard_Failure::Raise("Basis curve is not an ellipse");
this->myCurve = Handle_Geom_TrimmedCurve::DownCast(c->Copy());
}
const Handle_Geom_Geometry& GeomArcOfEllipse::handle() const
{
return myCurve;
}
Geometry *GeomArcOfEllipse::clone(void) const
{
GeomArcOfEllipse* copy = new GeomArcOfEllipse();
copy->setHandle(this->myCurve);
copy->Construction = this->Construction;
return copy;
}
Base::Vector3d GeomArcOfEllipse::getStartPoint() const
{
gp_Pnt pnt = this->myCurve->StartPoint();
return Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z());
}
Base::Vector3d GeomArcOfEllipse::getEndPoint() const
{
gp_Pnt pnt = this->myCurve->EndPoint();
return Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z());
}
Base::Vector3d GeomArcOfEllipse::getCenter(void) const
{
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(myCurve->BasisCurve());
gp_Ax1 axis = ellipse->Axis();
const gp_Pnt& loc = axis.Location();
return Base::Vector3d(loc.X(),loc.Y(),loc.Z());
}
void GeomArcOfEllipse::setCenter(const Base::Vector3d& Center)
{
gp_Pnt p1(Center.x,Center.y,Center.z);
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(myCurve->BasisCurve());
try {
ellipse->SetLocation(p1);
}
catch (Standard_Failure) {
Handle_Standard_Failure e = Standard_Failure::Caught();
throw Base::Exception(e->GetMessageString());
}
}
double GeomArcOfEllipse::getMajorRadius(void) const
{
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(myCurve->BasisCurve());
return ellipse->MajorRadius();
}
void GeomArcOfEllipse::setMajorRadius(double Radius)
{
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(myCurve->BasisCurve());
try {
ellipse->SetMajorRadius(Radius);
}
catch (Standard_Failure) {
Handle_Standard_Failure e = Standard_Failure::Caught();
throw Base::Exception(e->GetMessageString());
}
}
double GeomArcOfEllipse::getMinorRadius(void) const
{
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(myCurve->BasisCurve());
return ellipse->MinorRadius();
}
void GeomArcOfEllipse::setMinorRadius(double Radius)
{
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(myCurve->BasisCurve());
try {
ellipse->SetMinorRadius(Radius);
}
catch (Standard_Failure) {
Handle_Standard_Failure e = Standard_Failure::Caught();
throw Base::Exception(e->GetMessageString());
}
}
double GeomArcOfEllipse::getAngleXU(void) const
{
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(myCurve->BasisCurve());
gp_Pnt center = ellipse->Axis().Location();
gp_Dir normal = ellipse->Axis().Direction();
gp_Dir xdir = ellipse->XAxis().Direction();
gp_Ax2 xdirref(center, normal); // this is a reference system, might be CCW or CW depending on the creation method
return -xdir.AngleWithRef(xdirref.XDirection(),normal);
}
void GeomArcOfEllipse::setAngleXU(double angle)
{
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(myCurve->BasisCurve());
try {
gp_Pnt center = ellipse->Axis().Location();
gp_Dir normal = ellipse->Axis().Direction();
gp_Ax1 normaxis(center, normal);
gp_Ax2 xdirref(center, normal);
xdirref.Rotate(normaxis,angle);
ellipse->SetPosition(xdirref);
}
catch (Standard_Failure) {
Handle_Standard_Failure e = Standard_Failure::Caught();
throw Base::Exception(e->GetMessageString());
}
}
void GeomArcOfEllipse::getRange(double& u, double& v) const
{
u = myCurve->FirstParameter();
v = myCurve->LastParameter();
}
void GeomArcOfEllipse::setRange(double u, double v)
{
try {
myCurve->SetTrim(u, v);
}
catch (Standard_Failure) {
Handle_Standard_Failure e = Standard_Failure::Caught();
throw Base::Exception(e->GetMessageString());
}
}
// Persistence implementer
unsigned int GeomArcOfEllipse::getMemSize (void) const
{
return sizeof(Geom_Ellipse) + 2 *sizeof(double);
}
void GeomArcOfEllipse::Save(Base::Writer &writer) const
{
// save the attributes of the father class
GeomCurve::Save(writer);
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(this->myCurve->BasisCurve());
gp_Pnt center = ellipse->Axis().Location();
gp_Dir normal = ellipse->Axis().Direction();
gp_Dir xdir = ellipse->XAxis().Direction();
gp_Ax2 xdirref(center, normal); // this is a reference XY for the ellipse
double AngleXU = -xdir.AngleWithRef(xdirref.XDirection(),normal);
writer.Stream()
<< writer.ind()
<< "<ArcOfEllipse "
<< "CenterX=\"" << center.X() << "\" "
<< "CenterY=\"" << center.Y() << "\" "
<< "CenterZ=\"" << center.Z() << "\" "
<< "NormalX=\"" << normal.X() << "\" "
<< "NormalY=\"" << normal.Y() << "\" "
<< "NormalZ=\"" << normal.Z() << "\" "
<< "MajorRadius=\"" << ellipse->MajorRadius() << "\" "
<< "MinorRadius=\"" << ellipse->MinorRadius() << "\" "
<< "AngleXU=\"" << AngleXU << "\" "
<< "StartAngle=\"" << this->myCurve->FirstParameter() << "\" "
<< "EndAngle=\"" << this->myCurve->LastParameter() << "\" "
<< "/>" << endl;
}
void GeomArcOfEllipse::Restore(Base::XMLReader &reader)
{
// read the attributes of the father class
GeomCurve::Restore(reader);
double CenterX,CenterY,CenterZ,NormalX,NormalY,NormalZ,MajorRadius,MinorRadius,AngleXU,StartAngle,EndAngle;
// read my Element
reader.readElement("ArcOfEllipse");
// get the value of my Attribute
CenterX = reader.getAttributeAsFloat("CenterX");
CenterY = reader.getAttributeAsFloat("CenterY");
CenterZ = reader.getAttributeAsFloat("CenterZ");
NormalX = reader.getAttributeAsFloat("NormalX");
NormalY = reader.getAttributeAsFloat("NormalY");
NormalZ = reader.getAttributeAsFloat("NormalZ");
MajorRadius = reader.getAttributeAsFloat("MajorRadius");
MinorRadius = reader.getAttributeAsFloat("MinorRadius");
AngleXU = reader.getAttributeAsFloat("AngleXU");
StartAngle = reader.getAttributeAsFloat("StartAngle");
EndAngle = reader.getAttributeAsFloat("EndAngle");
// set the read geometry
gp_Pnt p1(CenterX,CenterY,CenterZ);
gp_Dir norm(NormalX,NormalY,NormalZ);
gp_Ax1 normaxis(p1,norm);
gp_Ax2 xdir(p1, norm);
xdir.Rotate(normaxis,AngleXU);
try {
GC_MakeEllipse mc(xdir, MajorRadius, MinorRadius);
if (!mc.IsDone())
throw Base::Exception(gce_ErrorStatusText(mc.Status()));
GC_MakeArcOfEllipse ma(mc.Value()->Elips(), StartAngle, EndAngle, 1);
if (!ma.IsDone())
throw Base::Exception(gce_ErrorStatusText(ma.Status()));
Handle_Geom_TrimmedCurve tmpcurve = ma.Value();
Handle_Geom_Ellipse tmpellipse = Handle_Geom_Ellipse::DownCast(tmpcurve->BasisCurve());
Handle_Geom_Ellipse ellipse = Handle_Geom_Ellipse::DownCast(this->myCurve->BasisCurve());
ellipse->SetElips(tmpellipse->Elips());
this->myCurve->SetTrim(tmpcurve->FirstParameter(), tmpcurve->LastParameter());
}
catch (Standard_Failure) {
Handle_Standard_Failure e = Standard_Failure::Caught();
throw Base::Exception(e->GetMessageString());
}
}
PyObject *GeomArcOfEllipse::getPyObject(void)
{
return new ArcOfEllipsePy(static_cast<GeomArcOfEllipse*>(this->clone()));
}
// -------------------------------------------------
TYPESYSTEM_SOURCE(Part::GeomHyperbola,Part::GeomCurve);

View File

@@ -244,6 +244,8 @@ public:
void setMajorRadius(double Radius);
double getMinorRadius(void) const;
void setMinorRadius(double Radius);
double getAngleXU(void) const;
void setAngleXU(double angle);
// Persistence implementer ---------------------
virtual unsigned int getMemSize(void) const;
@@ -258,6 +260,45 @@ private:
Handle_Geom_Ellipse myCurve;
};
class PartExport GeomArcOfEllipse : public GeomCurve
{
TYPESYSTEM_HEADER();
public:
GeomArcOfEllipse();
GeomArcOfEllipse(const Handle_Geom_Ellipse&);
virtual ~GeomArcOfEllipse();
virtual Geometry *clone(void) const;
Base::Vector3d getStartPoint() const;
Base::Vector3d getEndPoint() const;
Base::Vector3d getCenter(void) const;
void setCenter(const Base::Vector3d& Center);
double getMajorRadius(void) const;
void setMajorRadius(double Radius);
double getMinorRadius(void) const;
void setMinorRadius(double Radius);
double getAngleXU(void) const;
void setAngleXU(double angle);
void getRange(double& u, double& v) const;
void setRange(double u, double v);
// Persistence implementer ---------------------
virtual unsigned int getMemSize(void) const;
virtual void Save(Base::Writer &/*writer*/) const;
virtual void Restore(Base::XMLReader &/*reader*/);
// Base implementer ----------------------------
virtual PyObject *getPyObject(void);
void setHandle(const Handle_Geom_TrimmedCurve&);
const Handle_Geom_Geometry& handle() const;
private:
Handle_Geom_TrimmedCurve myCurve;
};
class PartExport GeomHyperbola : public GeomCurve
{
TYPESYSTEM_HEADER();
@@ -340,7 +381,7 @@ public:
Base::Vector3d getStartPoint() const;
Base::Vector3d getEndPoint() const;
void setPoints(const Base::Vector3d& p1,
void setPoints(const Base::Vector3d& p1,
const Base::Vector3d& p2);
// Persistence implementer ---------------------
@@ -674,14 +715,14 @@ bool find2DLinesIntersection(const GeomLineSegment *lineSeg1, const GeomLineSegm
PartExport
bool findFilletCenter(const GeomLineSegment *lineSeg1, const GeomLineSegment *lineSeg2, double radius,
Base::Vector3d &center);
PartExport
PartExport
bool findFilletCenter(const GeomLineSegment *lineSeg1, const GeomLineSegment *lineSeg2, double radius,
const Base::Vector3d& refPnt1, const Base::Vector3d& refPnt2,
Base::Vector3d &center);
PartExport
double suggestFilletRadius(const GeomLineSegment *lineSeg1, const GeomLineSegment *lineSeg2,
const Base::Vector3d &refPnt1, const Base::Vector3d &refPnt2);
PartExport
PartExport
GeomArcOfCircle *createFilletGeometry(const GeomLineSegment *lineSeg1, const GeomLineSegment *lineSeg2,
const Base::Vector3d &center, double radius);
}

View File

@@ -0,0 +1,309 @@
lib_LTLIBRARIES=libPart.la Part.la
BUILT_SOURCES=\
ArcPy.cpp \
ArcOfCirclePy.cpp \
ArcOfEllipsePy.cpp \
BRepOffsetAPI_MakePipeShellPy.cpp \
CirclePy.cpp \
EllipsePy.cpp \
HyperbolaPy.cpp \
ParabolaPy.cpp \
OffsetCurvePy.cpp \
GeometryPy.cpp \
GeometryCurvePy.cpp \
GeometrySurfacePy.cpp \
LinePy.cpp \
PointPy.cpp \
BezierCurvePy.cpp \
BSplineCurvePy.cpp \
PlanePy.cpp \
ConePy.cpp \
CylinderPy.cpp \
SpherePy.cpp \
ToroidPy.cpp \
BezierSurfacePy.cpp \
BSplineSurfacePy.cpp \
OffsetSurfacePy.cpp \
RectangularTrimmedSurfacePy.cpp \
SurfaceOfExtrusionPy.cpp \
SurfaceOfRevolutionPy.cpp \
PartFeaturePy.cpp \
FeaturePythonPy.cpp \
Part2DObjectPy.cpp \
TopoShapeCompoundPy.cpp \
TopoShapeCompSolidPy.cpp \
TopoShapeEdgePy.cpp \
TopoShapeFacePy.cpp \
TopoShapeShellPy.cpp \
TopoShapeSolidPy.cpp \
TopoShapeVertexPy.cpp \
TopoShapeWirePy.cpp \
TopoShapePy.cpp
libPart_la_BUILT=\
ArcPy.h \
ArcOfCirclePy.h \
ArcOfEllipsePy.h \
BRepOffsetAPI_MakePipeShellPy.h \
CirclePy.h \
EllipsePy.h \
HyperbolaPy.h \
ParabolaPy.h \
OffsetCurvePy.h \
GeometryPy.h \
GeometryCurvePy.h \
GeometrySurfacePy.h \
LinePy.h \
PointPy.h \
BezierCurvePy.h \
BSplineCurvePy.h \
PlanePy.h \
ConePy.h \
CylinderPy.h \
SpherePy.h \
ToroidPy.h \
BezierSurfacePy.h \
BSplineSurfacePy.h \
OffsetSurfacePy.h \
RectangularTrimmedSurfacePy.h \
SurfaceOfExtrusionPy.h \
SurfaceOfRevolutionPy.h \
PartFeaturePy.h \
FeaturePythonPy.h \
Part2DObjectPy.h \
TopoShapeCompoundPy.h \
TopoShapeCompSolidPy.h \
TopoShapeEdgePy.h \
TopoShapeFacePy.h \
TopoShapeShellPy.h \
TopoShapeSolidPy.h \
TopoShapeVertexPy.h \
TopoShapeWirePy.h \
TopoShapePy.h
libPart_la_SOURCES=\
AppPartPy.cpp \
ArcPyImp.cpp \
ArcOfCirclePyImp.cpp \
ArcOfEllipsePyImp.cpp \
BRepOffsetAPI_MakePipeShellPyImp.cpp \
CirclePyImp.cpp \
CrossSection.cpp \
EllipsePyImp.cpp \
HyperbolaPyImp.cpp \
ParabolaPyImp.cpp \
OffsetCurvePyImp.cpp \
GeometryPyImp.cpp \
GeometryCurvePyImp.cpp \
GeometrySurfacePyImp.cpp \
LinePyImp.cpp \
PointPyImp.cpp \
BezierCurvePyImp.cpp \
BSplineCurvePyImp.cpp \
PlanePyImp.cpp \
ConePyImp.cpp \
CylinderPyImp.cpp \
SpherePyImp.cpp \
ToroidPyImp.cpp \
BezierSurfacePyImp.cpp \
BSplineSurfacePyImp.cpp \
OffsetSurfacePyImp.cpp \
RectangularTrimmedSurfacePyImp.cpp \
SurfaceOfExtrusionPyImp.cpp \
SurfaceOfRevolutionPyImp.cpp \
edgecluster.cpp \
FeaturePartBoolean.cpp \
FeaturePartBox.cpp \
FeaturePartCircle.cpp \
FeaturePartCurveNet.cpp \
FeaturePartCommon.cpp \
FeaturePartCut.cpp \
FeaturePartFuse.cpp \
FeaturePartImportBrep.cpp \
FeaturePartImportIges.cpp \
FeaturePartImportStep.cpp \
FeaturePartPolygon.cpp \
FeaturePartSection.cpp \
FeatureChamfer.cpp \
FeatureExtrusion.cpp \
FeatureFillet.cpp \
FeatureGeometrySet.cpp \
FeatureRevolution.cpp \
FeatureMirroring.cpp \
PartFeatures.cpp \
Geometry.cpp \
ImportIges.cpp \
ImportStep.cpp \
modelRefine.cpp \
CustomFeature.cpp \
PartFeature.cpp \
PartFeatureReference.cpp \
PartFeaturePyImp.cpp \
FeaturePythonPyImp.cpp \
Part2DObject.cpp \
Part2DObjectPyImp.cpp \
PreCompiled.cpp \
PreCompiled.h \
PrimitiveFeature.cpp \
ProgressIndicator.cpp \
PropertyGeometryList.cpp \
PropertyTopoShape.cpp \
TopoShape.cpp \
TopoShapeCompoundPyImp.cpp \
TopoShapeCompSolidPyImp.cpp \
TopoShapeEdgePyImp.cpp \
TopoShapeFacePyImp.cpp \
TopoShapeShellPyImp.cpp \
TopoShapeSolidPyImp.cpp \
TopoShapeVertexPyImp.cpp \
TopoShapeWirePyImp.cpp \
TopoShapePyImp.cpp
nodist_include_HEADERS=\
$(libPart_la_BUILT)
include_HEADERS=\
CrossSection.h \
edgecluster.h \
FeaturePartBoolean.h \
FeaturePartBox.h \
FeaturePartCircle.h \
FeaturePartCurveNet.h \
FeaturePartCommon.h \
FeaturePartCut.h \
FeaturePartFuse.h \
FeaturePartImportBrep.h \
FeaturePartImportIges.h \
FeaturePartImportStep.h \
FeaturePartPolygon.h \
FeaturePartSection.h \
FeatureChamfer.h \
FeatureExtrusion.h \
FeatureFillet.h \
FeatureGeometrySet.h \
FeatureRevolution.h \
FeatureMirroring.h \
PartFeatures.h \
Geometry.h \
ImportIges.h \
ImportStep.h \
modelRefine.h \
PartFeature.h \
PartFeatureReference.h \
CustomFeature.h \
Part2DObject.h \
PrimitiveFeature.h \
ProgressIndicator.h \
PropertyGeometryList.h \
PropertyTopoShape.h \
Tools.h \
TopoShape.h
# the library search path.
libPart_la_LDFLAGS = -L../../../Base -L../../../App -L/usr/X11R6/lib -L$(OCC_LIB) $(all_libraries) \
-version-info @LIB_CURRENT@:@LIB_REVISION@:@LIB_AGE@
libPart_la_CPPFLAGS = -DPartExport=
libPart_la_LIBADD = \
@BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ \
-l@PYTHON_LIB@ \
-lxerces-c \
-lFreeCADBase \
-lFreeCADApp \
-lTKernel \
-lTKFillet \
-lTKG2d \
-lTKG3d \
-lTKMath \
-lTKMesh \
-lTKSTEP \
-lTKSTEPAttr \
-lTKSTEPBase \
-lTKIGES \
-lTKSTL \
-lTKShHealing \
-lTKXSBase \
-lTKBool \
-lTKBO \
-lTKBRep \
-lTKTopAlgo \
-lTKGeomAlgo \
-lTKGeomBase \
-lTKOffset \
-lTKPrim
%.cpp: %.xml $(top_srcdir)/src/Tools/generateTemplates/templateClassPyExport.py
$(PYTHON) $(top_srcdir)/src/Tools/generate.py --outputPath $(@D) $<
#--------------------------------------------------------------------------------------
# Loader of libPart
Part_la_SOURCES=\
AppPart.cpp
# the library search path.
Part_la_LDFLAGS = $(libPart_la_LDFLAGS) -module -avoid-version
Part_la_CPPFLAGS = $(libPart_la_CPPFLAGS)
Part_la_LIBADD = \
$(libPart_la_LIBADD) \
-lPart
Part_la_DEPENDENCIES = libPart.la
#--------------------------------------------------------------------------------------
# set the include path found by configure
AM_CXXFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src $(all_includes) -I$(OCC_INC)
includedir = @includedir@/Mod/Part/App
libdir = $(prefix)/Mod/Part
CLEANFILES = $(BUILT_SOURCES) $(libPart_la_BUILT)
EXTRA_DIST = \
OpenCascadeAll.h \
ArcPy.xml \
ArcOfCirclePy.xml \
ArcOfEllipsePy.xml \
BRepOffsetAPI_MakePipeShellPy.xml \
CirclePy.xml \
EllipsePy.xml \
HyperbolaPy.xml \
ParabolaPy.xml \
OffsetCurvePy.xml \
GeometryPy.xml \
GeometryCurvePy.xml \
GeometrySurfacePy.xml \
LinePy.xml \
PointPy.xml \
BezierCurvePy.xml \
BSplineCurvePy.xml \
PlanePy.xml \
ConePy.xml \
CylinderPy.xml \
SpherePy.xml \
ToroidPy.xml \
BezierSurfacePy.xml \
BSplineSurfacePy.xml \
OffsetSurfacePy.xml \
RectangularTrimmedSurfacePy.xml \
SurfaceOfExtrusionPy.xml \
SurfaceOfRevolutionPy.xml \
PartFeaturePy.xml \
FeaturePythonPy.xml \
Part2DObjectPy.xml \
TopoShapePy.xml \
TopoShapeCompSolidPy.xml \
TopoShapeCompoundPy.xml \
TopoShapeEdgePy.xml \
TopoShapeFacePy.xml \
TopoShapeShellPy.xml \
TopoShapeSolidPy.xml \
TopoShapeVertexPy.xml \
TopoShapeWirePy.xml \
CMakeLists.txt

View File

@@ -172,6 +172,10 @@ Gui::MenuItem* Workbench::setupMenuBar() const
Gui::MenuItem* cons = new Gui::MenuItem();
cons->setCommand("Sketcher constraints");
SketcherGui::addSketcherWorkbenchConstraints( *cons );
Gui::MenuItem* consaccel = new Gui::MenuItem();
consaccel->setCommand("Sketcher tools");
SketcherGui::addSketcherWorkbenchTools(*consaccel);
Gui::MenuItem* part = new Gui::MenuItem;
root->insertItem(item, part);
@@ -233,6 +237,10 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
cons->setCommand("Sketcher constraints");
SketcherGui::addSketcherWorkbenchConstraints( *cons );
Gui::ToolBarItem* consaccel = new Gui::ToolBarItem(root);
consaccel->setCommand("Sketcher tools");
SketcherGui::addSketcherWorkbenchTools( *consaccel );
return root;
}

View File

@@ -43,6 +43,7 @@ const int Constraint::GeoUndef = -2000;
Constraint::Constraint()
: Type(None),
AlignmentType(Undef),
Name(""),
Value(0.0),
First(GeoUndef),
@@ -58,6 +59,7 @@ Constraint::Constraint()
Constraint::Constraint(const Constraint& from)
: Type(from.Type),
AlignmentType(from.AlignmentType),
Name(from.Name),
Value(from.Value),
First(from.First),
@@ -92,18 +94,22 @@ unsigned int Constraint::getMemSize (void) const
void Constraint::Save (Writer &writer) const
{
writer.Stream() << writer.ind() << "<Constrain "
<< "Name=\"" << Name << "\" "
<< "Type=\"" << (int)Type << "\" "
<< "Value=\"" << Value << "\" "
<< "First=\"" << First << "\" "
<< "FirstPos=\"" << (int) FirstPos << "\" "
<< "Second=\"" << Second << "\" "
<< "SecondPos=\"" << (int) SecondPos << "\" "
<< "Third=\"" << Third << "\" "
<< "ThirdPos=\"" << (int) ThirdPos << "\" "
<< "LabelDistance=\"" << LabelDistance << "\" "
<< "LabelPosition=\"" << LabelPosition << "\" />"
writer.Stream() << writer.ind() << "<Constrain "
<< "Name=\"" << Name << "\" "
<< "Type=\"" << (int)Type << "\" ";
if(this->Type==InternalAlignment)
writer.Stream()
<< "InternalAlignmentType=\"" << (int)AlignmentType << "\" ";
writer.Stream()
<< "Value=\"" << Value << "\" "
<< "First=\"" << First << "\" "
<< "FirstPos=\"" << (int) FirstPos << "\" "
<< "Second=\"" << Second << "\" "
<< "SecondPos=\"" << (int) SecondPos << "\" "
<< "Third=\"" << Third << "\" "
<< "ThirdPos=\"" << (int) ThirdPos << "\" "
<< "LabelDistance=\"" << LabelDistance << "\" "
<< "LabelPosition=\"" << LabelPosition << "\" />"
<< std::endl;
}
@@ -118,6 +124,11 @@ void Constraint::Restore(XMLReader &reader)
Second = reader.getAttributeAsInteger("Second");
SecondPos = (PointPos) reader.getAttributeAsInteger("SecondPos");
if(this->Type==InternalAlignment)
AlignmentType = (InternalAlignmentType) reader.getAttributeAsInteger("InternalAlignmentType");
else
AlignmentType = Undef;
// read the third geo group if present
if (reader.hasAttribute("Third")) {
Third = reader.getAttributeAsInteger("Third");

View File

@@ -31,21 +31,30 @@ namespace Sketcher
{
enum ConstraintType {
None,
Coincident,
Horizontal,
Vertical,
Parallel,
Tangent,
Distance,
DistanceX,
DistanceY,
Angle,
Perpendicular,
Radius,
Equal,
PointOnObject,
Symmetric
None = 0,
Coincident = 1,
Horizontal = 2,
Vertical = 3,
Parallel = 4,
Tangent = 5,
Distance = 6,
DistanceX = 7,
DistanceY = 8,
Angle = 9,
Perpendicular = 10,
Radius = 11,
Equal = 12,
PointOnObject = 13,
Symmetric = 14,
InternalAlignment = 15
};
enum InternalAlignmentType {
Undef = 0,
EllipseMajorDiameter = 1,
EllipseMinorDiameter = 2,
EllipseFocus1 = 3,
EllipseFocus2 = 4
};
/// define if you want to use the end or start point
@@ -74,6 +83,7 @@ public:
public:
ConstraintType Type;
InternalAlignmentType AlignmentType;
std::string Name;
double Value;
int First;

View File

@@ -93,6 +93,20 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
this->getConstraintPtr()->Type = Equal;
valid = true;
}
else if (strstr(ConstraintType,"InternalAlignment") != NULL) {
this->getConstraintPtr()->Type = InternalAlignment;
valid = true;
if(strstr(ConstraintType,"EllipseMajorDiameter") != NULL)
this->getConstraintPtr()->AlignmentType=EllipseMajorDiameter;
else if(strstr(ConstraintType,"EllipseMinorDiameter") != NULL)
this->getConstraintPtr()->AlignmentType=EllipseMinorDiameter;
else {
this->getConstraintPtr()->AlignmentType=Undef;
valid = false;
}
}
if (valid) {
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->Second = SecondIndex;
@@ -155,6 +169,20 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
this->getConstraintPtr()->Type = PointOnObject;
valid = true;
}
else if (strstr(ConstraintType,"InternalAlignment") != NULL) {
this->getConstraintPtr()->Type = InternalAlignment;
valid = true;
if(strstr(ConstraintType,"EllipseFocus1") != NULL)
this->getConstraintPtr()->AlignmentType=EllipseFocus1;
else if(strstr(ConstraintType,"EllipseFocus2") != NULL)
this->getConstraintPtr()->AlignmentType=EllipseFocus2;
else {
this->getConstraintPtr()->AlignmentType=Undef;
valid = false;
}
}
if (valid) {
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->FirstPos = (Sketcher::PointPos) FirstPos;
@@ -340,17 +368,27 @@ std::string ConstraintPy::representation(void) const
std::stringstream result;
result << "<Constraint " ;
switch(this->getConstraintPtr()->Type) {
case None : result << "'None'>";break;
case DistanceX : result << "'DistanceX'>";break;
case DistanceY : result << "'DistanceY'>";break;
case Coincident : result << "'Coincident'>";break;
case Horizontal : result << "'Horizontal' (" << getConstraintPtr()->First << ")>";break;
case Vertical : result << "'Vertical' (" << getConstraintPtr()->First << ")>";break;
case Parallel : result << "'Parallel'>";break;
case Tangent : result << "'Tangent'>";break;
case Distance : result << "'Distance'>";break;
case Angle : result << "'Angle'>";break;
default : result << "'?'>";break;
case None : result << "'None'>";break;
case DistanceX : result << "'DistanceX'>";break;
case DistanceY : result << "'DistanceY'>";break;
case Coincident : result << "'Coincident'>";break;
case Horizontal : result << "'Horizontal' (" << getConstraintPtr()->First << ")>";break;
case Vertical : result << "'Vertical' (" << getConstraintPtr()->First << ")>";break;
case Parallel : result << "'Parallel'>";break;
case Tangent : result << "'Tangent'>";break;
case Distance : result << "'Distance'>";break;
case Angle : result << "'Angle'>";break;
case InternalAlignment :
switch(this->getConstraintPtr()->AlignmentType) {
case Undef : result << "'InternalAlignment:Undef'>";break;
case EllipseMajorDiameter : result << "'InternalAlignment:EllipseMajorDiameter'>";break;
case EllipseMinorDiameter : result << "'InternalAlignment:EllipseMinorDiameter'>";break;
case EllipseFocus1 : result << "'InternalAlignment:EllipseFocus1'>";break;
case EllipseFocus2 : result << "'InternalAlignment:EllipseFocus2'>";break;
default : result << "'InternalAlignment:?'>";break;
}
break;
default : result << "'?'>";break;
}
return result.str();
}

View File

@@ -40,6 +40,7 @@
#include <Mod/Part/App/Geometry.h>
#include <Mod/Part/App/GeometryCurvePy.h>
#include <Mod/Part/App/ArcOfCirclePy.h>
#include <Mod/Part/App/ArcOfEllipsePy.h>
#include <Mod/Part/App/CirclePy.h>
#include <Mod/Part/App/EllipsePy.h>
#include <Mod/Part/App/LinePy.h>
@@ -78,6 +79,8 @@ void Sketch::clear(void)
Lines.clear();
Arcs.clear();
Circles.clear();
Ellipses.clear();
ArcsOfEllipse.clear();
// deleting the doubles allocated with new
for (std::vector<double*>::iterator it = Parameters.begin(); it != Parameters.end(); ++it)
@@ -142,6 +145,8 @@ const char* nameByType(Sketch::GeoType type)
return "circle";
case Sketch::Ellipse:
return "ellipse";
case Sketch::ArcOfEllipse:
return "arcofellipse";
case Sketch::None:
default:
return "unknown";
@@ -164,10 +169,18 @@ int Sketch::addGeometry(const Part::Geometry *geo, bool fixed)
const GeomCircle *circle = dynamic_cast<const GeomCircle*>(geo);
// create the definition struct for that geom
return addCircle(*circle, fixed);
} else if (geo->getTypeId() == GeomEllipse::getClassTypeId()) { // add a ellipse
const GeomEllipse *ellipse = dynamic_cast<const GeomEllipse*>(geo);
// create the definition struct for that geom
return addEllipse(*ellipse, fixed);
} else if (geo->getTypeId() == GeomArcOfCircle::getClassTypeId()) { // add an arc
const GeomArcOfCircle *aoc = dynamic_cast<const GeomArcOfCircle*>(geo);
// create the definition struct for that geom
return addArc(*aoc, fixed);
} else if (geo->getTypeId() == GeomArcOfEllipse::getClassTypeId()) { // add an arc
const GeomArcOfEllipse *aoe = dynamic_cast<const GeomArcOfEllipse*>(geo);
// create the definition struct for that geom
return addArcOfEllipse(*aoe, fixed);
} else {
Base::Exception("Sketch::addGeometry(): Unknown or unsupported type added to a sketch");
return 0;
@@ -341,6 +354,99 @@ int Sketch::addArc(const Part::GeomArcOfCircle &circleSegment, bool fixed)
return Geoms.size()-1;
}
int Sketch::addArcOfEllipse(const Part::GeomArcOfEllipse &ellipseSegment, bool fixed)
{
std::vector<double *> &params = fixed ? FixParameters : Parameters;
// create our own copy
GeomArcOfEllipse *aoe = static_cast<GeomArcOfEllipse*>(ellipseSegment.clone());
// create the definition struct for that geom
GeoDef def;
def.geo = aoe;
def.type = ArcOfEllipse;
Base::Vector3d center = aoe->getCenter();
Base::Vector3d startPnt = aoe->getStartPoint();
Base::Vector3d endPnt = aoe->getEndPoint();
double radmaj = aoe->getMajorRadius();
double radmin = aoe->getMinorRadius();
double phi = aoe->getAngleXU();
double dist_C_F = sqrt(radmaj*radmaj-radmin*radmin);
// solver parameters
Base::Vector3d focus1 = center+dist_C_F*Vector3d(cos(phi), sin(phi),0); //+x
double startAngle, endAngle;
aoe->getRange(startAngle, endAngle);
GCS::Point p1, p2, p3;
GCS::Point f1;
params.push_back(new double(startPnt.x));
params.push_back(new double(startPnt.y));
p1.x = params[params.size()-2];
p1.y = params[params.size()-1];
params.push_back(new double(endPnt.x));
params.push_back(new double(endPnt.y));
p2.x = params[params.size()-2];
p2.y = params[params.size()-1];
params.push_back(new double(center.x));
params.push_back(new double(center.y));
p3.x = params[params.size()-2];
p3.y = params[params.size()-1];
params.push_back(new double(focus1.x));
params.push_back(new double(focus1.y));
f1.x = params[params.size()-2];
f1.y = params[params.size()-1];
def.startPointId = Points.size();
Points.push_back(p1);
def.endPointId = Points.size();
Points.push_back(p2);
def.midPointId = Points.size();
Points.push_back(p3);
Points.push_back(f1);
// add the radius parameters
params.push_back(new double(radmin));
double *rmin = params[params.size()-1];
params.push_back(new double(startAngle));
double *a1 = params[params.size()-1];
params.push_back(new double(endAngle));
double *a2 = params[params.size()-1];
// set the arc for later constraints
GCS::ArcOfEllipse a;
a.start = p1;
a.end = p2;
a.center = p3;
a.focus1 = f1;
a.radmin = rmin;
a.startAngle = a1;
a.endAngle = a2;
def.index = ArcsOfEllipse.size();
ArcsOfEllipse.push_back(a);
// store complete set
Geoms.push_back(def);
// arcs require an ArcRules constraint for the end points
if (!fixed)
GCSsys.addConstraintArcOfEllipseRules(a); // TODO: ArcOfEllipse implementation.
// return the position of the newly added geometry
return Geoms.size()-1;
}
int Sketch::addCircle(const Part::GeomCircle &cir, bool fixed)
{
std::vector<double *> &params = fixed ? FixParameters : Parameters;
@@ -384,8 +490,66 @@ int Sketch::addCircle(const Part::GeomCircle &cir, bool fixed)
return Geoms.size()-1;
}
int Sketch::addEllipse(const Part::GeomEllipse &ellipse, bool fixed)
int Sketch::addEllipse(const Part::GeomEllipse &elip, bool fixed)
{
// TODO: Ellipse
std::vector<double *> &params = fixed ? FixParameters : Parameters;
// create our own copy
GeomEllipse *elips = static_cast<GeomEllipse*>(elip.clone());
// create the definition struct for that geom
GeoDef def;
def.geo = elips;
def.type = Ellipse;
Base::Vector3d center = elips->getCenter();
double radmaj = elips->getMajorRadius();
double radmin = elips->getMinorRadius();
double phi = elips->getAngleXU();
double dist_C_F = sqrt(radmaj*radmaj-radmin*radmin);
// solver parameters
Base::Vector3d focus1 = center+dist_C_F*Vector3d(cos(phi), sin(phi),0); //+x
//double *radmin;
GCS::Point c;
params.push_back(new double(center.x));
params.push_back(new double(center.y));
c.x = params[params.size()-2];
c.y = params[params.size()-1];
def.midPointId = Points.size(); // this takes midPointId+1
Points.push_back(c);
GCS::Point f1;
params.push_back(new double(focus1.x));
params.push_back(new double(focus1.y));
f1.x = params[params.size()-2];
f1.y = params[params.size()-1];
//def.midPointId = Points.size();
Points.push_back(f1);
// add the radius parameters
params.push_back(new double(radmin));
double *rmin = params[params.size()-1];
// set the ellipse for later constraints
GCS::Ellipse e;
e.focus1 = f1;
e.center = c;
e.radmin = rmin;
def.index = Ellipses.size();
Ellipses.push_back(e);
// store complete set
Geoms.push_back(def);
// return the position of the newly added geometry
return Geoms.size()-1;
}
@@ -422,7 +586,11 @@ Py::Tuple Sketch::getPyGeometry(void) const
} else if (it->type == Ellipse) {
GeomEllipse *ellipse = dynamic_cast<GeomEllipse*>(it->geo->clone());
tuple[i] = Py::asObject(new EllipsePy(ellipse));
} else {
} else if (it->type == ArcOfEllipse) {
GeomArcOfEllipse *ellipse = dynamic_cast<GeomArcOfEllipse*>(it->geo->clone());
tuple[i] = Py::asObject(new ArcOfEllipsePy(ellipse));
}
else {
// not implemented type in the sketch!
}
}
@@ -549,6 +717,22 @@ int Sketch::addConstraint(const Constraint *constraint)
rtn = addSymmetricConstraint(constraint->First,constraint->FirstPos,
constraint->Second,constraint->SecondPos,constraint->Third);
break;
case InternalAlignment:
switch(constraint->AlignmentType) {
case EllipseMajorDiameter:
rtn = addInternalAlignmentEllipseMajorDiameter(constraint->First,constraint->Second);
break;
case EllipseMinorDiameter:
rtn = addInternalAlignmentEllipseMinorDiameter(constraint->First,constraint->Second);
break;
case EllipseFocus1:
rtn = addInternalAlignmentEllipseFocus1(constraint->First,constraint->Second);
break;
case EllipseFocus2:
rtn = addInternalAlignmentEllipseFocus2(constraint->First,constraint->Second);
break;
}
break;
case None:
break;
}
@@ -861,6 +1045,15 @@ int Sketch::addPerpendicularConstraint(int geoId1, PointPos pos1, int geoId2)
GCSsys.addConstraintPointOnLine(p2, l1, tag);
return ConstraintsCounter;
}
else if (Geoms[geoId2].type == Ellipse) {
// TODO: Ellipse
GCS::Ellipse &c2 = Ellipses[Geoms[geoId2].index];
GCS::Point &p2 = Points[Geoms[geoId2].midPointId];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintPointOnEllipse(p1, c2, tag);
GCSsys.addConstraintPointOnLine(p2, l1, tag);
return ConstraintsCounter;
}
}
else if (Geoms[geoId1].type == Arc) {
GCS::Arc &a1 = Arcs[Geoms[geoId1].index];
@@ -871,7 +1064,8 @@ int Sketch::addPerpendicularConstraint(int geoId1, PointPos pos1, int geoId2)
GCSsys.addConstraintPointOnLine(a1.center, l2, tag);
return ConstraintsCounter;
}
else if (Geoms[geoId2].type == Arc || Geoms[geoId2].type == Circle) {
else if (Geoms[geoId2].type == Arc || Geoms[geoId2].type == Circle || Geoms[geoId2].type == Ellipse) {
// TODO: ellipse real implementation
int tag = ++ConstraintsCounter;
GCS::Point &center = Points[Geoms[geoId2].midPointId];
double *radius;
@@ -879,10 +1073,15 @@ int Sketch::addPerpendicularConstraint(int geoId1, PointPos pos1, int geoId2)
GCS::Arc &a2 = Arcs[Geoms[geoId2].index];
radius = a2.rad;
}
else {
else if (Geoms[geoId2].type == Circle) {
GCS::Circle &c2 = Circles[Geoms[geoId2].index];
radius = c2.rad;
}
else {
// TODO: Ellipse
GCS::Ellipse &c2 = Ellipses[Geoms[geoId2].index];
radius = c2.radmin;
}
if (pos1 == start)
GCSsys.addConstraintPerpendicularCircle2Arc(center, radius, a1, tag);
else if (pos1 == end)
@@ -1026,6 +1225,18 @@ int Sketch::addTangentConstraint(int geoId1, int geoId2)
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangent(l, c, tag);
return ConstraintsCounter;
} else if (Geoms[geoId2].type == Ellipse) {
// TODO: real implementation
GCS::Ellipse &e = Ellipses[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangent(l, e, tag);
return ConstraintsCounter;
} else if (Geoms[geoId2].type == ArcOfEllipse) {
// TODO: real implementation
GCS::ArcOfEllipse &a = ArcsOfEllipse[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangent(l, a, tag);
return ConstraintsCounter;
}
} else if (Geoms[geoId1].type == Circle) {
GCS::Circle &c = Circles[Geoms[geoId1].index];
@@ -1034,12 +1245,33 @@ int Sketch::addTangentConstraint(int geoId1, int geoId2)
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangent(c, c2, tag);
return ConstraintsCounter;
} else if (Geoms[geoId2].type == Arc) {
} else if (Geoms[geoId2].type == Ellipse) {
// TODO: real implementation
GCS::Ellipse &e = Ellipses[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangent(e, c, tag);
return ConstraintsCounter;
}
else if (Geoms[geoId2].type == Arc) {
GCS::Arc &a = Arcs[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangent(c, a, tag);
return ConstraintsCounter;
}
} else if (Geoms[geoId1].type == Ellipse) {
GCS::Ellipse &e = Ellipses[Geoms[geoId1].index];
// TODO: Ellipse
if (Geoms[geoId2].type == Circle) {
GCS::Circle &c = Circles[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangent(e, c, tag);
return ConstraintsCounter;
} else if (Geoms[geoId2].type == Arc) {
GCS::Arc &a = Arcs[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangent(e, a, tag);
return ConstraintsCounter;
}
} else if (Geoms[geoId1].type == Arc) {
GCS::Arc &a = Arcs[Geoms[geoId1].index];
if (Geoms[geoId2].type == Circle) {
@@ -1047,6 +1279,12 @@ int Sketch::addTangentConstraint(int geoId1, int geoId2)
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangent(c, a, tag);
return ConstraintsCounter;
} else if (Geoms[geoId2].type == Ellipse) {
// TODO: Ellipse
GCS::Ellipse &e = Ellipses[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangent(e, a, tag);
return ConstraintsCounter;
} else if (Geoms[geoId2].type == Arc) {
GCS::Arc &a2 = Arcs[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
@@ -1096,6 +1334,14 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2)
GCSsys.addConstraintTangent(l1, c2, tag);
return ConstraintsCounter;
}
else if (Geoms[geoId2].type == Ellipse) {
// TODO: Ellipse
GCS::Ellipse &e = Ellipses[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintPointOnEllipse(p1, e, tag);
GCSsys.addConstraintTangent(l1, e, tag);
return ConstraintsCounter;
}
}
else if (Geoms[geoId1].type == Arc) {
GCS::Arc &a1 = Arcs[Geoms[geoId1].index];
@@ -1125,6 +1371,19 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2)
GCSsys.addConstraintTangentArc2Circle(a1, c2, tag);
return ConstraintsCounter;
}
} else if (Geoms[geoId2].type == Ellipse) {
// TODO: Ellipse
GCS::Ellipse &e = Ellipses[Geoms[geoId2].index];
if (pos1 == start) {
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangentEllipse2Arc(e, a1, tag);
return ConstraintsCounter;
}
else if (pos1 == end) {
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangentArc2Ellipse(a1, e, tag);
return ConstraintsCounter;
}
}
}
return -1;
@@ -1198,6 +1457,35 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos
else
return -1;
}
if (Geoms[geoId2].type == ArcOfEllipse) {
GCS::ArcOfEllipse &a2 = ArcsOfEllipse[Geoms[geoId2].index];
if (pos2 == start) {
if (pos1 == start) {
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangentLine2ArcOfEllipse(l1.p2, l1.p1, l1, a2, tag);
return ConstraintsCounter;
}
else if (pos1 == end) {
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangentLine2ArcOfEllipse(l1.p1, l1.p2, l1, a2, tag);
return ConstraintsCounter;
}
}
else if (pos2 == end) {
if (pos1 == start) {
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangentArcOfEllipse2Line(a2, l1, l1.p1, l1.p2, tag);
return ConstraintsCounter;
}
else if (pos1 == end) {
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangentArcOfEllipse2Line(a2, l1, l1.p2, l1.p1, tag);
return ConstraintsCounter;
}
}
else
return -1;
}
}
else if (Geoms[geoId1].type == Arc) {
GCS::Arc &a1 = Arcs[Geoms[geoId1].index];
@@ -1309,7 +1597,7 @@ int Sketch::addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, PointPo
return -1;
}
int Sketch::addRadiusConstraint(int geoId, double value)
int Sketch::addRadiusConstraint(int geoId, double value, int radiusnumber)
{
geoId = checkGeoId(geoId);
@@ -1448,6 +1736,18 @@ int Sketch::addEqualConstraint(int geoId1, int geoId2)
else
std::swap(geoId1, geoId2);
}
// TODO: Ellipse
if (Geoms[geoId2].type == Ellipse) {
if (Geoms[geoId1].type == Ellipse) {
GCS::Ellipse &e1 = Ellipses[Geoms[geoId1].index];
GCS::Ellipse &e2 = Ellipses[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintEqualRadii(e1, e2, tag);
return ConstraintsCounter;
}
else
std::swap(geoId1, geoId2);
}
if (Geoms[geoId1].type == Circle) {
GCS::Circle &c1 = Circles[Geoms[geoId1].index];
@@ -1502,6 +1802,18 @@ int Sketch::addPointOnObjectConstraint(int geoId1, PointPos pos1, int geoId2)
GCSsys.addConstraintPointOnCircle(p1, c, tag);
return ConstraintsCounter;
}
else if (Geoms[geoId2].type == Ellipse) {
GCS::Ellipse &e = Ellipses[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintPointOnEllipse(p1, e, tag);
return ConstraintsCounter;
}
else if (Geoms[geoId2].type == ArcOfEllipse) {
GCS::ArcOfEllipse &a = ArcsOfEllipse[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintPointOnArcOfEllipse(p1, a, tag);
return ConstraintsCounter;
}
}
return -1;
}
@@ -1555,6 +1867,167 @@ int Sketch::addSymmetricConstraint(int geoId1, PointPos pos1, int geoId2, PointP
return -1;
}
int Sketch::addInternalAlignmentEllipseMajorDiameter(int geoId1, int geoId2)
{
std::swap(geoId1, geoId2);
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
if (Geoms[geoId1].type != Ellipse && Geoms[geoId1].type != ArcOfEllipse)
return -1;
if (Geoms[geoId2].type != Line)
return -1;
int pointId1 = getPointId(geoId2, start);
int pointId2 = getPointId(geoId2, end);
if (pointId1 >= 0 && pointId1 < int(Points.size()) &&
pointId2 >= 0 && pointId2 < int(Points.size())) {
GCS::Point &p1 = Points[pointId1];
GCS::Point &p2 = Points[pointId2];
if(Geoms[geoId1].type == Ellipse) {
GCS::Ellipse &e1 = Ellipses[Geoms[geoId1].index];
// constraints
// 1. start point with ellipse -a
// 2. end point with ellipse +a
int tag = ++ConstraintsCounter;
GCSsys.addConstraintInternalAlignmentEllipseMajorDiameter(e1, p1, p2, tag);
return ConstraintsCounter;
}
else {
GCS::ArcOfEllipse &a1 = ArcsOfEllipse[Geoms[geoId1].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintInternalAlignmentEllipseMajorDiameter(a1, p1, p2, tag);
return ConstraintsCounter;
}
}
return -1;
}
int Sketch::addInternalAlignmentEllipseMinorDiameter(int geoId1, int geoId2)
{
std::swap(geoId1, geoId2);
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
if (Geoms[geoId1].type != Ellipse && Geoms[geoId1].type != ArcOfEllipse)
return -1;
if (Geoms[geoId2].type != Line)
return -1;
int pointId1 = getPointId(geoId2, start);
int pointId2 = getPointId(geoId2, end);
if (pointId1 >= 0 && pointId1 < int(Points.size()) &&
pointId2 >= 0 && pointId2 < int(Points.size())) {
GCS::Point &p1 = Points[pointId1];
GCS::Point &p2 = Points[pointId2];
if(Geoms[geoId1].type == Ellipse) {
GCS::Ellipse &e1 = Ellipses[Geoms[geoId1].index];
// constraints
// 1. start point with ellipse -a
// 2. end point with ellipse +a
int tag = ++ConstraintsCounter;
GCSsys.addConstraintInternalAlignmentEllipseMinorDiameter(e1, p1, p2, tag);
return ConstraintsCounter;
}
else {
GCS::ArcOfEllipse &a1 = ArcsOfEllipse[Geoms[geoId1].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintInternalAlignmentEllipseMinorDiameter(a1, p1, p2, tag);
return ConstraintsCounter;
}
}
return -1;
}
int Sketch::addInternalAlignmentEllipseFocus1(int geoId1, int geoId2)
{
std::swap(geoId1, geoId2);
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
if (Geoms[geoId1].type != Ellipse && Geoms[geoId1].type != ArcOfEllipse)
return -1;
if (Geoms[geoId2].type != Point)
return -1;
int pointId1 = getPointId(geoId2, start);
if (pointId1 >= 0 && pointId1 < int(Points.size())) {
GCS::Point &p1 = Points[pointId1];
if(Geoms[geoId1].type == Ellipse) {
GCS::Ellipse &e1 = Ellipses[Geoms[geoId1].index];
// constraints
// 1. start point with ellipse -a
// 2. end point with ellipse +a
int tag = ++ConstraintsCounter;
GCSsys.addConstraintInternalAlignmentEllipseFocus1(e1, p1, tag);
return ConstraintsCounter;
}
else {
GCS::ArcOfEllipse &a1 = ArcsOfEllipse[Geoms[geoId1].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintInternalAlignmentEllipseFocus1(a1, p1, tag);
return ConstraintsCounter;
}
}
return -1;
}
int Sketch::addInternalAlignmentEllipseFocus2(int geoId1, int geoId2)
{
std::swap(geoId1, geoId2);
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
if (Geoms[geoId1].type != Ellipse && Geoms[geoId1].type != ArcOfEllipse)
return -1;
if (Geoms[geoId2].type != Point)
return -1;
int pointId1 = getPointId(geoId2, start);
if (pointId1 >= 0 && pointId1 < int(Points.size())) {
GCS::Point &p1 = Points[pointId1];
if(Geoms[geoId1].type == Ellipse) {
GCS::Ellipse &e1 = Ellipses[Geoms[geoId1].index];
// constraints
// 1. start point with ellipse -a
// 2. end point with ellipse +a
int tag = ++ConstraintsCounter;
GCSsys.addConstraintInternalAlignmentEllipseFocus2(e1, p1, tag);
return ConstraintsCounter;
}
else {
GCS::ArcOfEllipse &a1 = ArcsOfEllipse[Geoms[geoId1].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintInternalAlignmentEllipseFocus2(a1, p1, tag);
return ConstraintsCounter;
}
}
return -1;
}
bool Sketch::updateGeometry()
{
int i=0;
@@ -1589,6 +2062,25 @@ bool Sketch::updateGeometry()
);
aoc->setRadius(*myArc.rad);
aoc->setRange(*myArc.startAngle, *myArc.endAngle);
} else if (it->type == ArcOfEllipse) {
GCS::ArcOfEllipse &myArc = ArcsOfEllipse[it->index];
GeomArcOfEllipse *aoe = dynamic_cast<GeomArcOfEllipse*>(it->geo);
Base::Vector3d center = Vector3d(*Points[it->midPointId].x, *Points[it->midPointId].y, 0.0);
Base::Vector3d f1 = Vector3d(*Points[it->midPointId+1].x, *Points[it->midPointId+1].y, 0.0);
double radmin = *ArcsOfEllipse[it->index].radmin;
Base::Vector3d fd=f1-center;
double radmaj = sqrt(fd*fd+radmin*radmin);
double phi = atan2(fd.y,fd.x);
aoe->setCenter(center);
aoe->setMajorRadius(radmaj);
aoe->setMinorRadius(radmin);
aoe->setAngleXU(phi);
aoe->setRange(*myArc.startAngle, *myArc.endAngle);
} else if (it->type == Circle) {
GeomCircle *circ = dynamic_cast<GeomCircle*>(it->geo);
circ->setCenter(Vector3d(*Points[it->midPointId].x,
@@ -1596,6 +2088,23 @@ bool Sketch::updateGeometry()
0.0)
);
circ->setRadius(*Circles[it->index].rad);
} else if (it->type == Ellipse) {
// TODO: Ellipse
GeomEllipse *ellipse = dynamic_cast<GeomEllipse*>(it->geo);
Base::Vector3d center = Vector3d(*Points[it->midPointId].x, *Points[it->midPointId].y, 0.0);
Base::Vector3d f1 = Vector3d(*Points[it->midPointId+1].x, *Points[it->midPointId+1].y, 0.0);
double radmin = *Ellipses[it->index].radmin;
Base::Vector3d fd=f1-center;
double radmaj = sqrt(fd*fd+radmin*radmin);
double phi = atan2(fd.y,fd.x);
ellipse->setCenter(center);
ellipse->setMajorRadius(radmaj);
ellipse->setMinorRadius(radmin);
ellipse->setAngleXU(phi);
}
} catch (Base::Exception e) {
Base::Console().Error("Updating geometry: Error build geometry(%d): %s\n",
@@ -1771,6 +2280,72 @@ int Sketch::initMove(int geoId, PointPos pos, bool fine)
GCSsys.rescaleConstraint(i-1, 0.01);
GCSsys.rescaleConstraint(i, 0.01);
}
} else if (Geoms[geoId].type == Ellipse) {
// TODO: Ellipse
GCS::Point &center = Points[Geoms[geoId].midPointId];
GCS::Point p0,p1;
if (pos == 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,-1);
} else if (pos == none) {
// TODO: Ellipse
MoveParameters.resize(4); // x,y,cx,cy
GCS::Ellipse &e = Ellipses[Geoms[geoId].index];
p0.x = &MoveParameters[0];
p0.y = &MoveParameters[1];
*p0.x = *center.x;
*p0.y = *center.y + *e.radmin;
GCSsys.addConstraintPointOnEllipse(p0,e,-1);
p1.x = &MoveParameters[2];
p1.y = &MoveParameters[3];
*p1.x = *center.x;
*p1.y = *center.y;
int i=GCSsys.addConstraintP2PCoincident(p1,center,-1);
GCSsys.rescaleConstraint(i-1, 0.01);
GCSsys.rescaleConstraint(i, 0.01);
}
} else if (Geoms[geoId].type == ArcOfEllipse) {
// TODO: ArcOfEllipse
GCS::Point &center = Points[Geoms[geoId].midPointId];
GCS::Point p0,p1;
if (pos == 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,-1);
} else if (pos == start || pos == end || pos == none) {
// TODO: Ellipse
MoveParameters.resize(4); // x,y,cx,cy
if (pos == start || pos == end) {
GCS::Point &p = (pos == 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,-1);
} else if (pos == none) {
GCS::ArcOfEllipse &a = ArcsOfEllipse[Geoms[geoId].index];
p0.x = &MoveParameters[0];
p0.y = &MoveParameters[1];
*p0.x = *center.x;
*p0.y = *center.y + *a.radmin;
GCSsys.addConstraintPointOnArcOfEllipse(p0,a,-1);
}
p1.x = &MoveParameters[2];
p1.y = &MoveParameters[3];
*p1.x = *center.x;
*p1.y = *center.y;
int i=GCSsys.addConstraintP2PCoincident(p1,center,-1);
GCSsys.rescaleConstraint(i-1, 0.01);
GCSsys.rescaleConstraint(i, 0.01);
}
} else if (Geoms[geoId].type == Arc) {
GCS::Point &center = Points[Geoms[geoId].midPointId];
GCS::Point p0,p1;
@@ -1858,6 +2433,16 @@ int Sketch::movePoint(int geoId, PointPos pos, Base::Vector3d toPoint, bool rela
MoveParameters[0] = toPoint.x;
MoveParameters[1] = toPoint.y;
}
} else if (Geoms[geoId].type == Ellipse) {
if (pos == mid || pos == none) {
MoveParameters[0] = toPoint.x;
MoveParameters[1] = toPoint.y;
}
} else if (Geoms[geoId].type == ArcOfEllipse) {
if (pos == start || pos == end || pos == mid || pos == none) {
MoveParameters[0] = toPoint.x;
MoveParameters[1] = toPoint.y;
}
}
return solve();
@@ -1886,6 +2471,33 @@ int Sketch::getPointId(int geoId, PointPos pos) const
return -1;
}
int Sketch::getVisiblePointId(int geoId, PointPos pos) const
{
// do a range check first
if (geoId < 0 || geoId >= (int)Geoms.size())
return -1;
int invisiblepoints = 0;
int i;
// calculate the number of points in the solver that are not visible in the UI
for(i=0;i<geoId;i++)
if(Geoms[i].type == Ellipse || Geoms[i].type == ArcOfEllipse)
invisiblepoints++;
switch (pos) {
case start:
return Geoms[geoId].startPointId-invisiblepoints;
case end:
return Geoms[geoId].endPointId-invisiblepoints;
case mid:
return Geoms[geoId].midPointId-invisiblepoints;
case none:
break;
}
return -1;
}
Base::Vector3d Sketch::getPoint(int geoId, PointPos pos)
{
geoId = checkGeoId(geoId);

View File

@@ -28,8 +28,8 @@
#include <Mod/Part/App/Geometry.h>
#include <Mod/Part/App/TopoShape.h>
#include "Constraint.h"
#include "freegcs/GCS.h"
#include "freegcs/GCS.h"
#include <Base/Persistence.h>
@@ -82,6 +82,8 @@ public:
/// retrieves the index of a point
int getPointId(int geoId, PointPos pos) const;
int getVisiblePointId(int geoId, PointPos pos) const;
/// retrieves a point
Base::Vector3d getPoint(int geoId, PointPos pos);
@@ -119,8 +121,10 @@ public:
int addArc(const Part::GeomArcOfCircle &circleSegment, bool fixed=false);
/// add a circle
int addCircle(const Part::GeomCircle &circle, bool fixed=false);
/// add a ellipse
/// add an ellipse
int addEllipse(const Part::GeomEllipse &ellipse, bool fixed=false);
/// add an arc of ellipse
int addArcOfEllipse(const Part::GeomArcOfEllipse &ellipseSegment, bool fixed=false);
//@}
@@ -163,11 +167,14 @@ public:
int addTangentConstraint(int geoId1, PointPos pos1, int geoId2);
int addTangentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2);
/// add a radius constraint on a circle or an arc
int addRadiusConstraint(int geoId, double value);
int addRadiusConstraint(int geoId, double value, int radiusnumber=0);
/// add an angle constraint on a line or between two lines
int addAngleConstraint(int geoId, double value);
int addAngleConstraint(int geoId1, int geoId2, double value);
int addAngleConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double value);
/// add ellipse XDir axis angle constraint with respect to XAxis or a lines
int addEllipseAngleXUConstraint(int geoId, double value);
int addEllipseAngleXUConstraint(int geoId1, int geoId2, double value);
/// add an equal length or radius constraints between two lines or between circles and arcs
int addEqualConstraint(int geoId1, int geoId2);
/// add a point on line constraint
@@ -177,14 +184,24 @@ public:
/// add a symmetric constraint between three points, the last point is in the middle of the first two
int addSymmetricConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, int geoId3, PointPos pos3);
//@}
/// Internal Alignment constraints
//@{
/// add InternalAlignmentEllipseMajorDiameter to a line and an ellipse
int addInternalAlignmentEllipseMajorDiameter(int geoId1, int geoId2);
int addInternalAlignmentEllipseMinorDiameter(int geoId1, int geoId2);
int addInternalAlignmentEllipseFocus1(int geoId1, int geoId2);
int addInternalAlignmentEllipseFocus2(int geoId1, int geoId2);
//@}
enum GeoType {
None = 0,
Point = 1, // 1 Point(start), 2 Parameters(x,y)
Line = 2, // 2 Points(start,end), 4 Parameters(x1,y1,x2,y2)
Arc = 3, // 3 Points(start,end,mid), (4)+5 Parameters((x1,y1,x2,y2),x,y,r,a1,a2)
Circle = 4, // 1 Point(mid), 3 Parameters(x,y,r)
Ellipse = 5
Ellipse = 5, // 1 Point(mid), 5 Parameters(x,y,r1,r2,phi) phi=angle xaxis of elipse with respect of sketch xaxis// TODO: Ellipse
ArcOfEllipse = 6
};
float SolveTime;
@@ -217,6 +234,8 @@ protected:
std::vector<GCS::Line> Lines;
std::vector<GCS::Arc> Arcs;
std::vector<GCS::Circle> Circles;
std::vector<GCS::Ellipse> Ellipses;
std::vector<GCS::ArcOfEllipse> ArcsOfEllipse;
bool isInitMove;
bool isFine;

View File

@@ -257,6 +257,10 @@ Base::Vector3d SketchObject::getPoint(int GeoId, PointPos PosId) const
const Part::GeomCircle *circle = dynamic_cast<const Part::GeomCircle*>(geo);
if (PosId == mid)
return circle->getCenter();
} else if (geo->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
const Part::GeomEllipse *ellipse = dynamic_cast<const Part::GeomEllipse*>(geo);
if (PosId == mid)
return ellipse->getCenter();
} else if (geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
const Part::GeomArcOfCircle *aoc = dynamic_cast<const Part::GeomArcOfCircle*>(geo);
if (PosId == start)
@@ -265,6 +269,14 @@ Base::Vector3d SketchObject::getPoint(int GeoId, PointPos PosId) const
return aoc->getEndPoint();
else if (PosId == mid)
return aoc->getCenter();
} else if (geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) {
const Part::GeomArcOfEllipse *aoc = dynamic_cast<const Part::GeomArcOfEllipse*>(geo);
if (PosId == start)
return aoc->getStartPoint();
else if (PosId == end)
return aoc->getEndPoint();
else if (PosId == mid)
return aoc->getCenter();
}
return Base::Vector3d();
@@ -944,7 +956,9 @@ int SketchObject::trim(int GeoId, const Base::Vector3d& point)
return 0;
}
} else if (geo->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
// TODO: Ellipse Trim support
return 0;
} else if (geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
const Part::GeomArcOfCircle *aoc = dynamic_cast<const Part::GeomArcOfCircle*>(geo);
Base::Vector3d center = aoc->getCenter();
@@ -1490,6 +1504,9 @@ void SketchObject::rebuildVertexIndex(void)
} else if ((*it)->getTypeId() == Part::GeomCircle::getClassTypeId()) {
VertexId2GeoId.push_back(i);
VertexId2PosId.push_back(mid);
} else if ((*it)->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
VertexId2GeoId.push_back(i);
VertexId2PosId.push_back(mid);
} else if ((*it)->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
VertexId2GeoId.push_back(i);
VertexId2PosId.push_back(start);
@@ -1497,6 +1514,13 @@ void SketchObject::rebuildVertexIndex(void)
VertexId2PosId.push_back(end);
VertexId2GeoId.push_back(i);
VertexId2PosId.push_back(mid);
} else if ((*it)->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) {
VertexId2GeoId.push_back(i);
VertexId2PosId.push_back(start);
VertexId2GeoId.push_back(i);
VertexId2PosId.push_back(end);
VertexId2GeoId.push_back(i);
VertexId2PosId.push_back(mid);
}
}
}

View File

@@ -90,7 +90,9 @@ PyObject* SketchObjectPy::addGeometry(PyObject *args)
}
else if (geo->getTypeId() == Part::GeomPoint::getClassTypeId() ||
geo->getTypeId() == Part::GeomCircle::getClassTypeId() ||
geo->getTypeId() == Part::GeomEllipse::getClassTypeId() ||
geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() ||
geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
ret = this->getSketchObjectPtr()->addGeometry(geo);
}
@@ -131,7 +133,9 @@ PyObject* SketchObjectPy::addGeometry(PyObject *args)
}
else if (geo->getTypeId() == Part::GeomPoint::getClassTypeId() ||
geo->getTypeId() == Part::GeomCircle::getClassTypeId() ||
geo->getTypeId() == Part::GeomEllipse::getClassTypeId() ||
geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() ||
geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
geoList.push_back(geo);
}

File diff suppressed because it is too large Load Diff

View File

@@ -46,7 +46,26 @@ namespace GCS
Perpendicular = 9,
L2LAngle = 10,
MidpointOnLine = 11,
TangentCircumf = 12
TangentCircumf = 12,
P2OnEllipse = 13,
TangentEllipseLine = 14,
Point2EllipseDistance = 15,
InternalAlignmentPoint2Ellipse = 16,
EqualMajorAxesEllipse = 17,
EllipticalArcRangeToEndPoints = 18
};
enum InternalAlignmentType {
EllipsePositiveMajorX = 0,
EllipsePositiveMajorY = 1,
EllipseNegativeMajorX = 2,
EllipseNegativeMajorY = 3,
EllipsePositiveMinorX = 4,
EllipsePositiveMinorY = 5,
EllipseNegativeMinorX = 6,
EllipseNegativeMinorY = 7,
EllipseFocus2X = 8,
EllipseFocus2Y = 9
};
class Constraint
@@ -159,6 +178,7 @@ namespace GCS
virtual double error();
virtual double grad(double *);
virtual double maxStep(MAP_pD_D &dir, double lim=1.);
double abs(double darea);
};
// PointOnLine
@@ -304,6 +324,110 @@ namespace GCS
virtual double error();
virtual double grad(double *);
};
// PointOnEllipse
class ConstraintPointOnEllipse : public Constraint
{
private:
inline double* p1x() { return pvec[0]; }
inline double* p1y() { return pvec[1]; }
inline double* cx() { return pvec[2]; }
inline double* cy() { return pvec[3]; }
inline double* f1x() { return pvec[4]; }
inline double* f1y() { return pvec[5]; }
inline double* rmin() { return pvec[6]; }
public:
ConstraintPointOnEllipse(Point &p, Ellipse &e);
ConstraintPointOnEllipse(Point &p, ArcOfEllipse &a);
virtual ConstraintType getTypeId();
virtual void rescale(double coef=1.);
virtual double error();
virtual double grad(double *);
};
class ConstraintEllipseTangentLine : public Constraint
{
private:
inline double* p1x() { return pvec[0]; }
inline double* p1y() { return pvec[1]; }
inline double* p2x() { return pvec[2]; }
inline double* p2y() { return pvec[3]; }
inline double* cx() { return pvec[4]; }
inline double* cy() { return pvec[5]; }
inline double* f1x() { return pvec[6]; }
inline double* f1y() { return pvec[7]; }
inline double* rmin() { return pvec[8]; }
public:
ConstraintEllipseTangentLine(Line &l, Ellipse &e);
ConstraintEllipseTangentLine(Line &l, ArcOfEllipse &a);
virtual ConstraintType getTypeId();
virtual void rescale(double coef=1.);
virtual double error();
virtual double grad(double *);
};
class ConstraintInternalAlignmentPoint2Ellipse : public Constraint
{
private:
inline double* p1x() { return pvec[0]; }
inline double* p1y() { return pvec[1]; }
inline double* cx() { return pvec[2]; }
inline double* cy() { return pvec[3]; }
inline double* f1x() { return pvec[4]; }
inline double* f1y() { return pvec[5]; }
inline double* rmin() { return pvec[6]; }
public:
ConstraintInternalAlignmentPoint2Ellipse(Ellipse &e, Point &p1, InternalAlignmentType alignmentType);
ConstraintInternalAlignmentPoint2Ellipse(ArcOfEllipse &e, Point &p1, InternalAlignmentType alignmentType);
virtual ConstraintType getTypeId();
virtual void rescale(double coef=1.);
virtual double error();
virtual double grad(double *);
private:
InternalAlignmentType AlignmentType;
};
class ConstraintEqualMajorAxesEllipse : public Constraint
{
private:
inline double* e1cx() { return pvec[0]; }
inline double* e1cy() { return pvec[1]; }
inline double* e1f1x() { return pvec[2]; }
inline double* e1f1y() { return pvec[3]; }
inline double* e1rmin() { return pvec[4]; }
inline double* e2cx() { return pvec[5]; }
inline double* e2cy() { return pvec[6]; }
inline double* e2f1x() { return pvec[7]; }
inline double* e2f1y() { return pvec[8]; }
inline double* e2rmin() { return pvec[9]; }
public:
ConstraintEqualMajorAxesEllipse(Ellipse &e1, Ellipse &e2);
virtual ConstraintType getTypeId();
virtual void rescale(double coef=1.);
virtual double error();
virtual double grad(double *);
};
// EllipticalArcRangeToEndPoints
class ConstraintEllipticalArcRangeToEndPoints : public Constraint
{
private:
inline double* p1x() { return pvec[0]; }
inline double* p1y() { return pvec[1]; }
inline double* angle() { return pvec[2]; }
inline double* cx() { return pvec[3]; }
inline double* cy() { return pvec[4]; }
inline double* f1x() { return pvec[5]; }
inline double* f1y() { return pvec[6]; }
inline double* rmin() { return pvec[7]; }
public:
ConstraintEllipticalArcRangeToEndPoints(Point &p, ArcOfEllipse &a, double *angle_t);
virtual ConstraintType getTypeId();
virtual void rescale(double coef=1.);
virtual double error();
virtual double grad(double *);
virtual double maxStep(MAP_pD_D &dir, double lim=1.);
};
} //namespace GCS

View File

@@ -27,6 +27,16 @@
#include "qp_eq.h"
#include <Eigen/QR>
#define _GCS_DEBUG 1
#ifdef _GCS_DEBUG
#include <Base/Writer.h>
#include <Base/Reader.h>
#include <Base/Exception.h>
#include <Base/TimeInfo.h>
#include <Base/Console.h>
#endif // _GCS_DEBUG
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/connected_components.hpp>
@@ -481,6 +491,42 @@ int System::addConstraintPointOnCircle(Point &p, Circle &c, int tagId)
return addConstraintP2PDistance(p, c.center, c.rad, tagId);
}
int System::addConstraintPointOnEllipse(Point &p, Ellipse &e, int tagId)
{
// TODO: Implement real constraint => Done
Constraint *constr = new ConstraintPointOnEllipse(p, e);
constr->setTag(tagId);
return addConstraint(constr);
}
int System::addConstraintEllipticalArcRangeToEndPoints(Point &p, ArcOfEllipse &a, double *angle, int tagId)
{
Constraint *constr = new ConstraintEllipticalArcRangeToEndPoints(p,a,angle);
constr->setTag(tagId);
return addConstraint(constr);
}
int System::addConstraintArcOfEllipseRules(ArcOfEllipse &a, int tagId)
{
/* addConstraintP2PAngle(a.center, a.start, a.startAngle, tagId);
return addConstraintP2PAngle(a.center, a.end, a.endAngle, tagId);*/
addConstraintEllipticalArcRangeToEndPoints(a.start,a,a.startAngle, tagId);
addConstraintEllipticalArcRangeToEndPoints(a.end,a,a.endAngle, tagId);
addConstraintPointOnArcOfEllipse(a.start, a, tagId);
return addConstraintPointOnArcOfEllipse(a.end, a, tagId);
}
int System::addConstraintPointOnArcOfEllipse(Point &p, ArcOfEllipse &a, int tagId)
{
Constraint *constr = new ConstraintPointOnEllipse(p, a);
constr->setTag(tagId);
return addConstraint(constr);
}
int System::addConstraintPointOnArc(Point &p, Arc &a, int tagId)
{
return addConstraintP2PDistance(p, a.center, a.rad, tagId);
@@ -552,6 +598,39 @@ int System::addConstraintTangent(Line &l, Circle &c, int tagId)
return addConstraintP2LDistance(c.center, l, c.rad, tagId);
}
int System::addConstraintTangent(Line &l, Ellipse &e, int tagId)
{
// TODO: real ellipse implementation => Done
Constraint *constr = new ConstraintEllipseTangentLine(l, e);
constr->setTag(tagId);
return addConstraint(constr);
}
int System::addConstraintTangent(Line &l, ArcOfEllipse &a, int tagId)
{
// TODO: real ellipse implementation => Done
Constraint *constr = new ConstraintEllipseTangentLine(l, a);
constr->setTag(tagId);
return addConstraint(constr);
}
int System::addConstraintTangent(Ellipse &e, Circle &c, int tagId)
{
// TODO: elipse
/*double dx = *(c.center.x) - *(e.center.x);
double dy = *(c.center.y) - *(e.center.y);
double d = sqrt(dx*dx + dy*dy);*/
/*Constraint *constr = new ConstraintPoint2EllipseDistance(c.center,e,c.rad);
constr->setTag(tagId);
return addConstraint(constr); */
//return addConstraintTangentCircumf(e.center, c.center, e.radmaj, c.rad,
// (d < *e.radmaj || d < *c.rad), tagId);
return 0;
}
int System::addConstraintTangent(Line &l, Arc &a, int tagId)
{
return addConstraintP2LDistance(a.center, l, a.rad, tagId);
@@ -584,6 +663,19 @@ int System::addConstraintTangent(Circle &c, Arc &a, int tagId)
(d < *c.rad || d < *a.rad), tagId);
}
int System::addConstraintTangent(Ellipse &e, Arc &a, int tagId)
{
// TODO: elipse
/*double dx = *(a.center.x) - *(e.center.x);
double dy = *(a.center.y) - *(e.center.y);
double d = sqrt(dx*dx + dy*dy);Constraint *constr = new ConstraintEllipseTangentLine(l, e);
constr->setTag(tagId);
return addConstraint(constr);
return addConstraintTangentCircumf(e.center, a.center, e.radmaj, a.rad,
(d < *e.radmaj || d < *a.rad), tagId);*/
return 0;
}
int System::addConstraintTangentLine2Arc(Point &p1, Point &p2, Arc &a, int tagId)
{
addConstraintP2PCoincident(p2, a.start, tagId);
@@ -598,6 +690,18 @@ int System::addConstraintTangentArc2Line(Arc &a, Point &p1, Point &p2, int tagId
return addConstraintP2PAngle(p1, p2, a.endAngle, incrAngle, tagId);
}
int System::addConstraintTangentLine2ArcOfEllipse(Point &p1, Point &p2, Line &l, ArcOfEllipse &a, int tagId)
{
addConstraintP2PCoincident(p2, a.start, tagId);
return addConstraintTangent(l, a, tagId);
}
int System::addConstraintTangentArcOfEllipse2Line(ArcOfEllipse &a, Line &l, Point &p1, Point &p2, int tagId)
{
addConstraintP2PCoincident(p1, a.end, tagId);
return addConstraintTangent(l, a, tagId);
}
int System::addConstraintTangentCircle2Arc(Circle &c, Arc &a, int tagId)
{
addConstraintPointOnCircle(a.start, c, tagId);
@@ -609,6 +713,19 @@ int System::addConstraintTangentCircle2Arc(Circle &c, Arc &a, int tagId)
return addConstraintP2PAngle(c.center, a.start, a.startAngle, M_PI, tagId);
}
int System::addConstraintTangentEllipse2Arc(Ellipse &e, Arc &a, int tagId)
{
// TODO: Ellipse
/*addConstraintPointOnEllipse(a.start, e, tagId);
double dx = *(a.start.x) - *(e.center.x);
double dy = *(a.start.y) - *(e.center.y);
if (dx * cos(*(a.startAngle)) + dy * sin(*(a.startAngle)) > 0)
return addConstraintP2PAngle(e.center, a.start, a.startAngle, 0, tagId);
else
return addConstraintP2PAngle(e.center, a.start, a.startAngle, M_PI, tagId);*/
return 0;
}
int System::addConstraintTangentArc2Circle(Arc &a, Circle &c, int tagId)
{
addConstraintPointOnCircle(a.end, c, tagId);
@@ -620,6 +737,19 @@ int System::addConstraintTangentArc2Circle(Arc &a, Circle &c, int tagId)
return addConstraintP2PAngle(c.center, a.end, a.endAngle, M_PI, tagId);
}
int System::addConstraintTangentArc2Ellipse(Arc &a, Ellipse &e, int tagId)
{
// TODO: Ellipse
/*addConstraintPointOnEllipse(a.end, e, tagId);
double dx = *(a.end.x) - *(e.center.x);
double dy = *(a.end.y) - *(e.center.y);
if (dx * cos(*(a.endAngle)) + dy * sin(*(a.endAngle)) > 0)
return addConstraintP2PAngle(e.center, a.end, a.endAngle, 0, tagId);
else
return addConstraintP2PAngle(e.center, a.end, a.endAngle, M_PI, tagId);*/
return 0;
}
int System::addConstraintTangentArc2Arc(Arc &a1, bool reverse1, Arc &a2, bool reverse2,
int tagId)
{
@@ -656,6 +786,17 @@ int System::addConstraintEqualRadius(Circle &c1, Circle &c2, int tagId)
return addConstraintEqual(c1.rad, c2.rad, tagId);
}
int System::addConstraintEqualRadii(Ellipse &e1, Ellipse &e2, int tagId)
{
// TODO: Ellipse
//addConstraintEqual(e1.radmaj, e2.radmaj, tagId);
addConstraintEqual(e1.radmin, e2.radmin, tagId);
Constraint *constr = new ConstraintEqualMajorAxesEllipse(e1,e2);
constr->setTag(tagId);
return addConstraint(constr);
}
int System::addConstraintEqualRadius(Circle &c1, Arc &a2, int tagId)
{
return addConstraintEqual(c1.rad, a2.rad, tagId);
@@ -678,6 +819,74 @@ int System::addConstraintP2PSymmetric(Point &p1, Point &p2, Point &p, int tagId)
return addConstraintPointOnLine(p, p1, p2, tagId);
}
int System::addConstraintInternalAlignmentPoint2Ellipse(Ellipse &e, Point &p1, InternalAlignmentType alignmentType, int tagId)
{
Constraint *constr = new ConstraintInternalAlignmentPoint2Ellipse(e, p1, alignmentType);
constr->setTag(tagId);
return addConstraint(constr);
}
int System::addConstraintInternalAlignmentEllipseMajorDiameter(Ellipse &e, Point &p1, Point &p2, int tagId)
{
addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipsePositiveMajorX,tagId);
addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipsePositiveMajorY,tagId);
addConstraintInternalAlignmentPoint2Ellipse(e,p2,EllipseNegativeMajorX,tagId);
return addConstraintInternalAlignmentPoint2Ellipse(e,p2,EllipseNegativeMajorY,tagId);
}
int System::addConstraintInternalAlignmentEllipseMinorDiameter(Ellipse &e, Point &p1, Point &p2, int tagId)
{
addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipsePositiveMinorX,tagId);
addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipsePositiveMinorY,tagId);
addConstraintInternalAlignmentPoint2Ellipse(e,p2,EllipseNegativeMinorX,tagId);
return addConstraintInternalAlignmentPoint2Ellipse(e,p2,EllipseNegativeMinorY,tagId);
}
int System::addConstraintInternalAlignmentEllipseFocus1(Ellipse &e, Point &p1, int tagId)
{
return addConstraintP2PCoincident(e.focus1,p1);
}
int System::addConstraintInternalAlignmentEllipseFocus2(Ellipse &e, Point &p1, int tagId)
{
addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipseFocus2X,tagId);
return addConstraintInternalAlignmentPoint2Ellipse(e,p1,EllipseFocus2Y,tagId);
}
int System::addConstraintInternalAlignmentPoint2Ellipse(ArcOfEllipse &a, Point &p1, InternalAlignmentType alignmentType, int tagId)
{
Constraint *constr = new ConstraintInternalAlignmentPoint2Ellipse(a, p1, alignmentType);
constr->setTag(tagId);
return addConstraint(constr);
}
int System::addConstraintInternalAlignmentEllipseMajorDiameter(ArcOfEllipse &a, Point &p1, Point &p2, int tagId)
{
addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipsePositiveMajorX,tagId);
addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipsePositiveMajorY,tagId);
addConstraintInternalAlignmentPoint2Ellipse(a,p2,EllipseNegativeMajorX,tagId);
return addConstraintInternalAlignmentPoint2Ellipse(a,p2,EllipseNegativeMajorY,tagId);
}
int System::addConstraintInternalAlignmentEllipseMinorDiameter(ArcOfEllipse &a, Point &p1, Point &p2, int tagId)
{
addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipsePositiveMinorX,tagId);
addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipsePositiveMinorY,tagId);
addConstraintInternalAlignmentPoint2Ellipse(a,p2,EllipseNegativeMinorX,tagId);
return addConstraintInternalAlignmentPoint2Ellipse(a,p2,EllipseNegativeMinorY,tagId);
}
int System::addConstraintInternalAlignmentEllipseFocus1(ArcOfEllipse &a, Point &p1, int tagId)
{
return addConstraintP2PCoincident(a.focus1,p1);
}
int System::addConstraintInternalAlignmentEllipseFocus2(ArcOfEllipse &a, Point &p1, int tagId)
{
addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipseFocus2X,tagId);
return addConstraintInternalAlignmentPoint2Ellipse(a,p1,EllipseFocus2Y,tagId);
}
void System::rescaleConstraint(int id, double coeff)
{
if (id >= clist.size() || id < 0)
@@ -1465,12 +1674,27 @@ int System::diagnose()
J(count-1,j) = (*constr)->grad(plist[j]);
}
}
#ifdef _GCS_DEBUG
// Debug code starts
std::stringstream stream;
stream << "[";
stream << J ;
stream << "]";
const std::string tmp = stream.str();
Base::Console().Warning(tmp.c_str());
// Debug code ends
#endif
if (J.rows() > 0) {
Eigen::FullPivHouseholderQR<Eigen::MatrixXd> qrJT(J.topRows(count).transpose());
Eigen::MatrixXd Q = qrJT.matrixQ ();
int paramsNum = qrJT.rows();
int constrNum = qrJT.cols();
//qrJT.setThreshold(0);
int rank = qrJT.rank();
Eigen::MatrixXd R;

View File

@@ -125,6 +125,10 @@ namespace GCS
int addConstraintCoordinateY(Point &p, double *y, int tagId=0);
int addConstraintArcRules(Arc &a, int tagId=0);
int addConstraintPointOnCircle(Point &p, Circle &c, int tagId=0);
int addConstraintPointOnEllipse(Point &p, Ellipse &e, int tagId=0);
int addConstraintEllipticalArcRangeToEndPoints(Point &p, ArcOfEllipse &a, double *angle, int tagId=0);
int addConstraintArcOfEllipseRules(ArcOfEllipse &a, int tagId=0);
int addConstraintPointOnArcOfEllipse(Point &p, ArcOfEllipse &a, int tagId=0);
int addConstraintPointOnArc(Point &p, Arc &a, int tagId=0);
int addConstraintPerpendicularLine2Arc(Point &p1, Point &p2, Arc &a,
int tagId=0);
@@ -137,24 +141,47 @@ namespace GCS
int addConstraintPerpendicularArc2Arc(Arc &a1, bool reverse1,
Arc &a2, bool reverse2, int tagId=0);
int addConstraintTangent(Line &l, Circle &c, int tagId=0);
int addConstraintTangent(Line &l, Ellipse &e, int tagId=0);
int addConstraintTangent(Line &l, ArcOfEllipse &a, int tagId=0);
int addConstraintTangent(Ellipse &e, Circle &c, int tagId=0);
int addConstraintTangent(Line &l, Arc &a, int tagId=0);
int addConstraintTangent(Circle &c1, Circle &c2, int tagId=0);
int addConstraintTangent(Arc &a1, Arc &a2, int tagId=0);
int addConstraintTangent(Circle &c, Arc &a, int tagId=0);
int addConstraintTangent(Ellipse &e, Arc &a, int tagId=0);
int addConstraintTangentLine2ArcOfEllipse(Point &p1, Point &p2, Line &l, ArcOfEllipse &a, int tagId=0);
int addConstraintTangentArcOfEllipse2Line(ArcOfEllipse &a, Line &l, Point &p1, Point &p2, int tagId=0);
int addConstraintTangentLine2Arc(Point &p1, Point &p2, Arc &a, int tagId=0);
int addConstraintTangentArc2Line(Arc &a, Point &p1, Point &p2, int tagId=0);
int addConstraintTangentCircle2Arc(Circle &c, Arc &a, int tagId=0);
int addConstraintTangentEllipse2Arc(Ellipse &e, Arc &a, int tagId=0);
int addConstraintTangentArc2Circle(Arc &a, Circle &c, int tagId=0);
int addConstraintTangentArc2Ellipse(Arc &a, Ellipse &e, int tagId=0);
int addConstraintTangentArc2Arc(Arc &a1, bool reverse1, Arc &a2, bool reverse2,
int tagId=0);
int addConstraintCircleRadius(Circle &c, double *radius, int tagId=0);
int addConstraintEllipseAngleXU(Ellipse &e, double *angle, int tagId=0);
int addConstraintArcRadius(Arc &a, double *radius, int tagId=0);
int addConstraintEqualLength(Line &l1, Line &l2, double *length, int tagId=0);
int addConstraintEqualRadius(Circle &c1, Circle &c2, int tagId=0);
int addConstraintEqualRadii(Ellipse &e1, Ellipse &e2, int tagId=0);
int addConstraintEqualRadius(Circle &c1, Arc &a2, int tagId=0);
int addConstraintEqualRadius(Arc &a1, Arc &a2, int tagId=0);
int addConstraintP2PSymmetric(Point &p1, Point &p2, Line &l, int tagId=0);
int addConstraintP2PSymmetric(Point &p1, Point &p2, Point &p, int tagId=0);
// internal alignment constraints
int addConstraintInternalAlignmentPoint2Ellipse(Ellipse &e, Point &p1, InternalAlignmentType alignmentType, int tagId=0);
int addConstraintInternalAlignmentEllipseMajorDiameter(Ellipse &e, Point &p1, Point &p2, int tagId=0);
int addConstraintInternalAlignmentEllipseMinorDiameter(Ellipse &e, Point &p1, Point &p2, int tagId=0);
int addConstraintInternalAlignmentEllipseFocus1(Ellipse &e, Point &p1, int tagId=0);
int addConstraintInternalAlignmentEllipseFocus2(Ellipse &e, Point &p1, int tagId=0);
int addConstraintInternalAlignmentPoint2Ellipse(ArcOfEllipse &a, Point &p1, InternalAlignmentType alignmentType, int tagId=0);
int addConstraintInternalAlignmentEllipseMajorDiameter(ArcOfEllipse &a, Point &p1, Point &p2, int tagId=0);
int addConstraintInternalAlignmentEllipseMinorDiameter(ArcOfEllipse &a, Point &p1, Point &p2, int tagId=0);
int addConstraintInternalAlignmentEllipseFocus1(ArcOfEllipse &a, Point &p1, int tagId=0);
int addConstraintInternalAlignmentEllipseFocus2(ArcOfEllipse &a, Point &p1, int tagId=0);
void rescaleConstraint(int id, double coeff);
void declareUnknowns(VEC_pD &params);

View File

@@ -65,6 +65,28 @@ namespace GCS
Point center;
double *rad;
};
class Ellipse
{
public:
Ellipse(){ radmin = 0;}
Point center;
Point focus1; //+x
double *radmin;
};
class ArcOfEllipse
{
public:
ArcOfEllipse(){startAngle=0;endAngle=0;radmin = 0;}
double *startAngle;
double *endAngle;
double *radmin;
Point start;
Point end;
Point center;
Point focus1; //+x
};
} //namespace GCS

View File

@@ -147,8 +147,8 @@ bool isSimpleVertex(const Sketcher::SketchObject* Obj, int GeoId, PointPos PosId
if (geo->getTypeId() == Part::GeomPoint::getClassTypeId())
return true;
else if (PosId == Sketcher::mid &&
(geo->getTypeId() == Part::GeomCircle::getClassTypeId() ||
geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()))
(geo->getTypeId() == Part::GeomCircle::getClassTypeId() || // TODO: ellipse
geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()))
return true;
else
return false;
@@ -802,8 +802,10 @@ void CmdSketcherConstrainPointOnObject::activated(int iMsg)
// Currently only accepts line segments and circles
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId() ||
geom->getTypeId() == Part::GeomCircle::getClassTypeId() ||
geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ) {
geom->getTypeId() == Part::GeomCircle::getClassTypeId() || // TODO: ellipse
geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
geom->getTypeId() == Part::GeomEllipse::getClassTypeId() ||
geom->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() ) {
openCommand("add point on object constraint");
Gui::Command::doCommand(
@@ -1287,7 +1289,7 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg)
}
else if (geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId() &&
geo2->getTypeId() != Part::GeomArcOfCircle::getClassTypeId() &&
geo2->getTypeId() != Part::GeomCircle::getClassTypeId()) {
geo2->getTypeId() != Part::GeomCircle::getClassTypeId()) { // TODO: ellipse
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("The selected edge should be an arc, line or circle."));
return;
@@ -1490,7 +1492,7 @@ void CmdSketcherConstrainRadius::activated(int iMsg)
double radius = arc->getRadius();
geoIdRadiusMap.push_back(std::make_pair(GeoId, radius));
}
else if (geom && geom->getTypeId() == Part::GeomCircle::getClassTypeId()) {
else if (geom && geom->getTypeId() == Part::GeomCircle::getClassTypeId()) { // TODO: ellipse
const Part::GeomCircle *circle = dynamic_cast<const Part::GeomCircle *>(geom);
double radius = circle->getRadius();
geoIdRadiusMap.push_back(std::make_pair(GeoId, radius));
@@ -1615,7 +1617,6 @@ bool CmdSketcherConstrainRadius::isActive(void)
return isCreateConstraintActive( getActiveGuiDocument() );
}
DEF_STD_CMD_A(CmdSketcherConstrainAngle);
CmdSketcherConstrainAngle::CmdSketcherConstrainAngle()
@@ -1764,7 +1765,6 @@ bool CmdSketcherConstrainAngle::isActive(void)
return isCreateConstraintActive( getActiveGuiDocument() );
}
DEF_STD_CMD_A(CmdSketcherConstrainEqual);
CmdSketcherConstrainEqual::CmdSketcherConstrainEqual()
@@ -1838,7 +1838,7 @@ void CmdSketcherConstrainEqual::activated(int iMsg)
lineSel = true;
else if (geo->getTypeId() != Part::GeomArcOfCircle::getClassTypeId())
arcSel = true;
else if (geo->getTypeId() != Part::GeomCircle::getClassTypeId())
else if (geo->getTypeId() != Part::GeomCircle::getClassTypeId()) // TODO: ellipse
circSel = true;
else {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
@@ -2027,7 +2027,412 @@ bool CmdSketcherConstrainSymmetric::isActive(void)
return isCreateConstraintActive( getActiveGuiDocument() );
}
DEF_STD_CMD_A(CmdSketcherConstrainInternalAlignment);
CmdSketcherConstrainInternalAlignment::CmdSketcherConstrainInternalAlignment()
:Command("Sketcher_ConstrainInternalAlignment")
{
sAppModule = "Sketcher";
sGroup = QT_TR_NOOP("Sketcher");
sMenuText = QT_TR_NOOP("Constrain InternalAlignment");
sToolTipText = QT_TR_NOOP("Constraint an element to be aligned with the internal geometry of another element");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "Constraint_InternalAlignment";
sAccel = "Ctrl+A";
eType = ForEdit;
}
void CmdSketcherConstrainInternalAlignment::activated(int iMsg)
{
// get the selection
std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
// only one sketch with its subelements are allowed to be selected
if (selection.size() != 1) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Select at least one ellipse and one edge from the sketch."));
return;
}
// get the needed lists and objects
const std::vector<std::string> &SubNames = selection[0].getSubNames();
Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
// go through the selected subelements
if (SubNames.size() < 2) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Select at least one ellipse and one edge from the sketch."));
return;
}
std::vector<int> pointids;
std::vector<int> lineids;
std::vector<int> ellipseids;
std::vector<int> arcsofellipseids;
bool hasAlreadyExternal = false;
for (std::vector<std::string>::const_iterator it=SubNames.begin(); it != SubNames.end(); ++it) {
int GeoId;
Sketcher::PointPos PosId;
getIdsFromName(*it, Obj, GeoId, PosId);
if (GeoId < 0) {
if (GeoId == -1 || GeoId == -2) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Sketch axes cannot be used in internal alignment constraint"));
return;
}
else if (hasAlreadyExternal) {
checkBothExternal(-1,-2); // just for printing the error message
return;
}
else
hasAlreadyExternal = true;
}
const Part::Geometry *geo = Obj->getGeometry(GeoId);
if (geo->getTypeId() == Part::GeomPoint::getClassTypeId())
pointids.push_back(GeoId);
else if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId())
lineids.push_back(GeoId);
else if (geo->getTypeId() == Part::GeomEllipse::getClassTypeId())
ellipseids.push_back(GeoId);
else if (geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId())
arcsofellipseids.push_back(GeoId);
else {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Select two or more compatible edges"));
return;
}
}
int GeoId;
Sketcher::PointPos PosId;
getIdsFromName(SubNames[SubNames.size()-1], Obj, GeoId, PosId); // last selected element
const Part::Geometry *geo = Obj->getGeometry(GeoId);
// Currently it is only supported for ellipses
if(geo->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
// Priority list
// EllipseMajorDiameter = 1,
// EllipseMinorDiameter = 2,
// EllipseFocus1 = 3,
// EllipseFocus2 = 4
if(ellipseids.size()>1){
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("You can not internally constraint an ellipse on other ellipse. Select only one ellipse."));
return;
}
if (pointids.size()>2) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Maximum 2 points are supported."));
return;
}
if (lineids.size()>2) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Maximum 2 lines are supported."));
return;
}
// look for which internal constraints are already applied
bool major=false;
bool minor=false;
bool focus1=false;
bool focus2=false;
bool extra_elements=false;
const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues();
for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin();
it != vals.end(); ++it) {
if((*it)->Type == Sketcher::InternalAlignment && (*it)->First == GeoId)
{
switch((*it)->AlignmentType){
case Sketcher::EllipseMajorDiameter:
major=true;
break;
case Sketcher::EllipseMinorDiameter:
minor=true;
break;
case Sketcher::EllipseFocus1:
focus1=true;
break;
case Sketcher::EllipseFocus2:
focus2=true;
break;
}
}
}
if(major && minor && focus1 && focus2) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Nothing to constraint"),
QObject::tr("Currently all internal geometry of the ellipse is already exposed."));
return;
}
if((!(focus1 && focus2) && pointids.size()>=1) || // if some element is missing and we are adding an element of that type
(!(major && minor) && lineids.size()>=1) ){
openCommand("add internal alignment constraint");
if(pointids.size()>=1)
{
if(!focus1) {
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseFocus1',%d,%d,%d)) ",
selection[0].getFeatName(),pointids[0],Sketcher::start,ellipseids[0]);
}
else if(!focus2) {
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseFocus2',%d,%d,%d)) ",
selection[0].getFeatName(),pointids[0],Sketcher::start,ellipseids[0]);
focus2=true;
}
else
extra_elements=true;
}
if(pointids.size()==2)
{
if(!focus2) {
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseFocus2',%d,%d,%d)) ",
selection[0].getFeatName(),pointids[1],Sketcher::start,ellipseids[0]);
}
else
extra_elements=true;
}
if(lineids.size()>=1)
{
if(!major) {
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseMajorDiameter',%d,%d)) ",
selection[0].getFeatName(),lineids[0],ellipseids[0]);
const Part::GeomLineSegment *geo = static_cast<const Part::GeomLineSegment *>(Obj->getGeometry(lineids[0]));
if(!geo->Construction)
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.toggleConstruction(%d) ",selection[0].getFeatName(),lineids[0]);
}
else if(!minor) {
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseMinorDiameter',%d,%d)) ",
selection[0].getFeatName(),lineids[0],ellipseids[0]);
const Part::GeomLineSegment *geo = static_cast<const Part::GeomLineSegment *>(Obj->getGeometry(lineids[0]));
if(!geo->Construction)
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.toggleConstruction(%d) ",selection[0].getFeatName(),lineids[0]);
minor=true;
}
else
extra_elements=true;
}
if(lineids.size()==2)
{
if(!minor){
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseMinorDiameter',%d,%d)) ",
selection[0].getFeatName(),lineids[1],ellipseids[0]);
const Part::GeomLineSegment *geo = static_cast<const Part::GeomLineSegment *>(Obj->getGeometry(lineids[1]));
if(!geo->Construction)
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.toggleConstruction(%d) ",selection[0].getFeatName(),lineids[1]);
}
else
extra_elements=true;
}
// finish the transaction and update
commitCommand();
updateActive();
if(extra_elements){
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Extra elements"),
QObject::tr("More elements than possible for the given ellipse were provided. These were ignored."));
}
// clear the selection (convenience)
getSelection().clearSelection();
}
else {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Extra elements"),
QObject::tr("More elements than possible for the given ellipse were provided. These were ignored."));
}
}
else if(geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) {
// Priority list
// EllipseMajorDiameter = 1,
// EllipseMinorDiameter = 2,
// EllipseFocus1 = 3,
// EllipseFocus2 = 4
if(arcsofellipseids.size()>1){
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("You can not internally constraint an arc of ellipse on other arc of ellipse. Select only one arc of ellipse."));
return;
}
if(ellipseids.size()>0){
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("You can not internally constraint an ellipse on an arc of ellipse. Select only one ellipse or arc of ellipse."));
return;
}
if (pointids.size()>2) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Maximum 2 points are supported."));
return;
}
if (lineids.size()>2) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Maximum 2 lines are supported."));
return;
}
// look for which internal constraints are already applied
bool major=false;
bool minor=false;
bool focus1=false;
bool focus2=false;
bool extra_elements=false;
const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues();
for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin();
it != vals.end(); ++it) {
if((*it)->Type == Sketcher::InternalAlignment && (*it)->First == GeoId)
{
switch((*it)->AlignmentType){
case Sketcher::EllipseMajorDiameter:
major=true;
break;
case Sketcher::EllipseMinorDiameter:
minor=true;
break;
case Sketcher::EllipseFocus1:
focus1=true;
break;
case Sketcher::EllipseFocus2:
focus2=true;
break;
}
}
}
if(major && minor && focus1 && focus2) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Nothing to constraint"),
QObject::tr("Currently all internal geometry of the arc of ellipse is already exposed."));
return;
}
if((!(focus1 && focus2) && pointids.size()>=1) || // if some element is missing and we are adding an element of that type
(!(major && minor) && lineids.size()>=1) ){
openCommand("add internal alignment constraint");
if(pointids.size()>=1)
{
if(!focus1) {
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseFocus1',%d,%d,%d)) ",
selection[0].getFeatName(),pointids[0],Sketcher::start,arcsofellipseids[0]);
}
else if(!focus2) {
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseFocus2',%d,%d,%d)) ",
selection[0].getFeatName(),pointids[0],Sketcher::start,arcsofellipseids[0]);
focus2=true;
}
else
extra_elements=true;
}
if(pointids.size()==2)
{
if(!focus2) {
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseFocus2',%d,%d,%d)) ",
selection[0].getFeatName(),pointids[1],Sketcher::start,arcsofellipseids[0]);
}
else
extra_elements=true;
}
if(lineids.size()>=1)
{
if(!major) {
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseMajorDiameter',%d,%d)) ",
selection[0].getFeatName(),lineids[0],arcsofellipseids[0]);
const Part::GeomLineSegment *geo = static_cast<const Part::GeomLineSegment *>(Obj->getGeometry(lineids[0]));
if(!geo->Construction)
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.toggleConstruction(%d) ",selection[0].getFeatName(),lineids[0]);
}
else if(!minor) {
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseMinorDiameter',%d,%d)) ",
selection[0].getFeatName(),lineids[0],arcsofellipseids[0]);
const Part::GeomLineSegment *geo = static_cast<const Part::GeomLineSegment *>(Obj->getGeometry(lineids[0]));
if(!geo->Construction)
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.toggleConstruction(%d) ",selection[0].getFeatName(),lineids[0]);
minor=true;
}
else
extra_elements=true;
}
if(lineids.size()==2)
{
if(!minor){
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseMinorDiameter',%d,%d)) ",
selection[0].getFeatName(),lineids[1],arcsofellipseids[0]);
const Part::GeomLineSegment *geo = static_cast<const Part::GeomLineSegment *>(Obj->getGeometry(lineids[1]));
if(!geo->Construction)
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.toggleConstruction(%d) ",selection[0].getFeatName(),lineids[1]);
}
else
extra_elements=true;
}
// finish the transaction and update
commitCommand();
updateActive();
if(extra_elements){
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Extra elements"),
QObject::tr("More elements than possible for the given ellipse were provided. These were ignored."));
}
// clear the selection (convenience)
getSelection().clearSelection();
}
else {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Extra elements"),
QObject::tr("More elements than possible for the given arc of ellipse were provided. These were ignored."));
}
}
else {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Currently internal geometry is only supported for ellipse or arc of ellipse. The last selected element must be an ellipse or an arc of ellipse."));
}
}
bool CmdSketcherConstrainInternalAlignment::isActive(void)
{
return isCreateConstraintActive( getActiveGuiDocument() );
}
void CreateSketcherCommandsConstraints(void)
{
@@ -2048,4 +2453,5 @@ void CreateSketcherCommandsConstraints(void)
rcCmdMgr.addCommand(new CmdSketcherConstrainEqual());
rcCmdMgr.addCommand(new CmdSketcherConstrainPointOnObject());
rcCmdMgr.addCommand(new CmdSketcherConstrainSymmetric());
rcCmdMgr.addCommand(new CmdSketcherConstrainInternalAlignment());
}

View File

@@ -1793,7 +1793,580 @@ bool CmdSketcherCreateCircle::isActive(void)
{
return isCreateGeoActive(getActiveGuiDocument());
}
// ======================================================================================
/* XPM */
static const char *cursor_createellipse[]={
"32 32 3 1",
"+ c white",
"# c red",
". c None",
"......+.........................",
"......+.........................",
"......+.........................",
"......+.........................",
"......+.........................",
"................................",
"+++++...+++++...................",
"................................",
"......+.........................",
"......+.........................",
"......+.........................",
"......+.........................",
"......+.........................",
"......+..............#####......",
"..................###.....#.....",
"...............###.......##.....",
".............##..........##.....",
"...........##............##.....",
"..........##.....###....##......",
".........##.....#.#.....#.......",
"........##.....###....##........",
"........##...........##.........",
".......##..........###..........",
"......##........####............",
"......#.....####................",
"......######....................",
"................................",
"................................",
"................................",
"................................",
"................................",
"................................"};
class DrawSketchHandlerEllipse : public DrawSketchHandler
{
public:
DrawSketchHandlerEllipse() : Mode(STATUS_SEEK_First),EditCurve(34){}
virtual ~DrawSketchHandlerEllipse(){}
/// mode table
enum SelectMode {
STATUS_SEEK_First, /**< enum value ----. */
STATUS_SEEK_Second, /**< enum value ----. */
STATUS_SEEK_Third, /**< enum value ----. */
STATUS_Close
};
virtual void activated(ViewProviderSketch *sketchgui)
{
setCursor(QPixmap(cursor_createellipse),7,7);
}
virtual void mouseMove(Base::Vector2D onSketchPos)
{
if (Mode==STATUS_SEEK_First) {
setPositionText(onSketchPos);
if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) { // TODO: ellipse prio 1
renderSuggestConstraintsCursor(sugConstr1);
return;
}
}
else if (Mode==STATUS_SEEK_Second) {
double rx0 = onSketchPos.fX - EditCurve[0].fX;
double ry0 = onSketchPos.fY - EditCurve[0].fY;
for (int i=0; i < 16; i++) {
double angle = i*M_PI/16.0;
double rx = rx0 * cos(angle) + ry0 * sin(angle);
double ry = -rx0 * sin(angle) + ry0 * cos(angle);
EditCurve[1+i] = Base::Vector2D(EditCurve[0].fX + rx, EditCurve[0].fY + ry);
EditCurve[17+i] = Base::Vector2D(EditCurve[0].fX - rx, EditCurve[0].fY - ry);
}
EditCurve[33] = EditCurve[1];
// Display radius for user
float radius = (onSketchPos - EditCurve[0]).Length();
SbString text;
text.sprintf(" (%.1fR,%.1fR)", radius,radius);
setPositionText(onSketchPos, text);
sketchgui->drawEdit(EditCurve);
if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2D(0.f,0.f),
AutoConstraint::CURVE)) {
renderSuggestConstraintsCursor(sugConstr2);
return;
}
}
else if (Mode==STATUS_SEEK_Third) {
double rx0 = EditCurve[1].fX - EditCurve[0].fX; // first semidiameter
double ry0 = EditCurve[1].fY - EditCurve[0].fY; // first semidiameter
// angle between the major axis of the ellipse and the X axis
double a = (EditCurve[1]-EditCurve[0]).Length();
double phi = atan2f(EditCurve[1].fY-EditCurve[0].fY,EditCurve[1].fX-EditCurve[0].fX);
// This is the angle at cursor point
double angleatpoint = acos((onSketchPos.fX-EditCurve[0].fX+(onSketchPos.fY-EditCurve[0].fY)*tan(phi))/(a*(cos(phi)+tan(phi)*sin(phi))));
double b=(onSketchPos.fY-EditCurve[0].fY-a*cos(angleatpoint)*sin(phi))/(sin(angleatpoint)*cos(phi));
for (int i=1; i < 16; i++) {
double angle = i*M_PI/16.0;
double rx = a * cos(angle) * cos(phi) - b * sin(angle) * sin(phi);
double ry = a * cos(angle) * sin(phi) + b * sin(angle) * cos(phi);
EditCurve[1+i] = Base::Vector2D(EditCurve[0].fX + rx, EditCurve[0].fY + ry);
EditCurve[17+i] = Base::Vector2D(EditCurve[0].fX - rx, EditCurve[0].fY - ry);
}
EditCurve[33] = EditCurve[1];
EditCurve[17] = EditCurve[16];
// Display radius for user
SbString text;
text.sprintf(" (%.1fR,%.1fR)", a, b);
setPositionText(onSketchPos, text);
sketchgui->drawEdit(EditCurve);
if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2D(0.f,0.f),
AutoConstraint::CURVE)) {
renderSuggestConstraintsCursor(sugConstr2);
return;
}
}
applyCursor();
}
virtual bool pressButton(Base::Vector2D onSketchPos)
{
if (Mode==STATUS_SEEK_First){
EditCurve[0] = onSketchPos;
Mode = STATUS_SEEK_Second;
}
else if(Mode==STATUS_SEEK_Second) {
EditCurve[1] = onSketchPos;
Mode = STATUS_SEEK_Third;
}
else {
EditCurve[2] = onSketchPos;
Mode = STATUS_Close;
}
return true;
}
virtual bool releaseButton(Base::Vector2D onSketchPos)
{
if (Mode==STATUS_Close) {
unsetCursor();
resetPositionText();
// angle between the major axis of the ellipse and the X axis
double a = (EditCurve[1]-EditCurve[0]).Length();
double phi = atan2f(EditCurve[1].fY-EditCurve[0].fY,EditCurve[1].fX-EditCurve[0].fX);
// This is the angle at cursor point
double angleatpoint = acos((EditCurve[2].fX-EditCurve[0].fX+(EditCurve[2].fY-EditCurve[0].fY)*tan(phi))/(a*(cos(phi)+tan(phi)*sin(phi))));
double b=(EditCurve[2].fY-EditCurve[0].fY-a*cos(angleatpoint)*sin(phi))/(sin(angleatpoint)*cos(phi));
Base::Vector2D majAxisDir,minAxisDir,minAxisPoint,majAxisPoint;
// We always create a CCW ellipse, because we want our XY reference system to be in the +X +Y direction
// Our normal will then always be in the +Z axis (local +Z axis of the sketcher)
if(a>b)
{
// force second semidiameter to be perpendicular to first semidiamater
majAxisDir = EditCurve[1] - EditCurve[0];
Base::Vector2D perp(-majAxisDir.fY,majAxisDir.fX);
perp.Normalize();
perp.Scale(abs(b));
minAxisPoint = EditCurve[0]+perp;
majAxisPoint = EditCurve[0]+majAxisDir;
}
else {
// force second semidiameter to be perpendicular to first semidiamater
minAxisDir = EditCurve[1] - EditCurve[0];
Base::Vector2D perp(minAxisDir.fY,-minAxisDir.fX);
perp.Normalize();
perp.Scale(abs(b));
majAxisPoint = EditCurve[0]+perp;
minAxisPoint = EditCurve[0]+minAxisDir;
}
Gui::Command::openCommand("Add sketch ellipse");
Gui::Command::doCommand(Gui::Command::Doc,
"App.ActiveDocument.%s.addGeometry(Part.Ellipse"
"(App.Vector(%f,%f,0),App.Vector(%f,%f,0),App.Vector(%f,%f,0)))",
sketchgui->getObject()->getNameInDocument(),
majAxisPoint.fX, majAxisPoint.fY,
minAxisPoint.fX, minAxisPoint.fY,
EditCurve[0].fX, EditCurve[0].fY);
Gui::Command::commitCommand();
Gui::Command::updateActive();
// add auto constraints for the center point
if (sugConstr1.size() > 0) {
createAutoConstraints(sugConstr1, getHighestCurveIndex(), Sketcher::mid);
sugConstr1.clear();
}
// add suggested constraints for circumference
if (sugConstr2.size() > 0) {
//createAutoConstraints(sugConstr2, getHighestCurveIndex(), Sketcher::none);
sugConstr2.clear();
}
EditCurve.clear();
sketchgui->drawEdit(EditCurve);
sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
}
return true;
}
protected:
SelectMode Mode;
std::vector<Base::Vector2D> EditCurve;
std::vector<AutoConstraint> sugConstr1, sugConstr2;
};
DEF_STD_CMD_A(CmdSketcherCreateEllipse);
CmdSketcherCreateEllipse::CmdSketcherCreateEllipse()
: Command("Sketcher_CreateEllipse")
{
sAppModule = "Sketcher";
sGroup = QT_TR_NOOP("Sketcher");
sMenuText = QT_TR_NOOP("Create ellipse");
sToolTipText = QT_TR_NOOP("Create an ellipse in the sketch");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "Sketcher_CreateEllipse";
eType = ForEdit;
}
void CmdSketcherCreateEllipse::activated(int iMsg)
{
ActivateHandler(getActiveGuiDocument(),new DrawSketchHandlerEllipse() );
}
bool CmdSketcherCreateEllipse::isActive(void)
{
return isCreateGeoActive(getActiveGuiDocument());
}
// ======================================================================================
/* XPM */
static const char *cursor_createarcofellipse[]={
"32 32 3 1",
"+ c white",
"# c red",
". c None",
"......+.........................",
"......+.........................",
"......+.........................",
"......+.........................",
"......+.........................",
"................................",
"+++++...+++++...................",
"................................",
"......+.........................",
"......+.........................",
"......+................##.......",
"......+..............##.........",
"......+............##...........",
"......+...........##............",
"................##..............",
"...............##...............",
"..............##................",
".............###................",
"............##.........###......",
"...........##.........#.#.......",
"...........##.........###.......",
"..........##....................",
".........##.....................",
"........##......................",
"........##......................",
"........##......................",
"........#.....####..............",
"........######..................",
"................................",
"................................",
"................................",
"................................"};
class DrawSketchHandlerArcOfEllipse : public DrawSketchHandler
{
public:
DrawSketchHandlerArcOfEllipse() : Mode(STATUS_SEEK_First),EditCurve(34){}
virtual ~DrawSketchHandlerArcOfEllipse(){}
/// mode table
enum SelectMode {
STATUS_SEEK_First, /**< enum value ----. */
STATUS_SEEK_Second, /**< enum value ----. */
STATUS_SEEK_Third, /**< enum value ----. */
STATUS_SEEK_Fourth, /**< enum value ----. */
STATUS_Close
};
virtual void activated(ViewProviderSketch *sketchgui)
{
setCursor(QPixmap(cursor_createarcofellipse),7,7);
}
virtual void mouseMove(Base::Vector2D onSketchPos)
{
if (Mode==STATUS_SEEK_First) {
setPositionText(onSketchPos);
if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) { // TODO: ellipse prio 1
renderSuggestConstraintsCursor(sugConstr1);
return;
}
}
else if (Mode==STATUS_SEEK_Second) {
double rx0 = onSketchPos.fX - EditCurve[0].fX;
double ry0 = onSketchPos.fY - EditCurve[0].fY;
for (int i=0; i < 16; i++) {
double angle = i*M_PI/16.0;
double rx = rx0 * cos(angle) + ry0 * sin(angle);
double ry = -rx0 * sin(angle) + ry0 * cos(angle);
EditCurve[1+i] = Base::Vector2D(EditCurve[0].fX + rx, EditCurve[0].fY + ry);
EditCurve[17+i] = Base::Vector2D(EditCurve[0].fX - rx, EditCurve[0].fY - ry);
}
EditCurve[33] = EditCurve[1];
// Display radius for user
float radius = (onSketchPos - EditCurve[0]).Length();
SbString text;
text.sprintf(" (%.1fR,%.1fR)", radius,radius);
setPositionText(onSketchPos, text);
sketchgui->drawEdit(EditCurve);
if (seekAutoConstraint(sugConstr2, onSketchPos, Base::Vector2D(0.f,0.f),
AutoConstraint::CURVE)) {
renderSuggestConstraintsCursor(sugConstr2);
return;
}
}
else if (Mode==STATUS_SEEK_Third) {
double rx0 = EditCurve[1].fX - EditCurve[0].fX; // first semidiameter
double ry0 = EditCurve[1].fY - EditCurve[0].fY; // first semidiameter
// angle between the major axis of the ellipse and the X axis
double a = (EditCurve[1]-EditCurve[0]).Length();
double phi = atan2f(EditCurve[1].fY-EditCurve[0].fY,EditCurve[1].fX-EditCurve[0].fX);
// This is the angle at cursor point
double angleatpoint = acos((onSketchPos.fX-EditCurve[0].fX+(onSketchPos.fY-EditCurve[0].fY)*tan(phi))/(a*(cos(phi)+tan(phi)*sin(phi))));
double b=(onSketchPos.fY-EditCurve[0].fY-a*cos(angleatpoint)*sin(phi))/(sin(angleatpoint)*cos(phi));
for (int i=1; i < 16; i++) {
double angle = i*M_PI/16.0;
double rx = a * cos(angle) * cos(phi) - b * sin(angle) * sin(phi);
double ry = a * cos(angle) * sin(phi) + b * sin(angle) * cos(phi);
EditCurve[1+i] = Base::Vector2D(EditCurve[0].fX + rx, EditCurve[0].fY + ry);
EditCurve[17+i] = Base::Vector2D(EditCurve[0].fX - rx, EditCurve[0].fY - ry);
}
EditCurve[33] = EditCurve[1];
EditCurve[17] = EditCurve[16];
// Display radius for user
SbString text;
text.sprintf(" (%.1fR,%.1fR)", a, b);
setPositionText(onSketchPos, text);
sketchgui->drawEdit(EditCurve);
if (seekAutoConstraint(sugConstr3, onSketchPos, Base::Vector2D(0.f,0.f),
AutoConstraint::CURVE)) {
renderSuggestConstraintsCursor(sugConstr3);
return;
}
}
else if (Mode==STATUS_SEEK_Fourth) { // here we differ from ellipse creation
double rx0 = axisPoint.fX - centerPoint.fX; // first semidiameter
double ry0 = axisPoint.fY - centerPoint.fY; // first semidiameter
// angle between the major axis of the ellipse and the X axis
double a = (axisPoint-centerPoint).Length();
double phi = atan2(axisPoint.fY-centerPoint.fY,axisPoint.fX-centerPoint.fX);
// This is the angle at cursor point
double angleatpoint = acos((startingPoint.fX-centerPoint.fX+(startingPoint.fY-centerPoint.fY)*tan(phi))/(a*(cos(phi)+tan(phi)*sin(phi))));
double b=abs((startingPoint.fY-centerPoint.fY-a*cos(angleatpoint)*sin(phi))/(sin(angleatpoint)*cos(phi)));
double rxs = startingPoint.fX - centerPoint.fX;
double rys = startingPoint.fY - centerPoint.fY;
startAngle = atan2(a*(rys*cos(phi)-rxs*sin(phi)), b*(rxs*cos(phi)+rys*sin(phi))); // eccentric anomaly angle
double angle1 = atan2(a*((onSketchPos.fY - centerPoint.fY)*cos(phi)-(onSketchPos.fX - centerPoint.fX)*sin(phi)),
b*((onSketchPos.fX - centerPoint.fX)*cos(phi)+(onSketchPos.fY - centerPoint.fY)*sin(phi)))- startAngle;
double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * M_PI ;
arcAngle = abs(angle1-arcAngle) < abs(angle2-arcAngle) ? angle1 : angle2;
for (int i=0; i < 34; i++) {
double angle = startAngle+i*arcAngle/34.0;
double rx = a * cos(angle) * cos(phi) - b * sin(angle) * sin(phi);
double ry = a * cos(angle) * sin(phi) + b * sin(angle) * cos(phi);
EditCurve[i] = Base::Vector2D(centerPoint.fX + rx, centerPoint.fY + ry);
}
// EditCurve[33] = EditCurve[1];
// EditCurve[17] = EditCurve[16];
// Display radii and angle for user
SbString text;
text.sprintf(" (%.1fR,%.1fR,%.1fdeg)", a, b, arcAngle * 180 / M_PI);
setPositionText(onSketchPos, text);
sketchgui->drawEdit(EditCurve);
if (seekAutoConstraint(sugConstr4, onSketchPos, Base::Vector2D(0.f,0.f),
AutoConstraint::CURVE)) {
renderSuggestConstraintsCursor(sugConstr4);
return;
}
}
applyCursor();
}
virtual bool pressButton(Base::Vector2D onSketchPos)
{
if (Mode==STATUS_SEEK_First){
EditCurve[0] = onSketchPos;
centerPoint = onSketchPos;
Mode = STATUS_SEEK_Second;
}
else if(Mode==STATUS_SEEK_Second) {
EditCurve[1] = onSketchPos;
axisPoint = onSketchPos;
Mode = STATUS_SEEK_Third;
}
else if(Mode==STATUS_SEEK_Third) {
startingPoint = onSketchPos;
arcAngle = 0.;
arcAngle_t= 0.;
Mode = STATUS_SEEK_Fourth;
}
else { // Fourth
endPoint = onSketchPos;
Mode = STATUS_Close;
}
return true;
}
virtual bool releaseButton(Base::Vector2D onSketchPos)
{
if (Mode==STATUS_Close) {
unsetCursor();
resetPositionText();
// angle between the major axis of the ellipse and the X axis
double a = (axisPoint-centerPoint).Length();
double phi = atan2(axisPoint.fY-centerPoint.fY,axisPoint.fX-centerPoint.fX);
// This is the angle at cursor point
double angleatpoint = acos((startingPoint.fX-centerPoint.fX+(startingPoint.fY-centerPoint.fY)*tan(phi))/(a*(cos(phi)+tan(phi)*sin(phi))));
double b=abs((startingPoint.fY-centerPoint.fY-a*cos(angleatpoint)*sin(phi))/(sin(angleatpoint)*cos(phi)));
double angle1 = atan2(a*((endPoint.fY - centerPoint.fY)*cos(phi)-(endPoint.fX - centerPoint.fX)*sin(phi)),
b*((endPoint.fX - centerPoint.fX)*cos(phi)+(endPoint.fY - centerPoint.fY)*sin(phi)))- startAngle;
double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * M_PI ;
arcAngle = abs(angle1-arcAngle) < abs(angle2-arcAngle) ? angle1 : angle2;
if (arcAngle > 0)
endAngle = startAngle + arcAngle;
else {
endAngle = startAngle;
startAngle += arcAngle;
}
Base::Vector2D majAxisDir,minAxisDir,minAxisPoint,majAxisPoint;
// We always create a CCW ellipse, because we want our XY reference system to be in the +X +Y direction
// Our normal will then always be in the +Z axis (local +Z axis of the sketcher)
if(a>b)
{
// force second semidiameter to be perpendicular to first semidiamater
majAxisDir = axisPoint - centerPoint;
Base::Vector2D perp(-majAxisDir.fY,majAxisDir.fX);
perp.Normalize();
perp.Scale(abs(b));
minAxisPoint = centerPoint+perp;
majAxisPoint = centerPoint+majAxisDir;
}
else {
// force second semidiameter to be perpendicular to first semidiamater
minAxisDir = axisPoint - centerPoint;
Base::Vector2D perp(minAxisDir.fY,-minAxisDir.fX);
perp.Normalize();
perp.Scale(abs(b));
majAxisPoint = centerPoint+perp;
minAxisPoint = centerPoint+minAxisDir;
endAngle += M_PI/2;
startAngle += M_PI/2;
}
//startAngle=-M_PI/4;
//endAngle=M_PI/4;
Gui::Command::openCommand("Add sketch arc of ellipse");
Gui::Command::doCommand(Gui::Command::Doc,
"App.ActiveDocument.%s.addGeometry(Part.ArcOfEllipse"
"(Part.Ellipse(App.Vector(%f,%f,0),App.Vector(%f,%f,0),App.Vector(%f,%f,0)),"
"%f,%f))",
sketchgui->getObject()->getNameInDocument(),
majAxisPoint.fX, majAxisPoint.fY,
minAxisPoint.fX, minAxisPoint.fY,
centerPoint.fX, centerPoint.fY,
startAngle, endAngle); //arcAngle > 0 ? 0 : 1);
Gui::Command::commitCommand();
Gui::Command::updateActive();
// add auto constraints for the center point
if (sugConstr1.size() > 0) {
createAutoConstraints(sugConstr1, getHighestCurveIndex(), Sketcher::mid);
sugConstr1.clear();
}
// add suggested constraints for circumference
if (sugConstr2.size() > 0) {
//createAutoConstraints(sugConstr2, getHighestCurveIndex(), Sketcher::none);
sugConstr2.clear();
}
EditCurve.clear();
sketchgui->drawEdit(EditCurve);
sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
}
return true;
}
protected:
SelectMode Mode;
std::vector<Base::Vector2D> EditCurve;
Base::Vector2D centerPoint, axisPoint, startingPoint, endPoint;
double rx, ry, startAngle, endAngle, arcAngle, arcAngle_t;
std::vector<AutoConstraint> sugConstr1, sugConstr2, sugConstr3, sugConstr4;
};
DEF_STD_CMD_A(CmdSketcherCreateArcOfEllipse);
CmdSketcherCreateArcOfEllipse::CmdSketcherCreateArcOfEllipse()
: Command("Sketcher_CreateArcOfEllipse")
{
sAppModule = "Sketcher";
sGroup = QT_TR_NOOP("Sketcher");
sMenuText = QT_TR_NOOP("Create an arc of ellipse");
sToolTipText = QT_TR_NOOP("Create an arc of ellipse in the sketch");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "Sketcher_Elliptical_Arc";
eType = ForEdit;
}
void CmdSketcherCreateArcOfEllipse::activated(int iMsg)
{
ActivateHandler(getActiveGuiDocument(),new DrawSketchHandlerArcOfEllipse() );
}
bool CmdSketcherCreateArcOfEllipse::isActive(void)
{
return isCreateGeoActive(getActiveGuiDocument());
}
// ======================================================================================
@@ -2548,6 +3121,7 @@ namespace SketcherGui {
geom->getTypeId() == Part::GeomCircle::getClassTypeId()||
geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId())
return true;
// TODO: ellipse
}
return false;
}
@@ -2628,6 +3202,7 @@ public:
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId() ||
geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
geom->getTypeId() == Part::GeomCircle::getClassTypeId()
// TODO: ellipse
) {
try {
Gui::Command::openCommand("Trim edge");
@@ -3548,6 +4123,8 @@ void CreateSketcherCommandsCreateGeo(void)
rcCmdMgr.addCommand(new CmdSketcherCreateCircle());
rcCmdMgr.addCommand(new CmdSketcherCreate3PointCircle());
rcCmdMgr.addCommand(new CmdSketcherCompCreateCircle());
rcCmdMgr.addCommand(new CmdSketcherCreateEllipse());
rcCmdMgr.addCommand(new CmdSketcherCreateArcOfEllipse());
rcCmdMgr.addCommand(new CmdSketcherCreateLine());
rcCmdMgr.addCommand(new CmdSketcherCreatePolyline());
rcCmdMgr.addCommand(new CmdSketcherCreateRectangle());

View File

@@ -679,6 +679,285 @@ bool CmdSketcherSelectElementsAssociatedWithConstraints::isActive(void)
return isSketcherAcceleratorActive( getActiveGuiDocument(), true );
}
DEF_STD_CMD_A(CmdSketcherRestoreInternalAlignmentGeometry);
CmdSketcherRestoreInternalAlignmentGeometry::CmdSketcherRestoreInternalAlignmentGeometry()
:Command("Sketcher_RestoreInternalAlignmentGeometry")
{
sAppModule = "Sketcher";
sGroup = QT_TR_NOOP("Sketcher");
sMenuText = QT_TR_NOOP("Show/hide internal geometry");
sToolTipText = QT_TR_NOOP("Show all internal geometry / hide unused internal geometry");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "Sketcher_Element_Ellipse_All";
sAccel = "CTRL+SHIFT+E";
eType = ForEdit;
}
void CmdSketcherRestoreInternalAlignmentGeometry::activated(int iMsg)
{
// get the selection
std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
Sketcher::SketchObject* Obj = dynamic_cast<Sketcher::SketchObject*>(selection[0].getObject());
// only one sketch with its subelements are allowed to be selected
if (selection.size() != 1) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Select elements from a single sketch."));
return;
}
// get the needed lists and objects
const std::vector<std::string> &SubNames = selection[0].getSubNames();
const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues();
std::string doc_name = Obj->getDocument()->getName();
std::string obj_name = Obj->getNameInDocument();
std::stringstream ss;
getSelection().clearSelection();
// go through the selected subelements
for (std::vector<std::string>::const_iterator it=SubNames.begin(); it != SubNames.end(); ++it) {
// only handle edges
if (it->size() > 4 && it->substr(0,4) == "Edge") {
int GeoId = std::atoi(it->substr(4,4000).c_str()) - 1;
const Part::Geometry *geo = Obj->getGeometry(GeoId);
// Only for supported types
if(geo->getTypeId() == Part::GeomEllipse::getClassTypeId() || geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) {
// First we search what has to be restored
bool major=false;
bool minor=false;
bool focus1=false;
bool focus2=false;
bool extra_elements=false;
int majorelementindex=-1;
int minorelementindex=-1;
int focus1elementindex=-1;
int focus2elementindex=-1;
const std::vector< Sketcher::Constraint * > &vals = Obj->Constraints.getValues();
for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin();
it != vals.end(); ++it) {
if((*it)->Type == Sketcher::InternalAlignment && (*it)->Second == GeoId)
{
switch((*it)->AlignmentType){
case Sketcher::EllipseMajorDiameter:
major=true;
majorelementindex=(*it)->First;
break;
case Sketcher::EllipseMinorDiameter:
minor=true;
minorelementindex=(*it)->First;
break;
case Sketcher::EllipseFocus1:
focus1=true;
focus1elementindex=(*it)->First;
break;
case Sketcher::EllipseFocus2:
focus2=true;
focus2elementindex=(*it)->First;
break;
}
}
}
if(major && minor && focus1 && focus2)
{
// Hide unused geometry here
int majorconstraints=0; // number of constraints associated to the geoid of the major axis
int minorconstraints=0;
int focus1constraints=0;
int focus2constraints=0;
for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin();
it != vals.end(); ++it) {
if((*it)->Second == majorelementindex || (*it)->First == majorelementindex || (*it)->Third == majorelementindex)
majorconstraints++;
else if((*it)->Second == minorelementindex || (*it)->First == minorelementindex || (*it)->Third == minorelementindex)
minorconstraints++;
else if((*it)->Second == focus1elementindex || (*it)->First == focus1elementindex || (*it)->Third == focus1elementindex)
focus1constraints++;
else if((*it)->Second == focus2elementindex || (*it)->First == focus2elementindex || (*it)->Third == focus2elementindex)
focus2constraints++;
}
// those with less than 2 constraints must be removed
if(majorconstraints>=2 && minorconstraints>=2 && focus1constraints>=2 && focus2constraints>=2)
return; // nothing to delete
App::Document* doc = App::GetApplication().getActiveDocument();
if (!doc) return;
doc->openTransaction("Delete");
if(majorconstraints<2) {
ss.str(std::string());
ss << "Edge" << majorelementindex + 1;
Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str());
}
if(minorconstraints<2) {
ss.str(std::string());
ss << "Edge" << minorelementindex + 1;
Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str());
}
if(focus1constraints<2) {
ss.str(std::string());
int vertex = Obj->getVertexIndexGeoPos(focus1elementindex,Sketcher::start);
if(vertex>-1){
ss << "Vertex" << vertex + 1;
Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str());
}
}
if(focus2constraints<2) {
ss.str(std::string());
int vertex = Obj->getVertexIndexGeoPos(focus2elementindex,Sketcher::start);
if(vertex>-1){
ss << "Vertex" << vertex + 1;
Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str());
}
}
SketcherGui::ViewProviderSketch* vp = dynamic_cast<SketcherGui::ViewProviderSketch*>(getActiveGuiDocument()->getInEdit());
if (vp) {
std::vector<Gui::SelectionObject> sel = Gui::Selection().getSelectionEx(doc->getName());
vp->onDelete(sel[0].getSubNames());
}
doc->commitTransaction();
return;
}
Gui::Command::openCommand("Expose ellipse internal geometry");
int currentgeoid= Obj->getHighestCurveIndex();
int incrgeo= 0;
int majorindex=-1;
int minorindex=-1;
Base::Vector3d center;
double majord;
double minord;
double phi;
if(geo->getTypeId() == Part::GeomEllipse::getClassTypeId()){
const Part::GeomEllipse *ellipse = static_cast<const Part::GeomEllipse *>(geo);
center=ellipse->getCenter();
majord=ellipse->getMajorRadius();
minord=ellipse->getMinorRadius();
phi=ellipse->getAngleXU();
}
else {
const Part::GeomArcOfEllipse *aoe = static_cast<const Part::GeomArcOfEllipse *>(geo);
center=aoe->getCenter();
majord=aoe->getMajorRadius();
minord=aoe->getMinorRadius();
phi=aoe->getAngleXU();
}
majord*=0.99;
minord*=0.99;
Base::Vector3d majorpositiveend = center + majord * Base::Vector3d(cos(phi),sin(phi),0);
Base::Vector3d majornegativeend = center - majord * Base::Vector3d(cos(phi),sin(phi),0);
Base::Vector3d minorpositiveend = center + minord * Base::Vector3d(-sin(phi),cos(phi),0);
Base::Vector3d minornegativeend = center - minord * Base::Vector3d(-sin(phi),cos(phi),0);
double df= sqrt(majord*majord-minord*minord);
Base::Vector3d focus1P = center + df * Base::Vector3d(cos(phi),sin(phi),0);
Base::Vector3d focus2P = center - df * Base::Vector3d(cos(phi),sin(phi),0);
try{
if(!major)
{
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Line(App.Vector(%f,%f,0),App.Vector(%f,%f,0)))",
Obj->getNameInDocument(),
majornegativeend.x,majornegativeend.y,majorpositiveend.x,majorpositiveend.y); // create line for major axis
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseMajorDiameter',%d,%d)) ",
selection[0].getFeatName(),currentgeoid+incrgeo+1,GeoId); // constrain major axis
majorindex=currentgeoid+incrgeo+1;
incrgeo++;
}
if(!minor)
{
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Line(App.Vector(%f,%f,0),App.Vector(%f,%f,0)))",
Obj->getNameInDocument(),
minorpositiveend.x,minorpositiveend.y,minornegativeend.x,minornegativeend.y); // create line for minor axis
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseMinorDiameter',%d,%d)) ",
selection[0].getFeatName(),currentgeoid+incrgeo+1,GeoId); // constrain minor axis
minorindex=currentgeoid+incrgeo+1;
incrgeo++;
}
if(!focus1)
{
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Point(App.Vector(%f,%f,0)))",
Obj->getNameInDocument(),
focus1P.x,focus1P.y);
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseFocus1',%d,%d,%d)) ",
selection[0].getFeatName(),currentgeoid+incrgeo+1,Sketcher::start,GeoId); // constrain major axis
incrgeo++;
}
if(!focus2)
{
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.addGeometry(Part.Point(App.Vector(%f,%f,0)))",
Obj->getNameInDocument(),
focus2P.x,focus2P.y);
Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('InternalAlignment:EllipseFocus2',%d,%d,%d)) ",
Obj->getNameInDocument(),currentgeoid+incrgeo+1,Sketcher::start,GeoId); // constrain major axis
}
// Make lines construction lines
if(majorindex!=-1){
doCommand(Doc,"App.ActiveDocument.%s.toggleConstruction(%d) ",Obj->getNameInDocument(),majorindex);
}
if(minorindex!=-1){
doCommand(Doc,"App.ActiveDocument.%s.toggleConstruction(%d) ",Obj->getNameInDocument(),minorindex);
}
Gui::Command::commitCommand();
Gui::Command::updateActive();
}
catch (const Base::Exception& e) {
Base::Console().Error("%s\n", e.what());
Gui::Command::abortCommand();
Gui::Command::updateActive();
}
} // if(geo->getTypeId() == Part::GeomEllipse::getClassTypeId())
else {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Currently internal geometry is only supported for ellipse and arc of ellipse. The last selected element must be an ellipse or an arc of ellipse."));
}
}
}
}
bool CmdSketcherRestoreInternalAlignmentGeometry::isActive(void)
{
return isSketcherAcceleratorActive( getActiveGuiDocument(), true );
}
void CreateSketcherCommandsConstraintAccel(void)
{
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
@@ -692,4 +971,5 @@ void CreateSketcherCommandsConstraintAccel(void)
rcCmdMgr.addCommand(new CmdSketcherSelectRedundantConstraints());
rcCmdMgr.addCommand(new CmdSketcherSelectConflictingConstraints());
rcCmdMgr.addCommand(new CmdSketcherSelectElementsAssociatedWithConstraints());
rcCmdMgr.addCommand(new CmdSketcherRestoreInternalAlignmentGeometry());
}

View File

@@ -241,6 +241,27 @@ int DrawSketchHandler::seekAutoConstraint(std::vector<AutoConstraint> &suggested
tangDeviation = projDist;
}
} else if ((*it)->getTypeId() == Part::GeomEllipse::getClassTypeId()) {
// TODO: Ellipse
const Part::GeomEllipse *ellipse = dynamic_cast<const Part::GeomEllipse *>((*it));
Base::Vector3d center = ellipse->getCenter();
Base::Vector3d tmpPos(Pos.fX, Pos.fY, 0.f);
double radius = ellipse->getMajorRadius();
Base::Vector3d projPnt(0.f, 0.f, 0.f);
projPnt = projPnt.ProjToLine(center - tmpPos, Base::Vector3d(Dir.fX, Dir.fY));
double projDist = projPnt.Length();
if ( (projDist < radius + tangDeviation ) && (projDist > radius - tangDeviation)) {
//Find if nearest
if (projDist < tangDeviation) {
tangId = i;
tangDeviation = projDist;
}
}
} else if ((*it)->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
const Part::GeomArcOfCircle *arc = dynamic_cast<const Part::GeomArcOfCircle *>((*it));

View File

@@ -72,8 +72,10 @@ void EditDatumDialog::exec(bool atCursor)
{
// Return if constraint doesn't have editable value
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) {
if (sketch->hasConflicts()) {
QMessageBox::critical(qApp->activeWindow(), QObject::tr("Distance constraint"),

View File

@@ -73,7 +73,7 @@ void PropertyConstraintListItem::initialize()
(*it)->Type == Sketcher::DistanceX ||
(*it)->Type == Sketcher::DistanceY ||
(*it)->Type == Sketcher::Radius ||
(*it)->Type == Sketcher::Angle) {
(*it)->Type == Sketcher::Angle ) {
PropertyUnitItem* item = static_cast<PropertyUnitItem*>(PropertyUnitItem::create());
@@ -146,10 +146,10 @@ QVariant PropertyConstraintListItem::value(const App::Property* prop) const
(*it)->Type == Sketcher::DistanceX ||
(*it)->Type == Sketcher::DistanceY ||
(*it)->Type == Sketcher::Radius ||
(*it)->Type == Sketcher::Angle) {
(*it)->Type == Sketcher::Angle ) {
Base::Quantity quant;
if ((*it)->Type == Sketcher::Angle) {
if ((*it)->Type == Sketcher::Angle ) {
double datum = Base::toDegrees<double>((*it)->Value);
quant.setUnit(Base::Unit::Angle);
quant.setValue(datum);
@@ -220,7 +220,7 @@ bool PropertyConstraintListItem::event (QEvent* ev)
(*it)->Type == Sketcher::DistanceX ||
(*it)->Type == Sketcher::DistanceY ||
(*it)->Type == Sketcher::Radius ||
(*it)->Type == Sketcher::Angle) {
(*it)->Type == Sketcher::Angle ) {
// Get the internal name
QString internalName = QString::fromLatin1("Constraint%1").arg(id+1);

View File

@@ -319,14 +319,8 @@ void TaskSketcherConstrains::on_listWidgetConstraints_itemChanged(QListWidgetIte
QString unitStr;
switch(v->Type) {
case Sketcher::Distance:
unitStr = Base::Quantity(v->Value,Base::Unit::Length).getUserString();
break;
case Sketcher::DistanceX:
unitStr = Base::Quantity(v->Value,Base::Unit::Length).getUserString();
break;
case Sketcher::DistanceY:
unitStr = Base::Quantity(v->Value,Base::Unit::Length).getUserString();
break;
case Sketcher::Radius:
unitStr = Base::Quantity(v->Value,Base::Unit::Length).getUserString();
break;
@@ -360,10 +354,18 @@ void TaskSketcherConstrains::slotConstraintsChanged(void)
QIcon tang ( Gui::BitmapFactory().pixmap("Constraint_Tangent") );
QIcon dist ( Gui::BitmapFactory().pixmap("Constraint_Length") );
QIcon radi ( Gui::BitmapFactory().pixmap("Constraint_Radius") );
QIcon majradi ( Gui::BitmapFactory().pixmap("Constraint_Ellipse_Major_Radius") );
QIcon minradi ( Gui::BitmapFactory().pixmap("Constraint_Ellipse_Minor_Radius") );
QIcon angl ( Gui::BitmapFactory().pixmap("Constraint_InternalAngle") );
QIcon ellipseXUAngl ( Gui::BitmapFactory().pixmap("Constraint_Ellipse_Axis_Angle") );
QIcon equal( Gui::BitmapFactory().pixmap("Constraint_EqualLength") );
QIcon pntoo( Gui::BitmapFactory().pixmap("Constraint_PointOnObject") );
QIcon symm ( Gui::BitmapFactory().pixmap("Constraint_Symmetric") );
QIcon iaellipseminoraxis ( Gui::BitmapFactory().pixmap("Constraint_InternalAlignment_Ellipse_MinorAxis") );
QIcon iaellipsemajoraxis ( Gui::BitmapFactory().pixmap("Constraint_InternalAlignment_Ellipse_MajorAxis") );
QIcon iaellipsefocus1 ( Gui::BitmapFactory().pixmap("Constraint_InternalAlignment_Ellipse_Focus1") );
QIcon iaellipsefocus2 ( Gui::BitmapFactory().pixmap("Constraint_InternalAlignment_Ellipse_Focus2") );
QIcon iaellipseother ( Gui::BitmapFactory().pixmap("Constraint_InternalAlignment") );
assert(sketchView);
// Build up ListView with the constraints
@@ -464,6 +466,27 @@ void TaskSketcherConstrains::slotConstraintsChanged(void)
ui->listWidgetConstraints->addItem(item);
}
break;
case Sketcher::InternalAlignment:
if (Filter<2 || (Filter==3 && !(*it)->Name.empty()))
switch((*it)->AlignmentType){
case Sketcher::EllipseMajorDiameter:
ui->listWidgetConstraints->addItem(new ConstraintItem(iaellipsemajoraxis,name,i-1,(*it)->Type));
break;
case Sketcher::EllipseMinorDiameter:
ui->listWidgetConstraints->addItem(new ConstraintItem(iaellipseminoraxis,name,i-1,(*it)->Type));
break;
case Sketcher::EllipseFocus1:
ui->listWidgetConstraints->addItem(new ConstraintItem(iaellipsefocus1,name,i-1,(*it)->Type));
break;
case Sketcher::EllipseFocus2:
ui->listWidgetConstraints->addItem(new ConstraintItem(iaellipsefocus2,name,i-1,(*it)->Type));
break;
case Sketcher::Undef:
default:
ui->listWidgetConstraints->addItem(new ConstraintItem(iaellipseother,name,i-1,(*it)->Type));
break;
}
break;
default:
ui->listWidgetConstraints->addItem(new ConstraintItem(name,i-1,(*it)->Type));
break;

View File

@@ -148,7 +148,7 @@ void ElementView::contextMenuEvent (QContextMenuEvent* event)
CONTEXT_ITEM("Constraint_Length","Length Constraint","Sketcher_ConstrainDistance",doLengthConstraint,true)
CONTEXT_ITEM("Constraint_Radius","Radius Constraint","Sketcher_ConstrainRadius",doRadiusConstraint,true)
CONTEXT_ITEM("Constraint_InternalAngle","Angle Constraint","Sketcher_ConstrainAngle",doAngleConstraint,true)
menu.addSeparator();
CONTEXT_ITEM("Sketcher_AlterConstruction","Toggle construction line","Sketcher_ToggleConstruction",doToggleConstruction,true)
@@ -638,7 +638,12 @@ void TaskSketcherElements::slotElementsChanged(void)
QIcon Sketcher_Element_Line_EndPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Line_EndPoint") );
QIcon Sketcher_Element_Line_StartingPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Line_StartingPoint") );
QIcon Sketcher_Element_Point_StartingPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Point_StartingPoint") );
QIcon Sketcher_Element_Ellipse_Edge( Gui::BitmapFactory().pixmap("Sketcher_Element_Ellipse_Edge_2") );
QIcon Sketcher_Element_Ellipse_MidPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Ellipse_CentrePoint") );
QIcon Sketcher_Element_ArcOfEllipse_Edge( Gui::BitmapFactory().pixmap("Sketcher_Element_Elliptical_Arc_Edge") );
QIcon Sketcher_Element_ArcOfEllipse_MidPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Elliptical_Arc_Centre_Point") );
QIcon Sketcher_Element_ArcOfEllipse_StartingPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Elliptical_Arc_Start_Point") );
QIcon Sketcher_Element_ArcOfEllipse_EndPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Elliptical_Arc_End_Point") );
QIcon none( Gui::BitmapFactory().pixmap("Sketcher_Element_SelectionTypeInvalid") );
assert(sketchView);
@@ -654,29 +659,41 @@ void TaskSketcherElements::slotElementsChanged(void)
Base::Type type = (*it)->getTypeId();
ui->listWidgetElements->addItem(new ElementItem(
(type == Part::GeomPoint::getClassTypeId() && element==1) ? Sketcher_Element_Point_StartingPoint :
(type == Part::GeomLineSegment::getClassTypeId() && element==0) ? Sketcher_Element_Line_Edge :
(type == Part::GeomLineSegment::getClassTypeId() && element==1) ? Sketcher_Element_Line_StartingPoint :
(type == Part::GeomLineSegment::getClassTypeId() && element==2) ? Sketcher_Element_Line_EndPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==0) ? Sketcher_Element_Arc_Edge :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==1) ? Sketcher_Element_Arc_StartingPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==2) ? Sketcher_Element_Arc_EndPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==3) ? Sketcher_Element_Arc_MidPoint :
(type == Part::GeomCircle::getClassTypeId() && element==0) ? Sketcher_Element_Circle_Edge :
(type == Part::GeomCircle::getClassTypeId() && element==3) ? Sketcher_Element_Circle_MidPoint :
(type == Part::GeomPoint::getClassTypeId() && element==1) ? Sketcher_Element_Point_StartingPoint :
(type == Part::GeomLineSegment::getClassTypeId() && element==0) ? Sketcher_Element_Line_Edge :
(type == Part::GeomLineSegment::getClassTypeId() && element==1) ? Sketcher_Element_Line_StartingPoint :
(type == Part::GeomLineSegment::getClassTypeId() && element==2) ? Sketcher_Element_Line_EndPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==0) ? Sketcher_Element_Arc_Edge :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==1) ? Sketcher_Element_Arc_StartingPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==2) ? Sketcher_Element_Arc_EndPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==3) ? Sketcher_Element_Arc_MidPoint :
(type == Part::GeomCircle::getClassTypeId() && element==0) ? Sketcher_Element_Circle_Edge :
(type == Part::GeomCircle::getClassTypeId() && element==3) ? Sketcher_Element_Circle_MidPoint :
(type == Part::GeomEllipse::getClassTypeId() && element==0) ? Sketcher_Element_Ellipse_Edge :
(type == Part::GeomEllipse::getClassTypeId() && element==3) ? Sketcher_Element_Ellipse_MidPoint :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfEllipse_Edge :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfEllipse_StartingPoint :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfEllipse_EndPoint :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfEllipse_MidPoint :
none,
type == Part::GeomPoint::getClassTypeId() ? ( isNamingBoxChecked ?
(tr("Point") + QString::fromLatin1("(Edge%1)").arg(i)):
(QString::fromLatin1("%1-").arg(i)+tr("Point"))) :
type == Part::GeomLineSegment::getClassTypeId() ? ( isNamingBoxChecked ?
(tr("Line") + QString::fromLatin1("(Edge%1)").arg(i)):
(QString::fromLatin1("%1-").arg(i)+tr("Line"))) :
type == Part::GeomArcOfCircle::getClassTypeId() ? ( isNamingBoxChecked ?
(tr("Arc") + QString::fromLatin1("(Edge%1)").arg(i)):
(QString::fromLatin1("%1-").arg(i)+tr("Arc"))) :
type == Part::GeomCircle::getClassTypeId() ? ( isNamingBoxChecked ?
(tr("Circle") + QString::fromLatin1("(Edge%1)").arg(i)):
(QString::fromLatin1("%1-").arg(i)+tr("Circle"))) :
type == Part::GeomPoint::getClassTypeId() ? ( isNamingBoxChecked ?
(tr("Point") + QString::fromLatin1("(Edge%1)").arg(i)):
(QString::fromLatin1("%1-").arg(i)+tr("Point"))) :
type == Part::GeomLineSegment::getClassTypeId() ? ( isNamingBoxChecked ?
(tr("Line") + QString::fromLatin1("(Edge%1)").arg(i)):
(QString::fromLatin1("%1-").arg(i)+tr("Line"))) :
type == Part::GeomArcOfCircle::getClassTypeId() ? ( isNamingBoxChecked ?
(tr("Arc") + QString::fromLatin1("(Edge%1)").arg(i)):
(QString::fromLatin1("%1-").arg(i)+tr("Arc"))) :
type == Part::GeomCircle::getClassTypeId() ? ( isNamingBoxChecked ?
(tr("Circle") + QString::fromLatin1("(Edge%1)").arg(i)):
(QString::fromLatin1("%1-").arg(i)+tr("Circle"))) :
type == Part::GeomEllipse::getClassTypeId() ? ( isNamingBoxChecked ?
(tr("Ellipse") + QString::fromLatin1("(Edge%1)").arg(i)):
(QString::fromLatin1("%1-").arg(i)+tr("Ellipse"))) :
type == Part::GeomArcOfEllipse::getClassTypeId() ? ( isNamingBoxChecked ?
(tr("Elliptical Arc") + QString::fromLatin1("(Edge%1)").arg(i)):
(QString::fromLatin1("%1-").arg(i)+tr("Elliptical Arc"))) :
( isNamingBoxChecked ?
(tr("Other") + QString::fromLatin1("(Edge%1)").arg(i)):
(QString::fromLatin1("%1-").arg(i)+tr("Other"))),
@@ -749,16 +766,17 @@ void TaskSketcherElements::on_listWidgetElements_filterShortcutPressed()
switch(element)
{
case 0: // Edge
element = ( type == Part::GeomCircle::getClassTypeId() ) ? 3 : 1;
element = ( type == Part::GeomCircle::getClassTypeId() || type == Part::GeomEllipse::getClassTypeId() ) ? 3 : 1;
break;
case 1: // StartingPoint
element = ( type == Part::GeomCircle::getClassTypeId() ) ? 3 :
( type == Part::GeomPoint::getClassTypeId() ) ? 1 : 2;
element = ( type == Part::GeomCircle::getClassTypeId() || type == Part::GeomEllipse::getClassTypeId() ) ? 3 :
( type == Part::GeomPoint::getClassTypeId() ) ? 1 : 2;
break;
case 2: // EndPoint
element = ( type == Part::GeomLineSegment::getClassTypeId() ) ? 0 :
( type == Part::GeomPoint::getClassTypeId() ) ? 1 : 3;
( type == Part::GeomPoint::getClassTypeId() ) ? 1 : 3;
break;
case 3: // MidPoint
element = ( type == Part::GeomPoint::getClassTypeId() ) ? 1 : 0;
@@ -850,22 +868,34 @@ void TaskSketcherElements::updateIcons(int element)
QIcon Sketcher_Element_Line_EndPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Line_EndPoint") );
QIcon Sketcher_Element_Line_StartingPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Line_StartingPoint") );
QIcon Sketcher_Element_Point_StartingPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Point_StartingPoint") );
QIcon Sketcher_Element_Ellipse_Edge( Gui::BitmapFactory().pixmap("Sketcher_Element_Ellipse_Edge_2") );
QIcon Sketcher_Element_Ellipse_MidPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Ellipse_CentrePoint") );
QIcon Sketcher_Element_ArcOfEllipse_Edge( Gui::BitmapFactory().pixmap("Sketcher_Element_Elliptical_Arc_Edge") );
QIcon Sketcher_Element_ArcOfEllipse_MidPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Elliptical_Arc_Centre_Point") );
QIcon Sketcher_Element_ArcOfEllipse_StartingPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Elliptical_Arc_Start_Point") );
QIcon Sketcher_Element_ArcOfEllipse_EndPoint( Gui::BitmapFactory().pixmap("Sketcher_Element_Elliptical_Arc_End_Point") );
QIcon none( Gui::BitmapFactory().pixmap("Sketcher_Element_SelectionTypeInvalid") );
for (int i=0;i<ui->listWidgetElements->count(); i++) {
Base::Type type = static_cast<ElementItem *>(ui->listWidgetElements->item(i))->GeometryType;
ui->listWidgetElements->item(i)->setIcon(
(type == Part::GeomPoint::getClassTypeId() && element==1) ? Sketcher_Element_Point_StartingPoint :
(type == Part::GeomLineSegment::getClassTypeId() && element==0) ? Sketcher_Element_Line_Edge :
(type == Part::GeomLineSegment::getClassTypeId() && element==1) ? Sketcher_Element_Line_StartingPoint :
(type == Part::GeomLineSegment::getClassTypeId() && element==2) ? Sketcher_Element_Line_EndPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==0) ? Sketcher_Element_Arc_Edge :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==1) ? Sketcher_Element_Arc_StartingPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==2) ? Sketcher_Element_Arc_EndPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==3) ? Sketcher_Element_Arc_MidPoint :
(type == Part::GeomCircle::getClassTypeId() && element==0) ? Sketcher_Element_Circle_Edge :
(type == Part::GeomCircle::getClassTypeId() && element==3) ? Sketcher_Element_Circle_MidPoint :
(type == Part::GeomPoint::getClassTypeId() && element==1) ? Sketcher_Element_Point_StartingPoint :
(type == Part::GeomLineSegment::getClassTypeId() && element==0) ? Sketcher_Element_Line_Edge :
(type == Part::GeomLineSegment::getClassTypeId() && element==1) ? Sketcher_Element_Line_StartingPoint :
(type == Part::GeomLineSegment::getClassTypeId() && element==2) ? Sketcher_Element_Line_EndPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==0) ? Sketcher_Element_Arc_Edge :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==1) ? Sketcher_Element_Arc_StartingPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==2) ? Sketcher_Element_Arc_EndPoint :
(type == Part::GeomArcOfCircle::getClassTypeId() && element==3) ? Sketcher_Element_Arc_MidPoint :
(type == Part::GeomCircle::getClassTypeId() && element==0) ? Sketcher_Element_Circle_Edge :
(type == Part::GeomCircle::getClassTypeId() && element==3) ? Sketcher_Element_Circle_MidPoint :
(type == Part::GeomEllipse::getClassTypeId() && element==0) ? Sketcher_Element_Ellipse_Edge :
(type == Part::GeomEllipse::getClassTypeId() && element==3) ? Sketcher_Element_Ellipse_MidPoint :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==0) ? Sketcher_Element_ArcOfEllipse_Edge :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==1) ? Sketcher_Element_ArcOfEllipse_StartingPoint :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==2) ? Sketcher_Element_ArcOfEllipse_EndPoint :
(type == Part::GeomArcOfEllipse::getClassTypeId() && element==3) ? Sketcher_Element_ArcOfEllipse_MidPoint :
none);
}
}

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);
}

View File

@@ -136,12 +136,16 @@ inline void SketcherAddWorkspaceArcs<Gui::MenuItem>(Gui::MenuItem& geom){
geom << "Sketcher_CreateArc"
<< "Sketcher_Create3PointArc"
<< "Sketcher_CreateCircle"
<< "Sketcher_Create3PointCircle";
<< "Sketcher_Create3PointCircle"
<< "Sketcher_CreateEllipse"
<< "Sketcher_CreateArcOfEllipse";
}
template <>
inline void SketcherAddWorkspaceArcs<Gui::ToolBarItem>(Gui::ToolBarItem& geom){
geom << "Sketcher_CompCreateArc"
<< "Sketcher_CompCreateCircle";
<< "Sketcher_CompCreateCircle"
<< "Sketcher_CreateEllipse"
<< "Sketcher_CreateArcOfEllipse";
}
template <typename T>
void SketcherAddWorkspaceRegularPolygon(T& geom);
@@ -177,9 +181,32 @@ inline void SketcherAddWorkbenchGeometries(T& geom){
/*<< "Sketcher_CreateDraftLine"*/;
}
template <typename T>
inline void SketcherAddWorkbenchConstraints(T& cons){
inline void SketcherAddWorkbenchConstraints(T& cons);
template <>
inline void SketcherAddWorkbenchConstraints<Gui::MenuItem>(Gui::MenuItem& cons){
cons << "Sketcher_ConstrainCoincident"
<< "Sketcher_ConstrainPointOnObject"
<< "Sketcher_ConstrainVertical"
<< "Sketcher_ConstrainHorizontal"
<< "Sketcher_ConstrainParallel"
<< "Sketcher_ConstrainPerpendicular"
<< "Sketcher_ConstrainTangent"
<< "Sketcher_ConstrainEqual"
<< "Sketcher_ConstrainSymmetric"
<< "Separator"
<< "Sketcher_ConstrainLock"
<< "Sketcher_ConstrainDistanceX"
<< "Sketcher_ConstrainDistanceY"
<< "Sketcher_ConstrainDistance"
<< "Sketcher_ConstrainRadius"
<< "Sketcher_ConstrainAngle"
<< "Sketcher_ConstrainInternalAlignment";
}
template <>
inline void SketcherAddWorkbenchConstraints<Gui::ToolBarItem>(Gui::ToolBarItem& cons){
cons << "Sketcher_ConstrainCoincident"
<< "Sketcher_ConstrainPointOnObject"
<< "Sketcher_ConstrainVertical"
@@ -196,7 +223,6 @@ inline void SketcherAddWorkbenchConstraints(T& cons){
<< "Sketcher_ConstrainDistance"
<< "Sketcher_ConstrainRadius"
<< "Sketcher_ConstrainAngle";
}
template <typename T>
@@ -212,13 +238,15 @@ inline void SketcherAddWorkbenchTools<Gui::MenuItem>(Gui::MenuItem& consaccel){
<< "Sketcher_SelectHorizontalAxis"
<< "Sketcher_SelectRedundantConstraints"
<< "Sketcher_SelectConflictingConstraints"
<< "Sketcher_SelectElementsAssociatedWithConstraints";
<< "Sketcher_SelectElementsAssociatedWithConstraints"
<< "Sketcher_RestoreInternalAlignmentGeometry";
}
template <>
inline void SketcherAddWorkbenchTools<Gui::ToolBarItem>(Gui::ToolBarItem& consaccel){
consaccel << "Sketcher_CloseShape"
<< "Sketcher_ConnectLines"
<< "Sketcher_SelectConstraints";
<< "Sketcher_SelectConstraints"
<< "Sketcher_RestoreInternalAlignmentGeometry";
}
template <typename T>