+ unify DLL export defines to namespace names

git-svn-id: https://free-cad.svn.sourceforge.net/svnroot/free-cad/trunk@5000 e8eeb9e2-ec13-0410-a4a9-efa5cf37419d
This commit is contained in:
wmayer
2011-10-10 13:44:52 +00:00
commit 120ca87015
4155 changed files with 2965978 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
/***************************************************************************
* Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) *
* *
* 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 <Python.h>
#endif
#include <Base/Console.h>
#include <Base/Interpreter.h>
#include "SketchObjectSF.h"
#include "SketchObject.h"
#include "Constraint.h"
#include "Sketch.h"
#include "ConstraintPy.h"
#include "SketchPy.h"
#include "PropertyConstraintList.h"
extern struct PyMethodDef Sketcher_methods[];
PyDoc_STRVAR(module_Sketcher_doc,
"This module is the Sketcher module.");
/* Python entry */
extern "C" {
void SketcherExport initSketcher()
{
// load dependent module
try {
Base::Interpreter().runString("import Part");
}
catch(const Base::Exception& e) {
PyErr_SetString(PyExc_ImportError, e.what());
return;
}
PyObject* sketcherModule = Py_InitModule3("Sketcher", Sketcher_methods, module_Sketcher_doc); /* mod name, table ptr */
// Add Types to module
Base::Interpreter().addType(&Sketcher::ConstraintPy ::Type,sketcherModule,"Constraint");
Base::Interpreter().addType(&Sketcher::SketchPy ::Type,sketcherModule,"Sketch");
// NOTE: To finish the initialization of our own type objects we must
// call PyType_Ready, otherwise we run into a segmentation fault, later on.
// This function is responsible for adding inherited slots from a type's base class.
Sketcher::SketchObjectSF ::init();
Sketcher::SketchObject ::init();
Sketcher::SketchObjectPython ::init();
Sketcher::Sketch ::init();
Sketcher::Constraint ::init();
Sketcher::PropertyConstraintList::init();
Base::Console().Log("Loading Sketcher module... done\n");
}
} // extern "C"
// debug print for sketchsolv
void debugprint(std::string s)
{
Base::Console().Log(s.c_str());
}

View File

@@ -0,0 +1,134 @@
/***************************************************************************
* Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) *
* *
* 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 <BRepPrimAPI_MakeBox.hxx>
# include <TopoDS_Face.hxx>
# include <Geom_Plane.hxx>
# include <Handle_Geom_Plane.hxx>
#endif
#include <Base/Console.h>
#include <Base/PyObjectBase.h>
#include <Base/Exception.h>
#include <Base/FileInfo.h>
#include <App/Application.h>
#include <App/Document.h>
// Things from the part module
#include <Mod/Part/App/TopoShape.h>
#include <Mod/Part/App/TopoShapePy.h>
#include "SketchObjectSF.h"
using Base::Console;
using namespace Part;
using namespace std;
/* module functions */
static PyObject * open(PyObject *self, PyObject *args)
{
const char* Name;
if (!PyArg_ParseTuple(args, "s",&Name))
return NULL;
PY_TRY {
} PY_CATCH;
//Base::Console().Log("Open in Part with %s",Name);
Base::FileInfo file(Name);
// extract ending
if (file.extension() == "")
Py_Error(PyExc_Exception,"no file ending");
//if (file.hasExtension("igs") || file.hasExtension("iges")) {
// // create new document and add Import feature
// App::Document *pcDoc = App::GetApplication().newDocument(file.fileNamePure().c_str());
// Part::ImportIges *pcFeature = (Part::ImportIges*) pcDoc->addObject("Part::ImportIges",file.fileNamePure().c_str());
// pcFeature->FileName.setValue(Name);
// pcDoc->recompute();
//}
// else {
Py_Error(PyExc_Exception,"unknown file ending");
//}
Py_Return;
}
/* module functions */
static PyObject * insert(PyObject *self, PyObject *args)
{
const char* Name;
const char* DocName;
if (!PyArg_ParseTuple(args, "ss",&Name,&DocName))
return NULL;
PY_TRY {
//Base::Console().Log("Insert in Part with %s",Name);
Base::FileInfo file(Name);
// extract ending
if (file.extension() == "")
Py_Error(PyExc_Exception,"no file ending");
App::Document *pcDoc = App::GetApplication().getDocument(DocName);
if (!pcDoc) {
pcDoc = App::GetApplication().newDocument(DocName);
}
if (file.hasExtension("skf")) {
Sketcher::SketchObjectSF *pcFeature = (Sketcher::SketchObjectSF *)pcDoc->addObject("Sketcher::SketchObjectSF",file.fileNamePure().c_str());
pcFeature->SketchFlatFile.setValue(Name);
pcDoc->recompute();
}
else {
Py_Error(PyExc_Exception,"unknown file ending");
}
} PY_CATCH;
Py_Return;
}
/* module functions */
//static PyObject * read(PyObject *self, PyObject *args)
//{
// const char* Name;
// if (!PyArg_ParseTuple(args, "s",&Name))
// return NULL;
// PY_TRY {
// } PY_CATCH;
//
// Py_Return;
//}
/* registration table */
struct PyMethodDef Sketcher_methods[] = {
{"open" , open, 1},
{"insert" , insert, 1},
// {"read" , read, 1},
{NULL, NULL} /* end of table marker */
};

View File

@@ -0,0 +1,126 @@
if(MSVC)
add_definitions(-DFCAppSketcher -DHAVE_ACOSH -DHAVE_ASINH -DHAVE_ATANH)
else(MSVC)
add_definitions(-DHAVE_LIMITS_H -DHAVE_CONFIG_H)
endif(MSVC)
include_directories(
${CMAKE_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/..
${CMAKE_CURRENT_BINARY_DIR}/..
${Boost_INCLUDE_DIRS}
${OCC_INCLUDE_DIR}
${ZLIB_INCLUDE_DIR}
${PYTHON_INCLUDE_PATH}
${XERCESC_INCLUDE_DIR}
${EIGEN3_INCLUDE_DIR}
)
link_directories(${OCC_LIBRARY_DIR})
set(Sketcher_LIBS
Part
FreeCADApp
)
generate_from_xml(SketchObjectSFPy)
generate_from_xml(SketchObjectPy)
generate_from_xml(ConstraintPy)
generate_from_xml(SketchPy)
SET(Properties_SRCS
PropertyConstraintList.cpp
PropertyConstraintList.h
)
SOURCE_GROUP("Properties" FILES ${Properties_SRCS})
SET(Features_SRCS
SketchObjectSF.cpp
SketchObjectSF.h
SketchObject.cpp
SketchObject.h
)
SOURCE_GROUP("Features" FILES ${Features_SRCS})
SET(Datatypes_SRCS
Constraint.cpp
Constraint.h
Sketch.cpp
Sketch.h
)
SOURCE_GROUP("Datatypes" FILES ${Datatypes_SRCS})
SET(Python_SRCS
SketchObjectSFPy.xml
SketchObjectSFPyImp.cpp
SketchObjectPy.xml
SketchObjectPyImp.cpp
ConstraintPyImp.cpp
ConstraintPy.xml
SketchPy.xml
SketchPyImp.cpp
)
SOURCE_GROUP("Python" FILES ${Python_SRCS})
SET(FreeGCS_SRCS
freegcs/qp_eq.h
freegcs/GCS.cpp
freegcs/GCS.h
freegcs/Util.h
freegcs/Geo.h
freegcs/Constraints.cpp
freegcs/Constraints.h
freegcs/SubSystem.cpp
freegcs/SubSystem.h
freegcs/qp_eq.cpp
freegcs/qp_eq.h
)
SOURCE_GROUP("FreeGCS" FILES ${FreeGCS_SRCS})
SET(SketchModule_SRCS
AppSketcher.cpp
AppSketcherPy.cpp
PreCompiled.cpp
PreCompiled.h
)
SOURCE_GROUP("Module" FILES ${SketchModule_SRCS})
SET(Sketcher_SRCS
${Features_SRCS}
${FreeGCS_SRCS}
${SketchModule_SRCS}
${Python_SRCS}
${Properties_SRCS}
${Datatypes_SRCS}
)
SET(Sketcher_Scripts
Init.py
SketcherExample.py
TestSketcherApp.py
)
add_library(Sketcher SHARED ${Sketcher_SRCS})
target_link_libraries(Sketcher ${Sketcher_LIBS})
fc_copy_script("Mod/Sketcher" "Sketcher" ${Sketcher_Scripts})
if(MSVC)
set_target_properties(Sketcher PROPERTIES SUFFIX ".pyd")
set_target_properties(Sketcher PROPERTIES DEBUG_OUTPUT_NAME "Sketcher_d")
set_target_properties(Sketcher PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Mod/Sketcher)
set_target_properties(Sketcher PROPERTIES PREFIX "../")
elseif(MINGW)
set_target_properties(Sketcher PROPERTIES SUFFIX ".pyd")
set_target_properties(Sketcher PROPERTIES DEBUG_OUTPUT_NAME "Sketcher_d")
set_target_properties(Sketcher PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Mod/Sketcher)
set_target_properties(Sketcher PROPERTIES PREFIX "")
else(MSVC)
set_target_properties(Sketcher PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Mod/Sketcher)
set_target_properties(Sketcher PROPERTIES PREFIX "")
endif(MSVC)
install(TARGETS Sketcher DESTINATION lib)

View File

@@ -0,0 +1,126 @@
/***************************************************************************
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2008 *
* *
* 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_
#endif
#include <Base/Writer.h>
#include <Base/Reader.h>
#include "Constraint.h"
#include "ConstraintPy.h"
using namespace Sketcher;
using namespace Base;
TYPESYSTEM_SOURCE(Sketcher::Constraint, Base::Persistence)
const int Constraint::GeoUndef = -2000;
Constraint::Constraint()
: Type(None),
Name(""),
Value(0.0),
First(GeoUndef),
FirstPos(none),
Second(GeoUndef),
SecondPos(none),
Third(GeoUndef),
ThirdPos(none),
LabelDistance(10.f)
{
}
Constraint::Constraint(const Constraint& from)
: Type(from.Type),
Name(from.Name),
Value(from.Value),
First(from.First),
FirstPos(from.FirstPos),
Second(from.Second),
SecondPos(from.SecondPos),
Third(from.Third),
ThirdPos(from.ThirdPos),
LabelDistance(from.LabelDistance)
{
}
Constraint::~Constraint()
{
}
Constraint *Constraint::clone(void) const
{
return new Constraint(*this);
}
PyObject *Constraint::getPyObject(void)
{
return new ConstraintPy(new Constraint(*this));
}
unsigned int Constraint::getMemSize (void) const
{
return 0;
}
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<< "\" />"
<< std::endl;
}
void Constraint::Restore(XMLReader &reader)
{
reader.readElement("Constrain");
Name = reader.getAttribute("Name");
Type = (ConstraintType) reader.getAttributeAsInteger("Type");
Value = reader.getAttributeAsFloat("Value");
First = reader.getAttributeAsInteger("First");
FirstPos = (PointPos) reader.getAttributeAsInteger("FirstPos");
Second = reader.getAttributeAsInteger("Second");
SecondPos = (PointPos) reader.getAttributeAsInteger("SecondPos");
// read the third geo group if present
if (reader.hasAttribute("Third")) {
Third = reader.getAttributeAsInteger("Third");
ThirdPos = (PointPos) reader.getAttributeAsInteger("ThirdPos");
}
// Read the distance a constraint label has been moved
if (reader.hasAttribute("LabelDistance"))
LabelDistance = (float)reader.getAttributeAsFloat("LabelDistance");
}

View File

@@ -0,0 +1,91 @@
/***************************************************************************
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2008 *
* *
* 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 *
* *
***************************************************************************/
#ifndef SKETCHER_CONSTRAINT_H
#define SKETCHER_CONSTRAINT_H
#include <Base/Persistence.h>
namespace Sketcher
{
enum ConstraintType {
None,
Coincident,
Horizontal,
Vertical,
Parallel,
Tangent,
Distance,
DistanceX,
DistanceY,
Angle,
Perpendicular,
Radius,
Equal,
PointOnObject,
Symmetric
};
/// define if you want to use the end or start point
enum PointPos { none, start, end, mid };
class SketcherExport Constraint :public Base::Persistence
{
TYPESYSTEM_HEADER();
public:
~Constraint();
Constraint();
Constraint(const Constraint&);
virtual Constraint *clone(void)const;
static const int GeoUndef;
// from base class
virtual unsigned int getMemSize(void) const;
virtual void Save(Base::Writer &/*writer*/) const;
virtual void Restore(Base::XMLReader &/*reader*/);
virtual PyObject *getPyObject(void);
friend class Sketch;
public:
ConstraintType Type;
std::string Name;
double Value;
int First;
PointPos FirstPos;
int Second;
PointPos SecondPos;
int Third;
PointPos ThirdPos;
float LabelDistance;
};
} //namespace Part
#endif // SKETCHER_CONSTRAINT_H

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="PersistencePy"
Name="ConstraintPy"
Twin="Constraint"
TwinPointer="Constraint"
Include="Mod/Sketcher/App/Constraint.h"
Namespace="Sketcher"
FatherInclude="Base/PersistencePy.h"
FatherNamespace="Base"
Constructor="true">
<Documentation>
<Author Licence="LGPL" Name="Juergen Riegel" EMail="FreeCAD@juergen-riegel.net" />
<UserDocu>With this objects you can handle sketches</UserDocu>
</Documentation>
<Attribute Name="First" ReadOnly="false">
<Documentation>
<UserDocu>First geometry index the Constraint referse to</UserDocu>
</Documentation>
<Parameter Name="First" Type="Int"/>
</Attribute>
<Attribute Name="Second" ReadOnly="false">
<Documentation>
<UserDocu>Second geometry index the Constraint referse to</UserDocu>
</Documentation>
<Parameter Name="Second" Type="Int"/>
</Attribute>
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,342 @@
/***************************************************************************
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2010 *
* *
* 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"
#include <strstream>
#include "Mod/Sketcher/App/Constraint.h"
// inclusion of the generated files (generated out of ConstraintPy.xml)
#include "ConstraintPy.h"
#include "ConstraintPy.cpp"
using namespace Sketcher;
PyObject *ConstraintPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
{
// create a new instance of ConstraintPy and the Twin object
return new ConstraintPy(new Constraint);
}
// constructor method
int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
{
if (PyArg_ParseTuple(args, "")) {
return 0;
}
PyErr_Clear();
char *ConstraintType;
int FirstIndex = Constraint::GeoUndef;
int FirstPos = none;
int SecondIndex= Constraint::GeoUndef;
int SecondPos = none;
int ThirdIndex = Constraint::GeoUndef;
int ThirdPos = none;
double Value = 0;
// Note: In Python 2.x PyArg_ParseTuple prints a warning if a float is given but an integer is expected.
// This means we must use a PyObject and check afterwards if it's a float or integer.
PyObject* index_or_value;
int any_index;
// ConstraintType, GeoIndex
if (PyArg_ParseTuple(args, "si", &ConstraintType, &FirstIndex)) {
if (strcmp("Horizontal",ConstraintType) == 0) {
this->getConstraintPtr()->Type = Horizontal;
this->getConstraintPtr()->First = FirstIndex;
return 0;
}
else if (strcmp("Vertical",ConstraintType) == 0) {
this->getConstraintPtr()->Type = Vertical;
this->getConstraintPtr()->First = FirstIndex;
return 0;
}
}
PyErr_Clear();
if (PyArg_ParseTuple(args, "siO", &ConstraintType, &FirstIndex, &index_or_value)) {
// ConstraintType, GeoIndex1, GeoIndex2
if (PyInt_Check(index_or_value)) {
SecondIndex = PyInt_AsLong(index_or_value);
bool valid = false;
if (strcmp("Tangent",ConstraintType) == 0) {
this->getConstraintPtr()->Type = Tangent;
valid = true;
}
else if (strcmp("Parallel",ConstraintType) == 0) {
this->getConstraintPtr()->Type = Parallel;
valid = true;
}
else if (strcmp("Perpendicular",ConstraintType) == 0) {
this->getConstraintPtr()->Type = Perpendicular;
valid = true;
}
else if (strcmp("Equal",ConstraintType) == 0) {
this->getConstraintPtr()->Type = Equal;
valid = true;
}
if (valid) {
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->Second = SecondIndex;
return 0;
}
}
// ConstraintType, GeoIndex, Value
else if (PyFloat_Check(index_or_value)) {
Value = PyFloat_AsDouble(index_or_value);
bool valid = false;
if (strcmp("Distance",ConstraintType) == 0 ) {
this->getConstraintPtr()->Type = Distance;
valid = true;
}
else if (strcmp("Angle",ConstraintType) == 0 ) {
this->getConstraintPtr()->Type = Angle;
valid = true;
}
else if (strcmp("DistanceX",ConstraintType) == 0) {
this->getConstraintPtr()->Type = DistanceX;
valid = true;
}
else if (strcmp("DistanceY",ConstraintType) == 0) {
this->getConstraintPtr()->Type = DistanceY;
valid = true;
}
else if (strcmp("Radius",ConstraintType) == 0) {
this->getConstraintPtr()->Type = Radius;
valid = true;
}
if (valid) {
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->Value = Value;
return 0;
}
}
}
PyErr_Clear();
if (PyArg_ParseTuple(args, "siiO", &ConstraintType, &FirstIndex, &any_index, &index_or_value)) {
// ConstraintType, GeoIndex1, PosIndex1, GeoIndex2
if (PyInt_Check(index_or_value)) {
FirstPos = any_index;
SecondIndex = PyInt_AsLong(index_or_value);
if (strcmp("Tangent", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Tangent;
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->FirstPos = (Sketcher::PointPos) FirstPos;
this->getConstraintPtr()->Second = SecondIndex;
return 0;
}
if (strcmp("PointOnObject", ConstraintType) == 0) {
this->getConstraintPtr()->Type = PointOnObject;
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->FirstPos = (Sketcher::PointPos) FirstPos;
this->getConstraintPtr()->Second = SecondIndex;
return 0;
}
}
// ConstraintType, GeoIndex1, GeoIndex2, Value
// ConstraintType, GeoIndex, PosIndex, Value
else if (PyFloat_Check(index_or_value)) {
SecondIndex = any_index;
Value = PyFloat_AsDouble(index_or_value);
//if (strcmp("Distance",ConstraintType) == 0) {
// this->getConstraintPtr()->Type = Distance;
// this->getConstraintPtr()->First = FirstIndex;
// this->getConstraintPtr()->Second = SecondIndex;
// this->getConstraintPtr()->Value = Value;
// return 0;
//}
//else
if (strcmp("Angle",ConstraintType) == 0) {
this->getConstraintPtr()->Type = Angle;
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->Second = SecondIndex;
this->getConstraintPtr()->Value = Value;
return 0;
}
else if (strcmp("DistanceX",ConstraintType) == 0) {
FirstPos = SecondIndex;
SecondIndex = -1;
this->getConstraintPtr()->Type = DistanceX;
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->FirstPos = (Sketcher::PointPos) FirstPos;
this->getConstraintPtr()->Value = Value;
return 0;
}
else if (strcmp("DistanceY",ConstraintType) == 0) {
FirstPos = SecondIndex;
SecondIndex = -1;
this->getConstraintPtr()->Type = DistanceY;
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->FirstPos = (Sketcher::PointPos) FirstPos;
this->getConstraintPtr()->Value = Value;
return 0;
}
}
}
PyErr_Clear();
if (PyArg_ParseTuple(args, "siiiO", &ConstraintType, &FirstIndex, &FirstPos, &SecondIndex, &index_or_value)) {
// Value, ConstraintType, GeoIndex1, PosIndex1, GeoIndex2, PosIndex2
if (PyInt_Check(index_or_value)) {
SecondPos = PyInt_AsLong(index_or_value);
bool valid = false;
if (strcmp("Coincident", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Coincident;
valid = true;
}
else if (strcmp("Horizontal", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Horizontal;
valid = true;
}
else if (strcmp("Vertical", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Vertical;
valid = true;
}
else if (strcmp("Tangent", ConstraintType) == 0) {
this->getConstraintPtr()->Type = Tangent;
valid = true;
}
if (valid) {
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->FirstPos = (Sketcher::PointPos) FirstPos;
this->getConstraintPtr()->Second = SecondIndex;
this->getConstraintPtr()->SecondPos = (Sketcher::PointPos) SecondPos;
return 0;
}
}
// ConstraintType, GeoIndex1, PosIndex1, GeoIndex2, Value
else if (PyFloat_Check(index_or_value)) {
Value = PyFloat_AsDouble(index_or_value);
if (strcmp("Distance",ConstraintType) == 0 ) {
this->getConstraintPtr()->Type = Distance;
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->FirstPos = (Sketcher::PointPos) FirstPos;
this->getConstraintPtr()->Second = SecondIndex;
this->getConstraintPtr()->Value = Value;
return 0;
}
}
}
PyErr_Clear();
if (PyArg_ParseTuple(args, "siiiiO", &ConstraintType, &FirstIndex, &FirstPos, &SecondIndex, &SecondPos, &index_or_value)) {
// ConstraintType, GeoIndex1, PosIndex1, GeoIndex2, PosIndex2, GeoIndex3
if (PyInt_Check(index_or_value)) {
ThirdIndex = PyInt_AsLong(index_or_value);
if (strcmp("Symmetric",ConstraintType) == 0 ) {
this->getConstraintPtr()->Type = Symmetric;
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->FirstPos = (Sketcher::PointPos) FirstPos;
this->getConstraintPtr()->Second = SecondIndex;
this->getConstraintPtr()->SecondPos = (Sketcher::PointPos) SecondPos;
this->getConstraintPtr()->Third = ThirdIndex;
return 0;
}
}
// ConstraintType, GeoIndex1, PosIndex1, GeoIndex2, PosIndex2, Value
else if (PyFloat_Check(index_or_value)) {
Value = PyFloat_AsDouble(index_or_value);
bool valid=false;
if (strcmp("Distance",ConstraintType) == 0 ) {
this->getConstraintPtr()->Type = Distance;
valid = true;
}
else if (strcmp("DistanceX",ConstraintType) == 0) {
this->getConstraintPtr()->Type = DistanceX;
valid = true;
}
else if (strcmp("DistanceY",ConstraintType) == 0) {
this->getConstraintPtr()->Type = DistanceY;
valid = true;
}
else if (strcmp("Angle",ConstraintType) == 0 ) {
this->getConstraintPtr()->Type = Angle;
valid = true;
}
if (valid) {
this->getConstraintPtr()->First = FirstIndex;
this->getConstraintPtr()->FirstPos = (Sketcher::PointPos) FirstPos;
this->getConstraintPtr()->Second = SecondIndex;
this->getConstraintPtr()->SecondPos = (Sketcher::PointPos) SecondPos;
this->getConstraintPtr()->Value = Value;
return 0;
}
}
}
PyErr_SetString(PyExc_TypeError, "Constraint constructor accepts:\n"
"-- empty parameter list\n"
"-- Constraint type and index\n");
return -1;
}
// returns a string which represents the object e.g. when printed in python
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;
}
return result.str();
}
Py::Int ConstraintPy::getFirst(void) const
{
return Py::Int(this->getConstraintPtr()->First);
}
void ConstraintPy::setFirst(Py::Int arg)
{
this->getConstraintPtr()->First = arg;
}
Py::Int ConstraintPy::getSecond(void) const
{
return Py::Int(this->getConstraintPtr()->Second);
}
void ConstraintPy::setSecond(Py::Int arg)
{
this->getConstraintPtr()->Second = arg;
}
PyObject *ConstraintPy::getCustomAttributes(const char* /*attr*/) const
{
return 0;
}
int ConstraintPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
{
return 0;
}

View File

@@ -0,0 +1,108 @@
SUBDIRS=freegcs
lib_LTLIBRARIES=libSketcher.la Sketcher.la
BUILT_SOURCES=\
ConstraintPy.cpp \
SketchPy.cpp \
SketchObjectPy.cpp \
SketchObjectSFPy.cpp
libSketcher_la_BUILT=\
ConstraintPy.h \
SketchPy.h \
SketchObjectPy.h \
SketchObjectSFPy.h
libSketcher_la_SOURCES = \
AppSketcherPy.cpp \
Constraint.cpp \
Constraint.h \
ConstraintPyImp.cpp \
PropertyConstraintList.cpp \
PropertyConstraintList.h \
SketchObject.cpp \
SketchObject.h \
SketchObjectPyImp.cpp \
SketchObjectSF.cpp \
SketchObjectSF.h \
SketchObjectSFPyImp.cpp \
Sketch.cpp \
Sketch.h \
SketchPyImp.cpp \
PreCompiled.cpp \
PreCompiled.h
# the library search path.
libSketcher_la_LDFLAGS = -L../../../Base -L../../../App -L../../../Mod/Part/App \
-L$(OCC_LIB) $(all_libraries) \
-version-info @LIB_CURRENT@:@LIB_REVISION@:@LIB_AGE@
libSketcher_la_CPPFLAGS = -DSketcherAppExport=
libSketcher_la_LIBADD = \
freegcs/libfreegcs.la \
@BOOST_REGEX_LIB@ @BOOST_SYSTEM_LIB@ \
-l@PYTHON_LIB@ \
-lxerces-c \
-lFreeCADBase \
-lFreeCADApp \
-lPart \
-lTKernel \
-lTKG2d \
-lTKG3d \
-lTKMath \
-lTKSTEP \
-lTKIGES \
-lTKSTL \
-lTKShHealing \
-lTKXSBase \
-lTKBool \
-lTKBO \
-lTKBRep \
-lTKTopAlgo \
-lTKGeomAlgo \
-lTKGeomBase \
-lTKOffset \
-lTKPrim \
-lTKHLR
%.cpp: %.xml $(top_srcdir)/src/Tools/generateTemplates/templateClassPyExport.py
$(PYTHON) $(top_srcdir)/src/Tools/generate.py --outputPath $(@D) $<
#--------------------------------------------------------------------------------------
# Loader of libSketcher
Sketcher_la_SOURCES=\
AppSketcher.cpp
# the library search path.
Sketcher_la_LDFLAGS = $(libSketcher_la_LDFLAGS) -module -avoid-version
Sketcher_la_CPPFLAGS = $(libSketcher_la_CPPFLAGS)
Sketcher_la_LIBADD = \
$(libSketcher_la_LIBADD) \
-lSketcher
Sketcher_la_DEPENDENCIES = libSketcher.la
#--------------------------------------------------------------------------------------
# set the include path found by configure
AM_CXXFLAGS = -I$(OCC_INC) -I$(top_srcdir)/src -I$(top_builddir)/src $(all_includes) \
-I$(EIGEN3_INC)
libdir = $(prefix)/Mod/Sketcher
datadir = $(prefix)/Mod/Sketcher
CLEANFILES = $(BUILT_SOURCES) $(libSketcher_la_BUILT)
EXTRA_DIST = \
$(data_DATA) \
CMakeLists.txt \
ConstraintPy.xml \
SketchPy.xml \
SketchObjectPy.xml \
SketchObjectSFPy.xml

View File

@@ -0,0 +1,24 @@
/***************************************************************************
* Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) *
* *
* 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"

View File

@@ -0,0 +1,60 @@
/***************************************************************************
* Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) *
* *
* 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 *
* *
***************************************************************************/
#ifndef __PRECOMPILED__
#define __PRECOMPILED__
#include <FCConfig.h>
// Exporting of App classes
#ifdef FC_OS_WIN32
# define SketcherExport __declspec(dllexport)
# define PartExport __declspec(dllimport)
# define MeshExport __declspec(dllimport)
#else // for Linux
# define SketcherExport
# define PartExport
# define MeshExport
#endif
#ifdef _PreComp_
// standard
#include <iostream>
#include <sstream>
#include <stdio.h>
#include <assert.h>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <bitset>
#include <Mod/Part/App/OpenCascadeAll.h>
#include <Python.h>
#elif defined(FC_OS_WIN32)
#include <windows.h>
#endif // _PreComp_
#endif

View File

@@ -0,0 +1,195 @@
/***************************************************************************
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2010 *
* *
* 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 <assert.h>
#endif
/// Here the FreeCAD includes sorted by Base,App,Gui......
#include <Base/Exception.h>
#include <Base/Reader.h>
#include <Base/Writer.h>
#include <Base/Console.h>
#include "PropertyConstraintList.h"
#include "ConstraintPy.h"
using namespace App;
using namespace Base;
using namespace std;
using namespace Sketcher;
//**************************************************************************
// PropertyConstraintList
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
TYPESYSTEM_SOURCE(Sketcher::PropertyConstraintList, App::PropertyLists);
//**************************************************************************
// Construction/Destruction
PropertyConstraintList::PropertyConstraintList()
{
}
PropertyConstraintList::~PropertyConstraintList()
{
for (std::vector<Constraint*>::iterator it = _lValueList.begin(); it != _lValueList.end(); ++it)
if (*it) delete *it;
}
void PropertyConstraintList::setSize(int newSize)
{
for (unsigned int i = newSize; i < _lValueList.size(); i++)
delete _lValueList[i];
_lValueList.resize(newSize);
}
int PropertyConstraintList::getSize(void) const
{
return static_cast<int>(_lValueList.size());
}
void PropertyConstraintList::setValue(const Constraint* lValue)
{
if (lValue) {
aboutToSetValue();
Constraint* newVal = lValue->clone();
for (unsigned int i = 0; i < _lValueList.size(); i++)
delete _lValueList[i];
_lValueList.resize(1);
_lValueList[0] = newVal;
hasSetValue();
}
}
void PropertyConstraintList::setValues(const std::vector<Constraint*>& lValue)
{
aboutToSetValue();
std::vector<Constraint*> oldVals(_lValueList);
_lValueList.resize(lValue.size());
// copy all objects
for (unsigned int i = 0; i < lValue.size(); i++)
_lValueList[i] = lValue[i]->clone();
for (unsigned int i = 0; i < oldVals.size(); i++)
delete oldVals[i];
hasSetValue();
}
PyObject *PropertyConstraintList::getPyObject(void)
{
PyObject* list = PyList_New(getSize());
for (int i = 0; i < getSize(); i++)
PyList_SetItem( list, i, _lValueList[i]->getPyObject());
return list;
}
void PropertyConstraintList::setPyObject(PyObject *value)
{
if (PyList_Check(value)) {
Py_ssize_t nSize = PyList_Size(value);
std::vector<Constraint*> values;
values.resize(nSize);
for (Py_ssize_t i=0; i < nSize; ++i) {
PyObject* item = PyList_GetItem(value, i);
if (!PyObject_TypeCheck(item, &(ConstraintPy::Type))) {
std::string error = std::string("types in list must be 'Constraint', not ");
error += item->ob_type->tp_name;
throw Py::TypeError(error);
}
values[i] = static_cast<ConstraintPy*>(item)->getConstraintPtr();
}
setValues(values);
}
else if (PyObject_TypeCheck(value, &(ConstraintPy::Type))) {
ConstraintPy *pcObject = static_cast<ConstraintPy*>(value);
setValue(pcObject->getConstraintPtr());
}
else {
std::string error = std::string("type must be 'Constraint' or list of 'Constraint', not ");
error += value->ob_type->tp_name;
throw Py::TypeError(error);
}
}
void PropertyConstraintList::Save(Writer &writer) const
{
writer.Stream() << writer.ind() << "<ConstraintList count=\"" << getSize() <<"\">" << endl;
writer.incInd();
for (int i = 0; i < getSize(); i++)
_lValueList[i]->Save(writer);
writer.decInd();
writer.Stream() << writer.ind() << "</ConstraintList>" << endl ;
}
void PropertyConstraintList::Restore(Base::XMLReader &reader)
{
// read my element
reader.readElement("ConstraintList");
// get the value of my attribute
int count = reader.getAttributeAsInteger("count");
std::vector<Constraint*> values;
values.reserve(count);
for (int i = 0; i < count; i++) {
Constraint *newC = new Constraint();
newC->Restore(reader);
values.push_back(newC);
}
reader.readEndElement("ConstraintList");
// assignment
setValues(values);
}
Property *PropertyConstraintList::Copy(void) const
{
PropertyConstraintList *p = new PropertyConstraintList();
p->setValues(_lValueList);
return p;
}
void PropertyConstraintList::Paste(const Property &from)
{
const PropertyConstraintList& FromList = dynamic_cast<const PropertyConstraintList&>(from);
setValues(FromList._lValueList);
}
unsigned int PropertyConstraintList::getMemSize(void) const
{
int size = sizeof(PropertyConstraintList);
for (int i = 0; i < getSize(); i++)
size += _lValueList[i]->getMemSize();
return size;
}

View File

@@ -0,0 +1,95 @@
/***************************************************************************
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2010 *
* *
* 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 *
* *
***************************************************************************/
#ifndef APP_PropertyConstraintList_H
#define APP_PropertyConstraintList_H
// Std. configurations
#include <vector>
#include <string>
#include <App/Property.h>
#include "Constraint.h"
namespace Base {
class Writer;
}
namespace Sketcher
{
class Constraint;
class SketcherExport PropertyConstraintList: public App::PropertyLists
{
TYPESYSTEM_HEADER();
public:
/**
* A constructor.
* A more elaborate description of the constructor.
*/
PropertyConstraintList();
/**
* A destructor.
* A more elaborate description of the destructor.
*/
virtual ~PropertyConstraintList();
virtual void setSize(int newSize);
virtual int getSize(void) const;
/** Sets the property
*/
void setValue(const Constraint*);
void setValues(const std::vector<Constraint*>&);
/// index operator
const Constraint *operator[] (const int idx) const {
return _lValueList[idx];
}
const std::vector<Constraint*> &getValues(void) const {
return _lValueList;
}
virtual PyObject *getPyObject(void);
virtual void setPyObject(PyObject *);
virtual void Save(Base::Writer &writer) const;
virtual void Restore(Base::XMLReader &reader);
virtual Property *Copy(void) const;
virtual void Paste(const App::Property &from);
virtual unsigned int getMemSize(void) const;
private:
std::vector<Constraint*> _lValueList;
};
} // namespace Sketcher
#endif // APP_PropertyConstraintList_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,222 @@
/***************************************************************************
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2010 *
* *
* 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 *
* *
***************************************************************************/
#ifndef SKETCHER_SKETCH_H
#define SKETCHER_SKETCH_H
#include <App/PropertyStandard.h>
#include <App/PropertyFile.h>
#include <Mod/Part/App/Geometry.h>
#include <Mod/Part/App/TopoShape.h>
#include "Constraint.h"
#include "freegcs/GCS.h"
#include <Base/Persistence.h>
namespace Sketcher
{
class SketcherExport Sketch :public Base::Persistence
{
TYPESYSTEM_HEADER();
public:
Sketch();
~Sketch();
// from base class
virtual unsigned int getMemSize(void) const;
virtual void Save(Base::Writer &/*writer*/) const;
virtual void Restore(Base::XMLReader &/*reader*/);
/// solve the actual set up sketch
int solve(void);
/// delete all geometry and constraints, leave an empty sketch
void clear(void);
/// set the sketch up with geoms and constraints
int setUpSketch(const std::vector<Part::Geometry *> &GeoList,const std::vector<Constraint *> &ConstraintList,
bool withDiagnose=true);
/// return the actual geometry of the sketch a TopoShape
Part::TopoShape toShape(void) const;
/// add unspecified geometry
int addGeometry(const Part::Geometry *geo);
/// add unspecified geometry
void addGeometry(const std::vector<Part::Geometry *> &geo);
/// returns the actual geometry
std::vector<Part::Geometry *> getGeometry(bool withConstrucionElements = true) const;
/// get the geometry as python objects
Py::Tuple getPyGeometry(void) const;
/// set a geometric element to a construction element
void setConstruction(int geoIndex,bool isConstruction=true);
bool getConstruction(int geoIndex) const;
/// retrieves the index of a point
int getPointId(int geoId, PointPos pos) const;
/// retrieves a point
Base::Vector3d getPoint(int geoId, PointPos pos);
/** returns the degree of freedom of a sketch and calculates a list of
* conflicting constraints
*
* 0 degrees of freedom correspond to a fully constrained sketch
* -1 degrees of freedom correspond to an over-constrained sketch
* positive degrees of freedom correspond to an under-constrained sketch
*
* an over-constrained sketch will always contain conflicting constraints
* a fully constrained or under-constrained sketch may contain conflicting
* constraints or may not
*/
int diagnose(void);
bool hasConflicts(void) const { return (Conflicting.size() > 0); };
const std::vector<int> &getConflicting(void) const { return Conflicting; };
/** set the datum of a distance or angle constraint to a certain value and solve
* This can cause the solving to fail!
*/
int setDatum(int constrId, double value);
/** initializes a point (or curve) drag by setting the current
* sketch status as a reference
*/
int initMove(int geoIndex, PointPos pos);
/** move this point (or curve) to a new location and solve.
* This will introduce some additional weak constraints expressing
* a condition for satisfying the new point location!
* The relative flag permits moving relatively to the current position
*/
int movePoint(int geoIndex, PointPos pos, Base::Vector3d toPoint, bool relative=false);
/// add dedicated geometry
//@{
/// add a point
int addPoint(const Base::Vector3d &point);
/// add an infinite line
int addLine(const Part::GeomLineSegment &line);
/// add a line segment
int addLineSegment(const Part::GeomLineSegment &lineSegment);
/// add a arc (circle segment)
int addArc(const Part::GeomArcOfCircle &circleSegment);
/// add a circle
int addCircle(const Part::GeomCircle &circle);
/// add a ellipse
int addEllipse(const Part::GeomEllipse &ellipse);
//@}
/// constraints
//@{
/// add all constraints in the list
int addConstraints(const std::vector<Constraint *> &ConstraintList);
/// add one constraint to the sketch
int addConstraint(const Constraint *constraint);
/// add a fixed coordinate constraint to a point
int addCoordinateXConstraint(int geoIndex, PointPos pos, double value);
int addCoordinateYConstraint(int geoIndex, PointPos pos, double value);
/// add a horizontal distance constraint to two points or line ends
int addDistanceXConstraint(int geoId, double value);
int addDistanceXConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double value);
/// add a vertical distance constraint to two points or line ends
int addDistanceYConstraint(int geoId, double value);
int addDistanceYConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double value);
/// add a horizontal constraint to a geometry
int addHorizontalConstraint(int geoIndex);
int addHorizontalConstraint(int geoIndex1, PointPos pos1, int geoIndex2, PointPos pos2);
/// add a vertical constraint to a geometry
int addVerticalConstraint(int geoIndex);
int addVerticalConstraint(int geoIndex1, PointPos pos1, int geoIndex2, PointPos pos2);
/// add a coincident constraint to two points of two geometries
int addPointCoincidentConstraint(int geoIndex1, PointPos pos1, int geoIndex2, PointPos pos2);
/// add a length or distance constraint
int addDistanceConstraint(int geoIndex1, double value);
int addDistanceConstraint(int geoIndex1, int geoIndex2, double value);
int addDistanceConstraint(int geoIndex1, PointPos pos1, int geoIndex2, double value);
int addDistanceConstraint(int geoIndex1, PointPos pos1, int geoIndex2, PointPos pos2, double value);
/// add a parallel constraint between two lines
int addParallelConstraint(int geoIndex1, int geoIndex2);
/// add a perpendicular constraint between two lines
int addPerpendicularConstraint(int geoIndex1, int geoIndex2);
/// add a tangency constraint between two geometries
int addTangentConstraint(int geoIndex1, int geoIndex2);
int addTangentConstraint(int geoIndex1, PointPos pos1, int geoIndex2);
int addTangentConstraint(int geoIndex1, PointPos pos1, int geoIndex2, PointPos pos2);
/// add a radius constraint on a circle or an arc
int addRadiusConstraint(int geoIndex, double value);
/// add an angle constraint on a line or between two lines
int addAngleConstraint(int geoIndex, double value);
int addAngleConstraint(int geoIndex1, int geoIndex2, double value);
int addAngleConstraint(int geoIndex1, PointPos pos1, int geoIndex2, PointPos pos2, double value);
/// add an equal length or radius constraints between two lines or between circles and arcs
int addEqualConstraint(int geoIndex1, int geoIndex2);
/// add a point on line constraint
int addPointOnObjectConstraint(int geoId1, PointPos pos1, int geoId2);
/// add a symmetric constraint between two points with respect to a line
int addSymmetricConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, int geoId3);
//@}
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
};
float SolveTime;
protected:
/// container element to store and work with the geometric elements of this sketch
struct GeoDef {
GeoDef() : geo(0),type(None),construction(false),index(-1),
startPointId(-1),midPointId(-1),endPointId(-1) {}
Part::Geometry * geo; // pointer to the geometry
GeoType type; // type of the geometry
bool construction; // defines if this element is a construction element
int index; // index in the corresponding storage vector (Lines, Arcs, Circles, ...)
int startPointId; // index in Points of the start point of this geometry
int midPointId; // index in Points of the start point of this geometry
int endPointId; // index in Points of the end point of this geometry
};
std::vector<GeoDef> Geoms;
GCS::System GCSsys;
int ConstraintsCounter;
std::vector<int> Conflicting;
// solving parameters
std::vector<double*> Parameters; // with memory allocation
std::vector<double*> FixParameters; // with memory allocation
std::vector<double> MoveParameters, InitParameters;
std::vector<GCS::Point> Points;
std::vector<GCS::Line> Lines;
std::vector<GCS::Arc> Arcs;
std::vector<GCS::Circle> Circles;
bool isInitMove;
};
} //namespace Part
#endif // SKETCHER_SKETCH_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,134 @@
/***************************************************************************
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2008 *
* *
* 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 *
* *
***************************************************************************/
#ifndef SKETCHER_SKETCHOBJECT_H
#define SKETCHER_SKETCHOBJECT_H
#include <App/PropertyStandard.h>
#include <App/PropertyFile.h>
#include <App/FeaturePython.h>
#include <Mod/Part/App/Part2DObject.h>
#include <Mod/Part/App/PropertyGeometryList.h>
#include <Mod/Sketcher/App/PropertyConstraintList.h>
namespace Sketcher
{
class SketcherExport SketchObject : public Part::Part2DObject
{
PROPERTY_HEADER(Sketcher::SketchObject);
public:
SketchObject();
/// Property
Part ::PropertyGeometryList Geometry;
Sketcher::PropertyConstraintList Constraints;
App ::PropertyLinkSubList ExternalConstraints;
/** @name methods overide Feature */
//@{
/// recalculate the Feature
App::DocumentObjectExecReturn *execute(void);
/// returns the type name of the ViewProvider
const char* getViewProviderName(void) const {
return "SketcherGui::ViewProviderSketch";
}
//@}
/// add unspecified geometry
int addGeometry(const Part::Geometry *geo);
/// add unspecified geometry
int addGeometry(const std::vector<Part::Geometry *> &geoList);
/// delete geometry
int delGeometry(int GeoNbr);
/// add all constraints in the list
int addConstraints(const std::vector<Constraint *> &ConstraintList);
/// add constraint
int addConstraint(const Constraint *constraint);
/// delete constraint
int delConstraint(int ConstrId);
int delConstraintOnPoint(int GeoId, PointPos PosId, bool onlyCoincident=true);
int delConstraintOnPoint(int VertexId, bool onlyCoincident=true);
/// add an external geometry reference
int addExternal(App::DocumentObject *Obj, const char* SubName);
/// returns a list of projected external geoms
std::vector<Part::Geometry *> getExternalGeometry(void);
/// delete external
int delExternal(int ConstrId);
/// returns non zero if the sketch contains conflicting constraints
int hasConflicts(void) const;
/// set the datum of a Distance or Angle constraint and solve
int setDatum(int ConstrId, double Datum);
/// move this point to a new location and solve
int movePoint(int geoIndex1, PointPos Pos1, const Base::Vector3d& toPoint, bool relative=false);
/// retrieves the coordinates of a point
Base::Vector3d getPoint(int geoIndex1, PointPos Pos1);
/// toggle geometry to draft line
int toggleConstruction(int GeoNbr);
/// create a fillet
int fillet(int geoId, PointPos pos, double radius, bool trim=true);
int fillet(int geoId1, int geoId2,
const Base::Vector3d& refPnt1, const Base::Vector3d& refPnt2,
double radius, bool trim=true);
/// trim a curve
int trim(int geoId, const Base::Vector3d& point);
/// retrieves for a Vertex number the corresponding GeoId and PosId
void getGeoVertexIndex(int VertexId, int &GeoId, PointPos &PosId);
int getHighestVertexIndex(void) { return VertexId2GeoId.size() - 1; }
int getHighestCurveIndex(void) { return Geometry.getSize() - 1; }
void rebuildVertexIndex(void);
/// retrieves for a Vertex number a list with all coincident points
void getCoincidentPoints(int GeoId, PointPos PosId, std::vector<int> &GeoIdList,
std::vector<PointPos> &PosIdList);
void getCoincidentPoints(int VertexId, std::vector<int> &GeoIdList, std::vector<PointPos> &PosIdList);
/// generates a warning message about constraint conflicts and appends it to the given message
static void appendConflictMsg(const std::vector<int> &conflicting, std::string &msg);
// from base class
virtual PyObject *getPyObject(void);
virtual unsigned int getMemSize(void) const;
virtual void Save(Base::Writer &/*writer*/) const;
virtual void Restore(Base::XMLReader &/*reader*/);
private:
std::vector<int> VertexId2GeoId;
std::vector<PointPos> VertexId2PosId;
};
typedef App::FeaturePythonT<SketchObject> SketchObjectPython;
} //namespace Sketcher
#endif // SKETCHER_SKETCHOBJECT_H

View File

@@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="Part2DObjectPy"
Name="SketchObjectPy"
Twin="SketchObject"
TwinPointer="SketchObject"
Include="Mod/Sketcher/App/SketchObject.h"
Namespace="Sketcher"
FatherInclude="Mod/Part/App/Part2DObjectPy.h"
FatherNamespace="Part">
<Documentation>
<Author Licence="LGPL" Name="Juergen Riegel" EMail="FreeCAD@juergen-riegel.net" />
<UserDocu>With this objects you can handle sketches</UserDocu>
</Documentation>
<Methode Name="solve">
<Documentation>
<UserDocu>solve the actual set of geometry and constraints</UserDocu>
</Documentation>
</Methode>
<Methode Name="addGeometry">
<Documentation>
<UserDocu>add a geometric object to the sketch</UserDocu>
</Documentation>
</Methode>
<Methode Name="delGeometry">
<Documentation>
<UserDocu>delete a geometric object from the sketch</UserDocu>
</Documentation>
</Methode>
<Methode Name="toggleConstruction">
<Documentation>
<UserDocu>switch a geometry to a construcion line</UserDocu>
</Documentation>
</Methode>
<Methode Name="addConstraint">
<Documentation>
<UserDocu>add a constraint to the sketch</UserDocu>
</Documentation>
</Methode>
<Methode Name="delConstraint">
<Documentation>
<UserDocu>delete a constraint from the sketch</UserDocu>
</Documentation>
</Methode>
<Methode Name="addExternal">
<Documentation>
<UserDocu>add a link to a external geometry to use them in a constraint</UserDocu>
</Documentation>
</Methode>
<Methode Name="delExternal">
<Documentation>
<UserDocu>delete a external geometry link from the sketch</UserDocu>
</Documentation>
</Methode>
<Methode Name="delConstraintOnPoint">
<Documentation>
<UserDocu>delete coincident constraints associated with a sketch point</UserDocu>
</Documentation>
</Methode>
<Methode Name="setDatum">
<Documentation>
<UserDocu>set the Datum of a Distance or Angle constraint</UserDocu>
</Documentation>
</Methode>
<Methode Name="movePoint">
<Documentation>
<UserDocu>
movePoint(GeoIndex,PointPos,Vector,[relative]) - move a given point (or curve)
to another location.
It moves the specified point (or curve) to the given location by adding some
temporary weak constraints and solve the sketch.
This method is mostly used to allow the user to drag some portions of the sketch
in real time by e.g. the mouse and it works only for underconstrained portions of
the sketch.
The argument 'relative', if present, states if the new location is given
relatively to the current one.
</UserDocu>
</Documentation>
</Methode>
<Methode Name="fillet">
<Documentation>
<UserDocu>create fillet between two edges or at a point</UserDocu>
</Documentation>
</Methode>
<Methode Name="trim">
<Documentation>
<UserDocu>trim a curve with a given id at a given reference point</UserDocu>
</Documentation>
</Methode>
<Attribute Name="ConstraintCount" ReadOnly="true">
<Documentation>
<UserDocu>Number of Constraints in this sketch</UserDocu>
</Documentation>
<Parameter Name="ConstraintCount" Type="Int"/>
</Attribute>
<Attribute Name="GeometryCount" ReadOnly="true">
<Documentation>
<UserDocu>Number of geometric objects in this sketch</UserDocu>
</Documentation>
<Parameter Name="GeometryCount" Type="Int"/>
</Attribute>
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,324 @@
/***************************************************************************
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2010 *
* *
* 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 <sstream>
#endif
#include "Mod/Sketcher/App/SketchObject.h"
#include <Mod/Part/App/LinePy.h>
#include <Mod/Part/App/Geometry.h>
#include <Base/VectorPy.h>
#include <App/Document.h>
// inclusion of the generated files (generated out of SketchObjectSFPy.xml)
#include "SketchObjectPy.h"
#include "SketchObjectPy.cpp"
// other python types
#include "ConstraintPy.h"
using namespace Sketcher;
// returns a string which represents the object e.g. when printed in python
std::string SketchObjectPy::representation(void) const
{
return "<Sketcher::SketchObject>";
}
PyObject* SketchObjectPy::solve(PyObject *args)
{
PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented");
return 0;
}
PyObject* SketchObjectPy::addGeometry(PyObject *args)
{
PyObject *pcObj;
if (!PyArg_ParseTuple(args, "O", &pcObj))
return 0;
if (PyObject_TypeCheck(pcObj, &(Part::GeometryPy::Type))) {
Part::Geometry *geo = static_cast<Part::GeometryPy*>(pcObj)->getGeometryPtr();
return Py::new_reference_to(Py::Int(this->getSketchObjectPtr()->addGeometry(geo)));
}
Py_Return;
}
PyObject* SketchObjectPy::delGeometry(PyObject *args)
{
int Index;
if (!PyArg_ParseTuple(args, "i", &Index))
return 0;
if (this->getSketchObjectPtr()->delGeometry(Index)) {
std::stringstream str;
str << "Not able to delete a geometry with the given index: " << Index;
PyErr_SetString(PyExc_ValueError, str.str().c_str());
return 0;
}
Py_Return;
}
PyObject* SketchObjectPy::toggleConstruction(PyObject *args)
{
int Index;
if (!PyArg_ParseTuple(args, "i", &Index))
return 0;
if (this->getSketchObjectPtr()->toggleConstruction(Index)) {
std::stringstream str;
str << "Not able to toggle a geometry with the given index: " << Index;
PyErr_SetString(PyExc_ValueError, str.str().c_str());
return 0;
}
Py_Return;
}
PyObject* SketchObjectPy::addConstraint(PyObject *args)
{
PyObject *pcObj;
if (!PyArg_ParseTuple(args, "O", &pcObj))
return 0;
if (PyObject_TypeCheck(pcObj, &(Sketcher::ConstraintPy::Type))) {
Sketcher::Constraint *constr = static_cast<Sketcher::ConstraintPy*>(pcObj)->getConstraintPtr();
return Py::new_reference_to(Py::Int(this->getSketchObjectPtr()->addConstraint(constr)));
}
Py_Return;
}
PyObject* SketchObjectPy::delConstraint(PyObject *args)
{
int Index;
if (!PyArg_ParseTuple(args, "i", &Index))
return 0;
if (this->getSketchObjectPtr()->delConstraint(Index)) {
std::stringstream str;
str << "Not able to delete a constraint with the given index: " << Index;
PyErr_SetString(PyExc_ValueError, str.str().c_str());
return 0;
}
Py_Return;
}
PyObject* SketchObjectPy::addExternal(PyObject *args)
{
char *ObjectName;
char *SubName;
if (!PyArg_ParseTuple(args, "ss:Give an object and subelement name", &ObjectName,&SubName))
return 0;
// get the target object for the external link
App::DocumentObject * Obj = this->getSketchObjectPtr()->getDocument()->getObject(ObjectName);
if (!Obj) {
std::stringstream str;
str << ObjectName << "does not exist in the document";
PyErr_SetString(PyExc_ValueError, str.str().c_str());
return 0;
}
// check if its belong to the sketch support
if (this->getSketchObjectPtr()->Support.getValue() != Obj) {
std::stringstream str;
str << ObjectName << "is not supported by this sketch";
PyErr_SetString(PyExc_ValueError, str.str().c_str());
return 0;
}
// add the external
if (this->getSketchObjectPtr()->addExternal(Obj,SubName)) {
std::stringstream str;
str << "Not able to add external shape element";
PyErr_SetString(PyExc_ValueError, str.str().c_str());
return 0;
}
Py_Return;
}
PyObject* SketchObjectPy::delExternal(PyObject *args)
{
PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented");
return 0;
}
PyObject* SketchObjectPy::delConstraintOnPoint(PyObject *args)
{
int Index;
if (!PyArg_ParseTuple(args, "i", &Index))
return 0;
if (this->getSketchObjectPtr()->delConstraintOnPoint(Index)) {
std::stringstream str;
str << "Not able to delete a constraint on point with the given index: " << Index;
PyErr_SetString(PyExc_ValueError, str.str().c_str());
return 0;
}
Py_Return;
}
PyObject* SketchObjectPy::setDatum(PyObject *args)
{
double Datum;
int Index;
if (!PyArg_ParseTuple(args, "id", &Index, &Datum))
return 0;
int err=this->getSketchObjectPtr()->setDatum(Index, Datum);
if (err) {
std::stringstream str;
if (err == -1)
str << "Invalid constraint index: " << Index;
else if (err == -3)
str << "Cannot set the datum because the sketch contains conflicting constraints";
else if (err == -2)
str << "Datum " << Datum << " for the constraint with index " << Index << " is invalid";
else
str << "Unexpected problem at setting datum " << Datum << " for the constraint with index " << Index;
PyErr_SetString(PyExc_ValueError, str.str().c_str());
return 0;
}
Py_Return;
}
PyObject* SketchObjectPy::movePoint(PyObject *args)
{
PyObject *pcObj;
int GeoId, PointType;
int relative=0;
if (!PyArg_ParseTuple(args, "iiO!|i", &GeoId, &PointType, &(Base::VectorPy::Type), &pcObj, &relative))
return 0;
Base::Vector3d v1 = static_cast<Base::VectorPy*>(pcObj)->value();
if (this->getSketchObjectPtr()->movePoint(GeoId,(Sketcher::PointPos)PointType,v1,(relative>0))) {
std::stringstream str;
str << "Not able to move point with the id and type: (" << GeoId << ", " << PointType << ")";
PyErr_SetString(PyExc_ValueError, str.str().c_str());
return 0;
}
Py_Return;
}
PyObject* SketchObjectPy::fillet(PyObject *args)
{
PyObject *pcObj1, *pcObj2;
int geoId1, geoId2, posId1, trim=1;
double radius;
// Two Lines, radius
if (PyArg_ParseTuple(args, "iiO!O!d|i", &geoId1, &geoId2, &(Base::VectorPy::Type), &pcObj1, &(Base::VectorPy::Type), &pcObj2, &radius, &trim)) {
Base::Vector3d v1 = static_cast<Base::VectorPy*>(pcObj1)->value();
Base::Vector3d v2 = static_cast<Base::VectorPy*>(pcObj2)->value();
if (this->getSketchObjectPtr()->fillet(geoId1, geoId2, v1, v2, radius, trim?true:false)) {
std::stringstream str;
str << "Not able to fillet lineSegments with ids : (" << geoId1 << ", " << geoId2 << ") and points (" << v1.x << ", " << v1.y << ", " << v1.z << ") & "
<< "(" << v2.x << ", " << v2.y << ", " << v2.z << ")";
PyErr_SetString(PyExc_ValueError, str.str().c_str());
return 0;
}
// Point, radius
}
PyErr_Clear();
if (PyArg_ParseTuple(args, "iid|i", &geoId1, &posId1, &radius, &trim)) {
if (this->getSketchObjectPtr()->fillet(geoId1, (Sketcher::PointPos) posId1, radius, trim?true:false)) {
std::stringstream str;
str << "Not able to fillet point with ( geoId: " << geoId1 << ", PointPos: " << posId1 << " )";
PyErr_SetString(PyExc_ValueError, str.str().c_str());
return 0;
}
}
Py_Return;
}
PyObject* SketchObjectPy::trim(PyObject *args)
{
PyObject *pcObj;
int GeoId;
if (!PyArg_ParseTuple(args, "iO!", &GeoId, &(Base::VectorPy::Type), &pcObj))
return 0;
Base::Vector3d v1 = static_cast<Base::VectorPy*>(pcObj)->value();
if (this->getSketchObjectPtr()->trim(GeoId,v1)) {
std::stringstream str;
str << "Not able to trim curve with the given index: " << GeoId;
PyErr_SetString(PyExc_ValueError, str.str().c_str());
return 0;
}
Py_Return;
}
Py::Int SketchObjectPy::getConstraintCount(void) const
{
return Py::Int(this->getSketchObjectPtr()->Constraints.getSize());
}
Py::Int SketchObjectPy::getGeometryCount(void) const
{
return Py::Int(this->getSketchObjectPtr()->Geometry.getSize());
}
PyObject *SketchObjectPy::getCustomAttributes(const char* /*attr*/) const
{
return 0;
}
int SketchObjectPy::setCustomAttributes(const char* attr, PyObject* obj)
{
// search in PropertyList
App::Property *prop = getSketchObjectPtr()->getPropertyByName(attr);
if (prop) {
// Read-only attributes must not be set over its Python interface
short Type = getSketchObjectPtr()->getPropertyType(prop);
if (Type & App::Prop_ReadOnly) {
std::stringstream s;
s << "Object attribute '" << attr << "' is read-only";
throw Py::AttributeError(s.str());
}
prop->setPyObject(obj);
if (strcmp(attr,"Geometry") == 0)
getSketchObjectPtr()->rebuildVertexIndex();
return 1;
}
return 0;
}

View File

@@ -0,0 +1,58 @@
/***************************************************************************
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2008 *
* *
* 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_
#endif
#include "SketchObjectSF.h"
#include <Base/Console.h>
using namespace Sketcher;
PROPERTY_SOURCE(Sketcher::SketchObjectSF, Part::Part2DObject)
SketchObjectSF::SketchObjectSF()
{
ADD_PROPERTY_TYPE(SketchFlatFile,(0),"",(App::PropertyType)(App::Prop_None),
"SketchFlat file (*.skf) which defines this sketch");
}
short SketchObjectSF::mustExecute() const
{
if (SketchFlatFile.isTouched())
return 1;
return 0;
}
App::DocumentObjectExecReturn *SketchObjectSF::execute(void)
{
Base::Console().Warning("%s: This feature is deprecated and will not longer supported in future version of FreeCAD \n",this->getNameInDocument());
// do nothing
return App::DocumentObject::StdReturn;
}

View File

@@ -0,0 +1,67 @@
/***************************************************************************
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2008 *
* *
* 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 *
* *
***************************************************************************/
#ifndef SKETCH_SKETCHOBJECTSF_H
#define SKETCH_SKETCHOBJECTSF_H
#include <App/PropertyStandard.h>
#include <App/PropertyFile.h>
#include <Mod/Part/App/Part2DObject.h>
namespace Sketcher
{
class SketchObjectSF :public Part::Part2DObject
{
PROPERTY_HEADER(Sketcher::SketchObjectSF);
public:
SketchObjectSF();
/// Property
App::PropertyFileIncluded SketchFlatFile;
/** @name methods overide Feature */
//@{
/// recalculate the Feature
App::DocumentObjectExecReturn *execute(void);
short mustExecute() const;
/// Uses the standard ViewProvider
//const char* getViewProviderName(void) const {
// return "SketcherGui::ViewProviderSketchSF";
//}
//@}
bool save(const char* FileName);
bool load(const char* FileName);
};
} //namespace Part
#endif // SKETCH_SKETCHOBJECTSF_H

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="Part2DObjectPy"
Name="SketchObjectSFPy"
Twin="SketchObjectSF"
TwinPointer="SketchObjectSF"
Include="Mod/Sketcher/App/SketchObjectSF.h"
Namespace="Sketcher"
FatherInclude="Mod/Part/App/Part2DObjectPy.h"
FatherNamespace="Part">
<Documentation>
<Author Licence="LGPL" Name="Juergen Riegel" EMail="FreeCAD@juergen-riegel.net" />
<UserDocu>With this objects you can handle sketches</UserDocu>
</Documentation>
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,51 @@
/***************************************************************************
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2010 *
* *
* 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"
#include "Mod/Sketcher/App/SketchObjectSF.h"
// inclusion of the generated files (generated out of SketchObjectSFPy.xml)
#include "SketchObjectSFPy.h"
#include "SketchObjectSFPy.cpp"
using namespace Sketcher;
// returns a string which represents the object e.g. when printed in python
std::string SketchObjectSFPy::representation(void) const
{
return "<SketchObjectSF object>";
}
PyObject *SketchObjectSFPy::getCustomAttributes(const char* /*attr*/) const
{
return 0;
}
int SketchObjectSFPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
{
return 0;
}

View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="PersistencePy"
Name="SketchPy"
Twin="Sketch"
TwinPointer="Sketch"
Include="Mod/Sketcher/App/Sketch.h"
Namespace="Sketcher"
FatherInclude="Base/PersistencePy.h"
FatherNamespace="Base"
Constructor="true">
<Documentation>
<Author Licence="LGPL" Name="Juergen Riegel" EMail="FreeCAD@juergen-riegel.net" />
<UserDocu>With this objects you can handle constraint sketches</UserDocu>
</Documentation>
<Methode Name="solve">
<Documentation>
<UserDocu>solve the actuall set of geometry and constraints</UserDocu>
</Documentation>
</Methode>
<Methode Name="addGeometry">
<Documentation>
<UserDocu>add a geometric object to the sketch</UserDocu>
</Documentation>
</Methode>
<Methode Name="addConstraint">
<Documentation>
<UserDocu>add an constraint object to the sketch</UserDocu>
</Documentation>
</Methode>
<Methode Name="clear">
<Documentation>
<UserDocu>clear the sketch</UserDocu>
</Documentation>
</Methode>
<Methode Name="movePoint">
<Documentation>
<UserDocu>
movePoint(GeoIndex,PointPos,Vector,[relative]) - move a given point (or curve)
to another location.
It moves the specified point (or curve) to the given location by adding some
temporary weak constraints and solve the sketch.
This method is mostly used to allow the user to drag some portions of the sketch
in real time by e.g. the mouse and it works only for underconstrained portions of
the sketch.
The argument 'relative', if present, states if the new location is given
relatively to the current one.
</UserDocu>
</Documentation>
</Methode>
<Attribute Name="Constraint" ReadOnly="true">
<Documentation>
<UserDocu>0: exactly constraint, -1 under-constraint, 1 over-constraint</UserDocu>
</Documentation>
<Parameter Name="Constraint" Type="Int"/>
</Attribute>
<Attribute Name="Constraints" ReadOnly="true">
<Documentation>
<UserDocu>Tuple of all constrains in this sketch</UserDocu>
</Documentation>
<Parameter Name="Constraints" Type="Tuple"/>
</Attribute>
<Attribute Name="Geometries" ReadOnly="true">
<Documentation>
<UserDocu>Tuple of all geometric elements in this sketch</UserDocu>
</Documentation>
<Parameter Name="Geometries" Type="Tuple"/>
</Attribute>
<Attribute Name="Shape" ReadOnly="true">
<Documentation>
<UserDocu>Resulting shape from the sketch geometry</UserDocu>
</Documentation>
<Parameter Name="Shape" Type="Object"/>
</Attribute>
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,179 @@
/***************************************************************************
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2010 *
* *
* 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"
#include <Base/VectorPy.h>
#include <Mod/Part/App/Geometry.h>
#include <Mod/Part/App/GeometryCurvePy.h>
#include <Mod/Part/App/LinePy.h>
#include <Mod/Part/App/TopoShapePy.h>
#include "Sketch.h"
#include "Constraint.h"
#include "ConstraintPy.h"
// inclusion of the generated files (generated out of SketchPy.xml)
#include "SketchPy.h"
#include "SketchPy.cpp"
using namespace Sketcher;
using namespace Part;
// returns a string which represents the object e.g. when printed in python
std::string SketchPy::representation(void) const
{
return std::string("<Sketch object>");
}
PyObject *SketchPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
{
// create a new instance of SketchPy and the Twin object
return new SketchPy(new Sketch());
}
// constructor method
int SketchPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
{
return 0;
}
// +++ methodes implementer ++++++++++++++++++++++++++++++++++++++++++++++++
PyObject* SketchPy::solve(PyObject *args)
{
return Py::new_reference_to(Py::Int(getSketchPtr()->solve()));
}
PyObject* SketchPy::addGeometry(PyObject *args)
{
PyObject *pcObj;
if (!PyArg_ParseTuple(args, "O", &pcObj))
return 0;
if (PyObject_TypeCheck(pcObj, &(LinePy::Type))) {
GeomLineSegment *line = static_cast<LinePy*>(pcObj)->getGeomLineSegmentPtr();
return Py::new_reference_to(Py::Int(this->getSketchPtr()->addGeometry(line->clone())));
}
Py_Return;
}
PyObject* SketchPy::addConstraint(PyObject *args)
{
int ret = -1;
PyObject *pcObj;
if (!PyArg_ParseTuple(args, "O", &pcObj))
return 0;
if (PyList_Check(pcObj)) {
Py_ssize_t nSize = PyList_Size(pcObj);
std::vector<Constraint*> values;
values.resize(nSize);
for (Py_ssize_t i=0; i<nSize;++i) {
PyObject* item = PyList_GetItem(pcObj, i);
if (!PyObject_TypeCheck(item, &(ConstraintPy::Type))) {
std::string error = std::string("types in list must be 'Constraint', not ");
error += item->ob_type->tp_name;
throw Py::TypeError(error);
}
values[i] = static_cast<ConstraintPy*>(item)->getConstraintPtr();
}
ret = getSketchPtr()->addConstraints(values);
}
else if(PyObject_TypeCheck(pcObj, &(ConstraintPy::Type))) {
ConstraintPy *pcObject = static_cast<ConstraintPy*>(pcObj);
ret = getSketchPtr()->addConstraint(pcObject->getConstraintPtr());
}
else {
std::string error = std::string("type must be 'Constraint' or list of 'Constraint', not ");
error += pcObj->ob_type->tp_name;
throw Py::TypeError(error);
}
return Py::new_reference_to(Py::Int(ret));
}
PyObject* SketchPy::clear(PyObject *args)
{
int index;
if (!PyArg_ParseTuple(args, "i", &index))
return 0;
return Py::new_reference_to(Py::Int(getSketchPtr()->addVerticalConstraint(index)));
}
PyObject* SketchPy::movePoint(PyObject *args)
{
int index1,index2;
PyObject *pcObj;
int relative=0;
if (!PyArg_ParseTuple(args, "iiO!|i", &index1,&index2,&(Base::VectorPy::Type),&pcObj,&relative))
return 0;
Base::Vector3d* toPoint = static_cast<Base::VectorPy*>(pcObj)->getVectorPtr();
return Py::new_reference_to(Py::Int(getSketchPtr()->movePoint(index1,(Sketcher::PointPos)index2,*toPoint,(relative>0))));
}
// +++ attributes implementer ++++++++++++++++++++++++++++++++++++++++++++++++
Py::Int SketchPy::getConstraint(void) const
{
//return Py::Int();
throw Py::AttributeError("Not yet implemented");
}
Py::Tuple SketchPy::getConstraints(void) const
{
//return Py::Tuple();
throw Py::AttributeError("Not yet implemented");
}
Py::Tuple SketchPy::getGeometries(void) const
{
return getSketchPtr()->getPyGeometry();
}
Py::Object SketchPy::getShape(void) const
{
return Py::Object(new TopoShapePy(new TopoShape(getSketchPtr()->toShape())));
}
// +++ custom attributes implementer ++++++++++++++++++++++++++++++++++++++++
PyObject *SketchPy::getCustomAttributes(const char* /*attr*/) const
{
return 0;
}
int SketchPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
{
return 0;
}

View File

@@ -0,0 +1,774 @@
/***************************************************************************
* Copyright (c) Konstantinos Poulios (logari81@gmail.com) 2011 *
* *
* 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 <cmath>
#include "Constraints.h"
namespace GCS
{
///////////////////////////////////////
// Constraints
///////////////////////////////////////
Constraint::Constraint()
: origpvec(0), pvec(0), scale(1.), tag(0)
{
}
void Constraint::redirectParams(MAP_pD_pD redirectionmap)
{
int i=0;
for (VEC_pD::iterator param=origpvec.begin();
param != origpvec.end(); ++param, i++) {
MAP_pD_pD::const_iterator it = redirectionmap.find(*param);
if (it != redirectionmap.end())
pvec[i] = it->second;
}
}
void Constraint::revertParams()
{
pvec = origpvec;
}
ConstraintType Constraint::getTypeId()
{
return None;
}
void Constraint::rescale(double coef)
{
scale = coef * 1.;
}
double Constraint::error()
{
return 0.;
}
double Constraint::grad(double *param)
{
return 0.;
}
double Constraint::maxStep(MAP_pD_D &dir, double lim)
{
return lim;
}
// Equal
ConstraintEqual::ConstraintEqual(double *p1, double *p2)
{
pvec.push_back(p1);
pvec.push_back(p2);
origpvec = pvec;
rescale();
}
ConstraintType ConstraintEqual::getTypeId()
{
return Equal;
}
void ConstraintEqual::rescale(double coef)
{
scale = coef * 1.;
}
double ConstraintEqual::error()
{
return scale * (*param1() - *param2());
}
double ConstraintEqual::grad(double *param)
{
double deriv=0.;
if (param == param1()) deriv += 1;
if (param == param2()) deriv += -1;
return scale * deriv;
}
// Difference
ConstraintDifference::ConstraintDifference(double *p1, double *p2, double *d)
{
pvec.push_back(p1);
pvec.push_back(p2);
pvec.push_back(d);
origpvec = pvec;
rescale();
}
ConstraintType ConstraintDifference::getTypeId()
{
return Difference;
}
void ConstraintDifference::rescale(double coef)
{
scale = coef * 1.;
}
double ConstraintDifference::error()
{
return scale * (*param2() - *param1() - *difference());
}
double ConstraintDifference::grad(double *param)
{
double deriv=0.;
if (param == param1()) deriv += -1;
if (param == param2()) deriv += 1;
if (param == difference()) deriv += -1;
return scale * deriv;
}
// P2PDistance
ConstraintP2PDistance::ConstraintP2PDistance(Point &p1, Point &p2, double *d)
{
pvec.push_back(p1.x);
pvec.push_back(p1.y);
pvec.push_back(p2.x);
pvec.push_back(p2.y);
pvec.push_back(d);
origpvec = pvec;
rescale();
}
ConstraintType ConstraintP2PDistance::getTypeId()
{
return P2PDistance;
}
void ConstraintP2PDistance::rescale(double coef)
{
scale = coef * 1.;
}
double ConstraintP2PDistance::error()
{
double dx = (*p1x() - *p2x());
double dy = (*p1y() - *p2y());
double d = sqrt(dx*dx + dy*dy);
double dist = *distance();
return scale * (d - dist);
}
double ConstraintP2PDistance::grad(double *param)
{
double deriv=0.;
if (param == p1x() || param == p1y() ||
param == p2x() || param == p2y()) {
double dx = (*p1x() - *p2x());
double dy = (*p1y() - *p2y());
double d = sqrt(dx*dx + dy*dy);
if (param == p1x()) deriv += dx/d;
if (param == p1y()) deriv += dy/d;
if (param == p2x()) deriv += -dx/d;
if (param == p2y()) deriv += -dy/d;
}
if (param == distance()) deriv += -1.;
return scale * deriv;
}
double ConstraintP2PDistance::maxStep(MAP_pD_D &dir, double lim)
{
MAP_pD_D::iterator it;
// distance() >= 0
it = dir.find(distance());
if (it != dir.end()) {
if (it->second < 0.)
lim = std::min(lim, -(*distance()) / it->second);
}
// restrict actual distance change
double ddx=0.,ddy=0.;
it = dir.find(p1x());
if (it != dir.end()) ddx += it->second;
it = dir.find(p1y());
if (it != dir.end()) ddy += it->second;
it = dir.find(p2x());
if (it != dir.end()) ddx -= it->second;
it = dir.find(p2y());
if (it != dir.end()) ddy -= it->second;
double dd = sqrt(ddx*ddx+ddy*ddy);
double dist = *distance();
if (dd > dist) {
double dx = (*p1x() - *p2x());
double dy = (*p1y() - *p2y());
double d = sqrt(dx*dx + dy*dy);
if (dd > d)
lim = std::min(lim, std::max(d,dist)/dd);
}
return lim;
}
// P2PAngle
ConstraintP2PAngle::ConstraintP2PAngle(Point &p1, Point &p2, double *a, double da_)
: da(da_)
{
pvec.push_back(p1.x);
pvec.push_back(p1.y);
pvec.push_back(p2.x);
pvec.push_back(p2.y);
pvec.push_back(a);
origpvec = pvec;
rescale();
}
ConstraintType ConstraintP2PAngle::getTypeId()
{
return P2PAngle;
}
void ConstraintP2PAngle::rescale(double coef)
{
scale = coef * 1.;
}
double ConstraintP2PAngle::error()
{
double dx = (*p2x() - *p1x());
double dy = (*p2y() - *p1y());
double a = *angle() + da;
double ca = cos(a);
double sa = sin(a);
double x = dx*ca + dy*sa;
double y = -dx*sa + dy*ca;
return scale * atan2(y,x);
}
double ConstraintP2PAngle::grad(double *param)
{
double deriv=0.;
if (param == p1x() || param == p1y() ||
param == p2x() || param == p2y()) {
double dx = (*p2x() - *p1x());
double dy = (*p2y() - *p1y());
double a = *angle() + da;
double ca = cos(a);
double sa = sin(a);
double x = dx*ca + dy*sa;
double y = -dx*sa + dy*ca;
double r2 = dx*dx+dy*dy;
dx = -y/r2;
dy = x/r2;
if (param == p1x()) deriv += (-ca*dx + sa*dy);
if (param == p1y()) deriv += (-sa*dx - ca*dy);
if (param == p2x()) deriv += ( ca*dx - sa*dy);
if (param == p2y()) deriv += ( sa*dx + ca*dy);
}
if (param == angle()) deriv += -1;
return scale * deriv;
}
double ConstraintP2PAngle::maxStep(MAP_pD_D &dir, double lim)
{
// step(angle()) <= pi/18 = 10°
MAP_pD_D::iterator it = dir.find(angle());
if (it != dir.end()) {
double step = std::abs(it->second);
if (step > M_PI/18.)
lim = std::min(lim, (M_PI/18.) / step);
}
return lim;
}
// P2LDistance
ConstraintP2LDistance::ConstraintP2LDistance(Point &p, Line &l, double *d)
{
pvec.push_back(p.x);
pvec.push_back(p.y);
pvec.push_back(l.p1.x);
pvec.push_back(l.p1.y);
pvec.push_back(l.p2.x);
pvec.push_back(l.p2.y);
pvec.push_back(d);
origpvec = pvec;
rescale();
}
ConstraintType ConstraintP2LDistance::getTypeId()
{
return P2LDistance;
}
void ConstraintP2LDistance::rescale(double coef)
{
scale = coef;
}
double ConstraintP2LDistance::error()
{
double x0=*p0x(), x1=*p1x(), x2=*p2x();
double y0=*p0y(), y1=*p1y(), y2=*p2y();
double dist = *distance();
double dx = x2-x1;
double dy = y2-y1;
double d = sqrt(dx*dx+dy*dy);
double area = std::abs(-x0*dy+y0*dx+x1*y2-x2*y1); // = x1y2 - x2y1 - x0y2 + x2y0 + x0y1 - x1y0 = 2*(triangle area)
return scale * (area/d - dist);
}
double ConstraintP2LDistance::grad(double *param)
{
double deriv=0.;
// darea/dx0 = (y1-y2) darea/dy0 = (x2-x1)
// darea/dx1 = (y2-y0) darea/dy1 = (x0-x2)
// darea/dx2 = (y0-y1) darea/dy2 = (x1-x0)
if (param == p0x() || param == p0y() ||
param == p1x() || param == p1y() ||
param == p2x() || param == p2y()) {
double x0=*p0x(), x1=*p1x(), x2=*p2x();
double y0=*p0y(), y1=*p1y(), y2=*p2y();
double dx = x2-x1;
double dy = y2-y1;
double d2 = dx*dx+dy*dy;
double d = sqrt(d2);
double area = -x0*dy+y0*dx+x1*y2-x2*y1;
if (param == p0x()) deriv += (y1-y2) / d;
if (param == p0y()) deriv += (x2-x1) / d ;
if (param == p1x()) deriv += ((y2-y0)*d + (dx/d)*area) / d2;
if (param == p1y()) deriv += ((x0-x2)*d + (dy/d)*area) / d2;
if (param == p2x()) deriv += ((y0-y1)*d - (dx/d)*area) / d2;
if (param == p2y()) deriv += ((x1-x0)*d - (dy/d)*area) / d2;
if (area < 0)
deriv *= -1;
}
if (param == distance()) deriv += -1;
return scale * deriv;
}
double ConstraintP2LDistance::maxStep(MAP_pD_D &dir, double lim)
{
MAP_pD_D::iterator it;
// distance() >= 0
it = dir.find(distance());
if (it != dir.end()) {
if (it->second < 0.)
lim = std::min(lim, -(*distance()) / it->second);
}
// restrict actual area change
double darea=0.;
double x0=*p0x(), x1=*p1x(), x2=*p2x();
double y0=*p0y(), y1=*p1y(), y2=*p2y();
it = dir.find(p0x());
if (it != dir.end()) darea += (y1-y2) * it->second;
it = dir.find(p0y());
if (it != dir.end()) darea += (x2-x1) * it->second;
it = dir.find(p1x());
if (it != dir.end()) darea += (y2-y0) * it->second;
it = dir.find(p1y());
if (it != dir.end()) darea += (x0-x2) * it->second;
it = dir.find(p2x());
if (it != dir.end()) darea += (y0-y1) * it->second;
it = dir.find(p2y());
if (it != dir.end()) darea += (x1-x0) * it->second;
darea = std::abs(darea);
if (darea > 0.) {
double dx = x2-x1;
double dy = y2-y1;
double area = 0.3*(*distance())*sqrt(dx*dx+dy*dy);
if (darea > area) {
area = std::max(area, 0.3*std::abs(-x0*dy+y0*dx+x1*y2-x2*y1));
if (darea > area)
lim = std::min(lim, area/darea);
}
}
return lim;
}
// PointOnLine
ConstraintPointOnLine::ConstraintPointOnLine(Point &p, Line &l)
{
pvec.push_back(p.x);
pvec.push_back(p.y);
pvec.push_back(l.p1.x);
pvec.push_back(l.p1.y);
pvec.push_back(l.p2.x);
pvec.push_back(l.p2.y);
origpvec = pvec;
rescale();
}
ConstraintType ConstraintPointOnLine::getTypeId()
{
return PointOnLine;
}
void ConstraintPointOnLine::rescale(double coef)
{
scale = coef;
}
double ConstraintPointOnLine::error()
{
double x0=*p0x(), x1=*p1x(), x2=*p2x();
double y0=*p0y(), y1=*p1y(), y2=*p2y();
double dx = x2-x1;
double dy = y2-y1;
double d = sqrt(dx*dx+dy*dy);
double area = -x0*dy+y0*dx+x1*y2-x2*y1; // = x1y2 - x2y1 - x0y2 + x2y0 + x0y1 - x1y0 = 2*(triangle area)
return scale * area/d;
}
double ConstraintPointOnLine::grad(double *param)
{
double deriv=0.;
// darea/dx0 = (y1-y2) darea/dy0 = (x2-x1)
// darea/dx1 = (y2-y0) darea/dy1 = (x0-x2)
// darea/dx2 = (y0-y1) darea/dy2 = (x1-x0)
if (param == p0x() || param == p0y() ||
param == p1x() || param == p1y() ||
param == p2x() || param == p2y()) {
double x0=*p0x(), x1=*p1x(), x2=*p2x();
double y0=*p0y(), y1=*p1y(), y2=*p2y();
double dx = x2-x1;
double dy = y2-y1;
double d2 = dx*dx+dy*dy;
double d = sqrt(d2);
double area = -x0*dy+y0*dx+x1*y2-x2*y1;
if (param == p0x()) deriv += (y1-y2) / d;
if (param == p0y()) deriv += (x2-x1) / d ;
if (param == p1x()) deriv += ((y2-y0)*d + (dx/d)*area) / d2;
if (param == p1y()) deriv += ((x0-x2)*d + (dy/d)*area) / d2;
if (param == p2x()) deriv += ((y0-y1)*d - (dx/d)*area) / d2;
if (param == p2y()) deriv += ((x1-x0)*d - (dy/d)*area) / d2;
}
return scale * deriv;
}
// Parallel
ConstraintParallel::ConstraintParallel(Line &l1, Line &l2)
{
pvec.push_back(l1.p1.x);
pvec.push_back(l1.p1.y);
pvec.push_back(l1.p2.x);
pvec.push_back(l1.p2.y);
pvec.push_back(l2.p1.x);
pvec.push_back(l2.p1.y);
pvec.push_back(l2.p2.x);
pvec.push_back(l2.p2.y);
origpvec = pvec;
rescale();
}
ConstraintType ConstraintParallel::getTypeId()
{
return Parallel;
}
void ConstraintParallel::rescale(double coef)
{
double dx1 = (*l1p1x() - *l1p2x());
double dy1 = (*l1p1y() - *l1p2y());
double dx2 = (*l2p1x() - *l2p2x());
double dy2 = (*l2p1y() - *l2p2y());
scale = coef / sqrt((dx1*dx1+dy1*dy1)*(dx2*dx2+dy2*dy2));
}
double ConstraintParallel::error()
{
double dx1 = (*l1p1x() - *l1p2x());
double dy1 = (*l1p1y() - *l1p2y());
double dx2 = (*l2p1x() - *l2p2x());
double dy2 = (*l2p1y() - *l2p2y());
return scale * (dx1*dy2 - dy1*dx2);
}
double ConstraintParallel::grad(double *param)
{
double deriv=0.;
if (param == l1p1x()) deriv += (*l2p1y() - *l2p2y()); // = dy2
if (param == l1p2x()) deriv += -(*l2p1y() - *l2p2y()); // = -dy2
if (param == l1p1y()) deriv += -(*l2p1x() - *l2p2x()); // = -dx2
if (param == l1p2y()) deriv += (*l2p1x() - *l2p2x()); // = dx2
if (param == l2p1x()) deriv += -(*l1p1y() - *l1p2y()); // = -dy1
if (param == l2p2x()) deriv += (*l1p1y() - *l1p2y()); // = dy1
if (param == l2p1y()) deriv += (*l1p1x() - *l1p2x()); // = dx1
if (param == l2p2y()) deriv += -(*l1p1x() - *l1p2x()); // = -dx1
return scale * deriv;
}
// Perpendicular
ConstraintPerpendicular::ConstraintPerpendicular(Line &l1, Line &l2)
{
pvec.push_back(l1.p1.x);
pvec.push_back(l1.p1.y);
pvec.push_back(l1.p2.x);
pvec.push_back(l1.p2.y);
pvec.push_back(l2.p1.x);
pvec.push_back(l2.p1.y);
pvec.push_back(l2.p2.x);
pvec.push_back(l2.p2.y);
origpvec = pvec;
rescale();
}
ConstraintPerpendicular::ConstraintPerpendicular(Point &l1p1, Point &l1p2,
Point &l2p1, Point &l2p2)
{
pvec.push_back(l1p1.x);
pvec.push_back(l1p1.y);
pvec.push_back(l1p2.x);
pvec.push_back(l1p2.y);
pvec.push_back(l2p1.x);
pvec.push_back(l2p1.y);
pvec.push_back(l2p2.x);
pvec.push_back(l2p2.y);
origpvec = pvec;
rescale();
}
ConstraintType ConstraintPerpendicular::getTypeId()
{
return Perpendicular;
}
void ConstraintPerpendicular::rescale(double coef)
{
double dx1 = (*l1p1x() - *l1p2x());
double dy1 = (*l1p1y() - *l1p2y());
double dx2 = (*l2p1x() - *l2p2x());
double dy2 = (*l2p1y() - *l2p2y());
scale = coef / sqrt((dx1*dx1+dy1*dy1)*(dx2*dx2+dy2*dy2));
}
double ConstraintPerpendicular::error()
{
double dx1 = (*l1p1x() - *l1p2x());
double dy1 = (*l1p1y() - *l1p2y());
double dx2 = (*l2p1x() - *l2p2x());
double dy2 = (*l2p1y() - *l2p2y());
return scale * (dx1*dx2 + dy1*dy2);
}
double ConstraintPerpendicular::grad(double *param)
{
double deriv=0.;
if (param == l1p1x()) deriv += (*l2p1x() - *l2p2x()); // = dx2
if (param == l1p2x()) deriv += -(*l2p1x() - *l2p2x()); // = -dx2
if (param == l1p1y()) deriv += (*l2p1y() - *l2p2y()); // = dy2
if (param == l1p2y()) deriv += -(*l2p1y() - *l2p2y()); // = -dy2
if (param == l2p1x()) deriv += (*l1p1x() - *l1p2x()); // = dx1
if (param == l2p2x()) deriv += -(*l1p1x() - *l1p2x()); // = -dx1
if (param == l2p1y()) deriv += (*l1p1y() - *l1p2y()); // = dy1
if (param == l2p2y()) deriv += -(*l1p1y() - *l1p2y()); // = -dy1
return scale * deriv;
}
// L2LAngle
ConstraintL2LAngle::ConstraintL2LAngle(Line &l1, Line &l2, double *a)
{
pvec.push_back(l1.p1.x);
pvec.push_back(l1.p1.y);
pvec.push_back(l1.p2.x);
pvec.push_back(l1.p2.y);
pvec.push_back(l2.p1.x);
pvec.push_back(l2.p1.y);
pvec.push_back(l2.p2.x);
pvec.push_back(l2.p2.y);
pvec.push_back(a);
origpvec = pvec;
rescale();
}
ConstraintL2LAngle::ConstraintL2LAngle(Point &l1p1, Point &l1p2,
Point &l2p1, Point &l2p2, double *a)
{
pvec.push_back(l1p1.x);
pvec.push_back(l1p1.y);
pvec.push_back(l1p2.x);
pvec.push_back(l1p2.y);
pvec.push_back(l2p1.x);
pvec.push_back(l2p1.y);
pvec.push_back(l2p2.x);
pvec.push_back(l2p2.y);
pvec.push_back(a);
origpvec = pvec;
rescale();
}
ConstraintType ConstraintL2LAngle::getTypeId()
{
return L2LAngle;
}
void ConstraintL2LAngle::rescale(double coef)
{
scale = coef * 1.;
}
double ConstraintL2LAngle::error()
{
double dx1 = (*l1p2x() - *l1p1x());
double dy1 = (*l1p2y() - *l1p1y());
double dx2 = (*l2p2x() - *l2p1x());
double dy2 = (*l2p2y() - *l2p1y());
double a = atan2(dy1,dx1) + *angle();
double ca = cos(a);
double sa = sin(a);
double x2 = dx2*ca + dy2*sa;
double y2 = -dx2*sa + dy2*ca;
return scale * atan2(y2,x2);
}
double ConstraintL2LAngle::grad(double *param)
{
double deriv=0.;
if (param == l1p1x() || param == l1p1y() ||
param == l1p2x() || param == l1p2y()) {
double dx1 = (*l1p2x() - *l1p1x());
double dy1 = (*l1p2y() - *l1p1y());
double r2 = dx1*dx1+dy1*dy1;
if (param == l1p1x()) deriv += -dy1/r2;
if (param == l1p1y()) deriv += dx1/r2;
if (param == l1p2x()) deriv += dy1/r2;
if (param == l1p2y()) deriv += -dx1/r2;
}
if (param == l2p1x() || param == l2p1y() ||
param == l2p2x() || param == l2p2y()) {
double dx1 = (*l1p2x() - *l1p1x());
double dy1 = (*l1p2y() - *l1p1y());
double dx2 = (*l2p2x() - *l2p1x());
double dy2 = (*l2p2y() - *l2p1y());
double a = atan2(dy1,dx1) + *angle();
double ca = cos(a);
double sa = sin(a);
double x2 = dx2*ca + dy2*sa;
double y2 = -dx2*sa + dy2*ca;
double r2 = dx2*dx2+dy2*dy2;
dx2 = -y2/r2;
dy2 = x2/r2;
if (param == l2p1x()) deriv += (-ca*dx2 + sa*dy2);
if (param == l2p1y()) deriv += (-sa*dx2 - ca*dy2);
if (param == l2p2x()) deriv += ( ca*dx2 - sa*dy2);
if (param == l2p2y()) deriv += ( sa*dx2 + ca*dy2);
}
if (param == angle()) deriv += -1;
return scale * deriv;
}
double ConstraintL2LAngle::maxStep(MAP_pD_D &dir, double lim)
{
// step(angle()) <= pi/18 = 10°
MAP_pD_D::iterator it = dir.find(angle());
if (it != dir.end()) {
double step = std::abs(it->second);
if (step > M_PI/18.)
lim = std::min(lim, (M_PI/18.) / step);
}
return lim;
}
// MidpointOnLine
ConstraintMidpointOnLine::ConstraintMidpointOnLine(Line &l1, Line &l2)
{
pvec.push_back(l1.p1.x);
pvec.push_back(l1.p1.y);
pvec.push_back(l1.p2.x);
pvec.push_back(l1.p2.y);
pvec.push_back(l2.p1.x);
pvec.push_back(l2.p1.y);
pvec.push_back(l2.p2.x);
pvec.push_back(l2.p2.y);
origpvec = pvec;
rescale();
}
ConstraintMidpointOnLine::ConstraintMidpointOnLine(Point &l1p1, Point &l1p2, Point &l2p1, Point &l2p2)
{
pvec.push_back(l1p1.x);
pvec.push_back(l1p1.y);
pvec.push_back(l1p2.x);
pvec.push_back(l1p2.y);
pvec.push_back(l2p1.x);
pvec.push_back(l2p1.y);
pvec.push_back(l2p2.x);
pvec.push_back(l2p2.y);
origpvec = pvec;
rescale();
}
ConstraintType ConstraintMidpointOnLine::getTypeId()
{
return MidpointOnLine;
}
void ConstraintMidpointOnLine::rescale(double coef)
{
scale = coef * 1;
}
double ConstraintMidpointOnLine::error()
{
double x0=((*l1p1x())+(*l1p2x()))/2;
double y0=((*l1p1y())+(*l1p2y()))/2;
double x1=*l2p1x(), x2=*l2p2x();
double y1=*l2p1y(), y2=*l2p2y();
double dx = x2-x1;
double dy = y2-y1;
double d = sqrt(dx*dx+dy*dy);
double area = -x0*dy+y0*dx+x1*y2-x2*y1; // = x1y2 - x2y1 - x0y2 + x2y0 + x0y1 - x1y0 = 2*(triangle area)
return scale * area/d;
}
double ConstraintMidpointOnLine::grad(double *param)
{
double deriv=0.;
// darea/dx0 = (y1-y2) darea/dy0 = (x2-x1)
// darea/dx1 = (y2-y0) darea/dy1 = (x0-x2)
// darea/dx2 = (y0-y1) darea/dy2 = (x1-x0)
if (param == l1p1x() || param == l1p1y() ||
param == l1p2x() || param == l1p2y()||
param == l2p1x() || param == l2p1y() ||
param == l2p2x() || param == l2p2y()) {
double x0=((*l1p1x())+(*l1p2x()))/2;
double y0=((*l1p1y())+(*l1p2y()))/2;
double x1=*l2p1x(), x2=*l2p2x();
double y1=*l2p1y(), y2=*l2p2y();
double dx = x2-x1;
double dy = y2-y1;
double d2 = dx*dx+dy*dy;
double d = sqrt(d2);
double area = -x0*dy+y0*dx+x1*y2-x2*y1;
if (param == l1p1x()) deriv += (y1-y2) / (2*d);
if (param == l1p1y()) deriv += (x2-x1) / (2*d);
if (param == l1p2x()) deriv += (y1-y2) / (2*d);
if (param == l1p2y()) deriv += (x2-x1) / (2*d);
if (param == l2p1x()) deriv += ((y2-y0)*d + (dx/d)*area) / d2;
if (param == l2p1y()) deriv += ((x0-x2)*d + (dy/d)*area) / d2;
if (param == l2p2x()) deriv += ((y0-y1)*d - (dx/d)*area) / d2;
if (param == l2p2y()) deriv += ((x1-x0)*d - (dy/d)*area) / d2;
}
return scale * deriv;
}
} //namespace GCS

View File

@@ -0,0 +1,267 @@
/***************************************************************************
* Copyright (c) Konstantinos Poulios (logari81@gmail.com) 2011 *
* *
* 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 *
* *
***************************************************************************/
#ifndef FREEGCS_CONSTRAINTS_H
#define FREEGCS_CONSTRAINTS_H
#include "Geo.h"
#include "Util.h"
namespace GCS
{
///////////////////////////////////////
// Constraints
///////////////////////////////////////
enum ConstraintType {
None = 0,
Equal = 1,
Difference = 2,
P2PDistance = 3,
P2PAngle = 4,
P2LDistance = 5,
PointOnLine = 6,
Parallel = 7,
Perpendicular = 8,
L2LAngle = 9,
MidpointOnLine = 10
};
class Constraint
{
protected:
VEC_pD origpvec; // is used only as a reference for redirecting and reverting pvec
VEC_pD pvec;
double scale;
int tag;
public:
Constraint();
inline VEC_pD params() { return pvec; }
void redirectParams(MAP_pD_pD redirectionmap);
void revertParams();
void setTag(int tagId) { tag = tagId; }
int getTag() { return tag; }
virtual ConstraintType getTypeId();
virtual void rescale(double coef=1.);
virtual double error();
virtual double grad(double *);
// virtual void grad(MAP_pD_D &deriv); --> TODO: vectorized grad version
virtual double maxStep(MAP_pD_D &dir, double lim=1.);
};
// Equal
class ConstraintEqual : public Constraint
{
private:
inline double* param1() { return pvec[0]; }
inline double* param2() { return pvec[1]; }
public:
ConstraintEqual(double *p1, double *p2);
virtual ConstraintType getTypeId();
virtual void rescale(double coef=1.);
virtual double error();
virtual double grad(double *);
};
// Difference
class ConstraintDifference : public Constraint
{
private:
inline double* param1() { return pvec[0]; }
inline double* param2() { return pvec[1]; }
inline double* difference() { return pvec[2]; }
public:
ConstraintDifference(double *p1, double *p2, double *d);
virtual ConstraintType getTypeId();
virtual void rescale(double coef=1.);
virtual double error();
virtual double grad(double *);
};
// P2PDistance
class ConstraintP2PDistance : 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* distance() { return pvec[4]; }
public:
ConstraintP2PDistance(Point &p1, Point &p2, double *d);
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.);
};
// P2PAngle
class ConstraintP2PAngle : 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* angle() { return pvec[4]; }
double da;
public:
ConstraintP2PAngle(Point &p1, Point &p2, double *a, double da_=0.);
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.);
};
// P2LDistance
class ConstraintP2LDistance : public Constraint
{
private:
inline double* p0x() { return pvec[0]; }
inline double* p0y() { return pvec[1]; }
inline double* p1x() { return pvec[2]; }
inline double* p1y() { return pvec[3]; }
inline double* p2x() { return pvec[4]; }
inline double* p2y() { return pvec[5]; }
inline double* distance() { return pvec[6]; }
public:
ConstraintP2LDistance(Point &p, Line &l, double *d);
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.);
};
// PointOnLine
class ConstraintPointOnLine : public Constraint
{
private:
inline double* p0x() { return pvec[0]; }
inline double* p0y() { return pvec[1]; }
inline double* p1x() { return pvec[2]; }
inline double* p1y() { return pvec[3]; }
inline double* p2x() { return pvec[4]; }
inline double* p2y() { return pvec[5]; }
public:
ConstraintPointOnLine(Point &p, Line &l);
virtual ConstraintType getTypeId();
virtual void rescale(double coef=1.);
virtual double error();
virtual double grad(double *);
};
// Parallel
class ConstraintParallel : public Constraint
{
private:
inline double* l1p1x() { return pvec[0]; }
inline double* l1p1y() { return pvec[1]; }
inline double* l1p2x() { return pvec[2]; }
inline double* l1p2y() { return pvec[3]; }
inline double* l2p1x() { return pvec[4]; }
inline double* l2p1y() { return pvec[5]; }
inline double* l2p2x() { return pvec[6]; }
inline double* l2p2y() { return pvec[7]; }
public:
ConstraintParallel(Line &l1, Line &l2);
virtual ConstraintType getTypeId();
virtual void rescale(double coef=1.);
virtual double error();
virtual double grad(double *);
};
// Perpendicular
class ConstraintPerpendicular : public Constraint
{
private:
inline double* l1p1x() { return pvec[0]; }
inline double* l1p1y() { return pvec[1]; }
inline double* l1p2x() { return pvec[2]; }
inline double* l1p2y() { return pvec[3]; }
inline double* l2p1x() { return pvec[4]; }
inline double* l2p1y() { return pvec[5]; }
inline double* l2p2x() { return pvec[6]; }
inline double* l2p2y() { return pvec[7]; }
public:
ConstraintPerpendicular(Line &l1, Line &l2);
ConstraintPerpendicular(Point &l1p1, Point &l1p2, Point &l2p1, Point &l2p2);
virtual ConstraintType getTypeId();
virtual void rescale(double coef=1.);
virtual double error();
virtual double grad(double *);
};
// L2LAngle
class ConstraintL2LAngle : public Constraint
{
private:
inline double* l1p1x() { return pvec[0]; }
inline double* l1p1y() { return pvec[1]; }
inline double* l1p2x() { return pvec[2]; }
inline double* l1p2y() { return pvec[3]; }
inline double* l2p1x() { return pvec[4]; }
inline double* l2p1y() { return pvec[5]; }
inline double* l2p2x() { return pvec[6]; }
inline double* l2p2y() { return pvec[7]; }
inline double* angle() { return pvec[8]; }
public:
ConstraintL2LAngle(Line &l1, Line &l2, double *a);
ConstraintL2LAngle(Point &l1p1, Point &l1p2,
Point &l2p1, Point &l2p2, double *a);
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.);
};
// MidpointOnLine
class ConstraintMidpointOnLine : public Constraint
{
private:
inline double* l1p1x() { return pvec[0]; }
inline double* l1p1y() { return pvec[1]; }
inline double* l1p2x() { return pvec[2]; }
inline double* l1p2y() { return pvec[3]; }
inline double* l2p1x() { return pvec[4]; }
inline double* l2p1y() { return pvec[5]; }
inline double* l2p2x() { return pvec[6]; }
inline double* l2p2y() { return pvec[7]; }
public:
ConstraintMidpointOnLine(Line &l1, Line &l2);
ConstraintMidpointOnLine(Point &l1p1, Point &l1p2, Point &l2p1, Point &l2p2);
virtual ConstraintType getTypeId();
virtual void rescale(double coef=1.);
virtual double error();
virtual double grad(double *);
};
} //namespace GCS
#endif // FREEGCS_CONSTRAINTS_H

View File

@@ -0,0 +1,954 @@
/***************************************************************************
* Copyright (c) Konstantinos Poulios (logari81@gmail.com) 2011 *
* *
* 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 <iostream>
#include <algorithm>
#include "GCS.h"
#include "qp_eq.h"
#include <Eigen/QR>
namespace GCS
{
///////////////////////////////////////
// Solver
///////////////////////////////////////
// System
System::System()
: clist(0),
c2p(), p2c(),
subsystems(0),
reference(),
init(false)
{
}
System::System(std::vector<Constraint *> clist_)
: c2p(), p2c(),
subsystems(0),
reference(),
init(false)
{
// create own (shallow) copy of constraints
for (std::vector<Constraint *>::iterator constr=clist_.begin();
constr != clist_.end(); ++constr) {
Constraint *newconstr;
switch ((*constr)->getTypeId()) {
case Equal: {
ConstraintEqual *oldconstr = static_cast<ConstraintEqual *>(*constr);
newconstr = new ConstraintEqual(*oldconstr);
break;
}
case Difference: {
ConstraintDifference *oldconstr = static_cast<ConstraintDifference *>(*constr);
newconstr = new ConstraintDifference(*oldconstr);
break;
}
case P2PDistance: {
ConstraintP2PDistance *oldconstr = static_cast<ConstraintP2PDistance *>(*constr);
newconstr = new ConstraintP2PDistance(*oldconstr);
break;
}
case P2PAngle: {
ConstraintP2PAngle *oldconstr = static_cast<ConstraintP2PAngle *>(*constr);
newconstr = new ConstraintP2PAngle(*oldconstr);
break;
}
case P2LDistance: {
ConstraintP2LDistance *oldconstr = static_cast<ConstraintP2LDistance *>(*constr);
newconstr = new ConstraintP2LDistance(*oldconstr);
break;
}
case PointOnLine: {
ConstraintPointOnLine *oldconstr = static_cast<ConstraintPointOnLine *>(*constr);
newconstr = new ConstraintPointOnLine(*oldconstr);
break;
}
case Parallel: {
ConstraintParallel *oldconstr = static_cast<ConstraintParallel *>(*constr);
newconstr = new ConstraintParallel(*oldconstr);
break;
}
case Perpendicular: {
ConstraintPerpendicular *oldconstr = static_cast<ConstraintPerpendicular *>(*constr);
newconstr = new ConstraintPerpendicular(*oldconstr);
break;
}
case L2LAngle: {
ConstraintL2LAngle *oldconstr = static_cast<ConstraintL2LAngle *>(*constr);
newconstr = new ConstraintL2LAngle(*oldconstr);
break;
}
case MidpointOnLine: {
ConstraintMidpointOnLine *oldconstr = static_cast<ConstraintMidpointOnLine *>(*constr);
newconstr = new ConstraintMidpointOnLine(*oldconstr);
break;
}
case None:
break;
}
if (newconstr)
addConstraint(newconstr);
}
}
System::~System()
{
clear();
}
void System::clear()
{
clearReference();
clearSubSystems();
free(clist);
c2p.clear();
p2c.clear();
}
void System::clearByTag(int tagId)
{
std::vector<Constraint *> constrvec;
for (std::vector<Constraint *>::const_iterator
constr=clist.begin(); constr != clist.end(); ++constr) {
if ((*constr)->getTag() == tagId)
constrvec.push_back(*constr);
}
for (std::vector<Constraint *>::const_iterator
constr=constrvec.begin(); constr != constrvec.end(); ++constr) {
removeConstraint(*constr);
}
}
int System::addConstraint(Constraint *constr)
{
clearReference();
clist.push_back(constr);
VEC_pD constr_params = constr->params();
for (VEC_pD::const_iterator param=constr_params.begin();
param != constr_params.end(); ++param) {
// jacobi.set(constr, *param, 0.);
c2p[constr].push_back(*param);
p2c[*param].push_back(constr);
}
return clist.size()-1;
}
void System::removeConstraint(Constraint *constr)
{
clearReference();
clearSubSystems();
std::vector<Constraint *>::iterator it;
it = std::find(clist.begin(), clist.end(), constr);
clist.erase(it);
VEC_pD constr_params = c2p[constr];
for (VEC_pD::const_iterator param=constr_params.begin();
param != constr_params.end(); ++param) {
std::vector<Constraint *> &constraints = p2c[*param];
it = std::find(constraints.begin(), constraints.end(), constr);
constraints.erase(it);
}
c2p.erase(constr);
std::vector<Constraint *> constrvec;
constrvec.push_back(constr);
free(constrvec);
}
// basic constraints
int System::addConstraintEqual(double *param1, double *param2, int tagId)
{
Constraint *constr = new ConstraintEqual(param1, param2);
constr->setTag(tagId);
return addConstraint(constr);
}
int System::addConstraintDifference(double *param1, double *param2,
double *difference, int tagId)
{
Constraint *constr = new ConstraintDifference(param1, param2, difference);
constr->setTag(tagId);
return addConstraint(constr);
}
int System::addConstraintP2PDistance(Point &p1, Point &p2, double *distance, int tagId)
{
Constraint *constr = new ConstraintP2PDistance(p1, p2, distance);
constr->setTag(tagId);
return addConstraint(constr);
}
int System::addConstraintP2PAngle(Point &p1, Point &p2, double *angle,
double incr_angle, int tagId)
{
Constraint *constr = new ConstraintP2PAngle(p1, p2, angle, incr_angle);
constr->setTag(tagId);
return addConstraint(constr);
}
int System::addConstraintP2PAngle(Point &p1, Point &p2, double *angle, int tagId)
{
return addConstraintP2PAngle(p1, p2, angle, 0.);
}
int System::addConstraintP2LDistance(Point &p, Line &l, double *distance, int tagId)
{
Constraint *constr = new ConstraintP2LDistance(p, l, distance);
constr->setTag(tagId);
return addConstraint(constr);
}
int System::addConstraintPointOnLine(Point &p, Line &l, int tagId)
{
Constraint *constr = new ConstraintPointOnLine(p, l);
constr->setTag(tagId);
return addConstraint(constr);
}
int System::addConstraintParallel(Line &l1, Line &l2, int tagId)
{
Constraint *constr = new ConstraintParallel(l1, l2);
constr->setTag(tagId);
return addConstraint(constr);
}
int System::addConstraintPerpendicular(Line &l1, Line &l2, int tagId)
{
Constraint *constr = new ConstraintPerpendicular(l1, l2);
constr->setTag(tagId);
return addConstraint(constr);
}
int System::addConstraintPerpendicular(Point &l1p1, Point &l1p2,
Point &l2p1, Point &l2p2, int tagId)
{
Constraint *constr = new ConstraintPerpendicular(l1p1, l1p2, l2p1, l2p2);
constr->setTag(tagId);
return addConstraint(constr);
}
int System::addConstraintL2LAngle(Line &l1, Line &l2, double *angle, int tagId)
{
Constraint *constr = new ConstraintL2LAngle(l1, l2, angle);
constr->setTag(tagId);
return addConstraint(constr);
}
int System::addConstraintL2LAngle(Point &l1p1, Point &l1p2,
Point &l2p1, Point &l2p2, double *angle, int tagId)
{
Constraint *constr = new ConstraintL2LAngle(l1p1, l1p2, l2p1, l2p2, angle);
constr->setTag(tagId);
return addConstraint(constr);
}
int System::addConstraintMidpointOnLine(Line &l1, Line &l2, int tagId)
{
Constraint *constr = new ConstraintMidpointOnLine(l1, l2);
constr->setTag(tagId);
return addConstraint(constr);
}
int System::addConstraintMidpointOnLine(Point &l1p1, Point &l1p2,
Point &l2p1, Point &l2p2, int tagId)
{
Constraint *constr = new ConstraintMidpointOnLine(l1p1, l1p2, l2p1, l2p2);
constr->setTag(tagId);
return addConstraint(constr);
}
// derived constraints
int System::addConstraintP2PCoincident(Point &p1, Point &p2, int tagId)
{
addConstraintEqual(p1.x, p2.x, tagId);
return addConstraintEqual(p1.y, p2.y, tagId);
}
int System::addConstraintHorizontal(Line &l, int tagId)
{
return addConstraintEqual(l.p1.y, l.p2.y, tagId);
}
int System::addConstraintHorizontal(Point &p1, Point &p2, int tagId)
{
return addConstraintEqual(p1.y, p2.y, tagId);
}
int System::addConstraintVertical(Line &l, int tagId)
{
return addConstraintEqual(l.p1.x, l.p2.x, tagId);
}
int System::addConstraintVertical(Point &p1, Point &p2, int tagId)
{
return addConstraintEqual(p1.x, p2.x, tagId);
}
int System::addConstraintCoordinateX(Point &p, double *x, int tagId)
{
return addConstraintEqual(p.x, x, tagId);
}
int System::addConstraintCoordinateY(Point &p, double *y, int tagId)
{
return addConstraintEqual(p.y, y, tagId);
}
int System::addConstraintArcRules(Arc &a, int tagId)
{
addConstraintP2PAngle(a.center, a.start, a.startAngle, tagId);
addConstraintP2PAngle(a.center, a.end, a.endAngle, tagId);
addConstraintP2PDistance(a.center, a.start, a.rad, tagId);
return addConstraintP2PDistance(a.center, a.end, a.rad, tagId);
}
int System::addConstraintPointOnCircle(Point &p, Circle &c, int tagId)
{
return addConstraintP2PDistance(p, c.center, c.rad, tagId);
}
int System::addConstraintPointOnArc(Point &p, Arc &a, int tagId)
{
return addConstraintP2PDistance(p, a.center, a.rad, tagId);
}
int System::addConstraintTangent(Line &l, Circle &c, int tagId)
{
return addConstraintP2LDistance(c.center, l, c.rad, tagId);
}
int System::addConstraintTangent(Line &l, Arc &a, int tagId)
{
return addConstraintP2LDistance(a.center, l, a.rad, tagId);
}
int System::addConstraintTangentLine2Arc(Point &p1, Point &p2, Arc &a, int tagId)
{
addConstraintP2PCoincident(p2, a.start, tagId);
double incr_angle = *(a.startAngle) < *(a.endAngle) ? M_PI/2 : -M_PI/2;
return addConstraintP2PAngle(p1, p2, a.startAngle, incr_angle, tagId);
}
int System::addConstraintTangentArc2Line(Arc &a, Point &p1, Point &p2, int tagId)
{
addConstraintP2PCoincident(p1, a.end, tagId);
double incr_angle = *(a.startAngle) < *(a.endAngle) ? M_PI/2 : -M_PI/2;
return addConstraintP2PAngle(p1, p2, a.endAngle, incr_angle, tagId);
}
int System::addConstraintCircleRadius(Circle &c, double *radius, int tagId)
{
return addConstraintEqual(c.rad, radius, tagId);
}
int System::addConstraintArcRadius(Arc &a, double *radius, int tagId)
{
return addConstraintEqual(a.rad, radius, tagId);
}
int System::addConstraintEqualLength(Line &l1, Line &l2, double *length, int tagId)
{
addConstraintP2PDistance(l1.p1, l1.p2, length, tagId);
return addConstraintP2PDistance(l2.p1, l2.p2, length, tagId);
}
int System::addConstraintEqualRadius(Circle &c1, Circle &c2, int tagId)
{
return addConstraintEqual(c1.rad, c2.rad, tagId);
}
int System::addConstraintEqualRadius(Circle &c1, Arc &a2, int tagId)
{
return addConstraintEqual(c1.rad, a2.rad, tagId);
}
int System::addConstraintEqualRadius(Arc &a1, Arc &a2, int tagId)
{
return addConstraintEqual(a1.rad, a2.rad, tagId);
}
int System::addConstraintP2PSymmetric(Point &p1, Point &p2, Line &l, int tagId)
{
addConstraintPerpendicular(p1, p2, l.p1, l.p2, tagId);
return addConstraintMidpointOnLine(p1, p2, l.p1, l.p2, tagId);
}
void System::initSolution(VEC_pD &params)
{
// - Stores the current parameters in the vector "reference"
// - Identifies the equality constraints with tagged with ids >= 0
// and prepares a corresponding system reduction
// - Organizes the rest of constraints into two subsystems for
// tag ids >=0 and < 0 respectively and applies the
// system reduction specified in the previous step
clearReference();
for (VEC_pD::const_iterator param=params.begin();
param != params.end(); ++param)
reference[*param] = **param;
// identification of equality constraints and parameter reduction
std::set<Constraint *> eliminated; // constraints that will be eliminated through reduction
reductionmap.clear();
{
VEC_pD reduced_params=params;
MAP_pD_I params_index;
for (int i=0; i < int(params.size()); ++i)
params_index[params[i]] = i;
for (std::vector<Constraint *>::const_iterator constr=clist.begin();
constr != clist.end(); ++constr) {
if ((*constr)->getTag() >= 0 && (*constr)->getTypeId() == Equal) {
MAP_pD_I::const_iterator it1,it2;
it1 = params_index.find((*constr)->params()[0]);
it2 = params_index.find((*constr)->params()[1]);
if (it1 != params_index.end() && it2 != params_index.end()) {
eliminated.insert(*constr);
double *p_kept = reduced_params[it1->second];
double *p_replaced = reduced_params[it2->second];
for (int i=0; i < int(params.size()); ++i)
if (reduced_params[i] == p_replaced)
reduced_params[i] = p_kept;
}
}
}
for (int i=0; i < int(params.size()); ++i)
if (params[i] != reduced_params[i])
reductionmap[params[i]] = reduced_params[i];
}
int i=0;
std::vector<Constraint *> clist0, clist1;
for (std::vector<Constraint *>::const_iterator constr=clist.begin();
constr != clist.end(); ++constr, i++) {
if (eliminated.count(*constr) == 0) {
if ((*constr)->getTag() >= 0)
clist0.push_back(*constr);
else
clist1.push_back(*constr);
}
}
clearSubSystems();
if (clist0.size() > 0)
subsystems.push_back(new SubSystem(clist0, params, reductionmap));
if (clist1.size() > 0)
subsystems.push_back(new SubSystem(clist1, params, reductionmap));
init = true;
}
void System::clearReference()
{
init = false;
reference.clear();
}
void System::resetToReference()
{
for (MAP_pD_D::const_iterator it=reference.begin();
it != reference.end(); ++it)
*(it->first) = it->second;
}
int System::solve(VEC_pD &params, int isFine)
{
initSolution(params);
return solve(isFine);
}
int System::solve(int isFine)
{
if (subsystems.size() == 0)
return 0;
else if (subsystems.size() == 1) {
resetToReference();
return solve(subsystems[0], isFine);
}
else {
resetToReference();
solve(subsystems[0], isFine);
return solve(subsystems[0], subsystems[1], isFine);
}
}
int System::solve(SubSystem *subsys, int isFine)
{
int xsize = subsys->pSize();
if (xsize == 0)
return Success;
subsys->redirectParams();
Eigen::MatrixXd D = Eigen::MatrixXd::Identity(xsize, xsize);
Eigen::VectorXd x(xsize);
Eigen::VectorXd xdir(xsize);
Eigen::VectorXd grad(xsize);
Eigen::VectorXd h(xsize);
Eigen::VectorXd y(xsize);
Eigen::VectorXd Dy(xsize);
// Initial unknowns vector and initial gradient vector
subsys->getParams(x);
subsys->calcGrad(grad);
// Initial search direction oposed to gradient (steepest-descent)
xdir = -grad;
lineSearch(subsys, xdir);
double err = subsys->error();
h = x;
subsys->getParams(x);
h = x - h; // = x - xold
double convergence = (isFine > 0) ? XconvergenceFine : XconvergenceRough;
int maxIterNumber = MaxIterations * xsize;
for (int iter=1; iter < maxIterNumber; iter++) {
if (h.norm() <= convergence || err <= smallF)
break;
y = grad;
subsys->calcGrad(grad);
y = grad - y; // = grad - gradold
double hty = h.dot(y);
//make sure that hty is never 0
if (hty == 0)
hty = .0000000001;
Dy = D * y;
double ytDy = y.dot(Dy);
//Now calculate the BFGS update on D
D += (1.+ytDy/hty)/hty * h * h.transpose();
D -= 1./hty * (h * Dy.transpose() + Dy * h.transpose());
xdir = -D * grad;
lineSearch(subsys, xdir);
err = subsys->error();
h = x;
subsys->getParams(x);
h = x - h; // = x - xold
}
subsys->revertParams();
if (err <= smallF)
return Success;
if (h.norm() <= convergence)
return Converged;
return Failed;
}
// The following solver variant solves a system compound of two subsystems
// treating the first of them as of higher priority than the second
int System::solve(SubSystem *subsysA, SubSystem *subsysB, int isFine)
{
int xsizeA = subsysA->pSize();
int xsizeB = subsysB->pSize();
int csizeA = subsysA->cSize();
VEC_pD plist(xsizeA+xsizeB);
{
VEC_pD plistA, plistB;
subsysA->getParamList(plistA);
subsysB->getParamList(plistB);
std::sort(plistA.begin(),plistA.end());
std::sort(plistB.begin(),plistB.end());
VEC_pD::const_iterator it;
it = std::set_union(plistA.begin(),plistA.end(),
plistB.begin(),plistB.end(),plist.begin());
plist.resize(it-plist.begin());
}
int xsize = plist.size();
Eigen::MatrixXd B = Eigen::MatrixXd::Identity(xsize, xsize);
Eigen::MatrixXd JA(csizeA, xsize);
Eigen::MatrixXd Y,Z;
Eigen::VectorXd resA(csizeA);
Eigen::VectorXd lambda(csizeA), lambda0(csizeA), lambdadir(csizeA);
Eigen::VectorXd x(xsize), x0(xsize), xdir(xsize), xdir1(xsize);
Eigen::VectorXd grad(xsize);
Eigen::VectorXd h(xsize);
Eigen::VectorXd y(xsize);
Eigen::VectorXd Bh(xsize);
// We assume that there are no common constraints in subsysA and subsysB
subsysA->redirectParams();
subsysB->redirectParams();
subsysB->getParams(plist,x);
subsysA->getParams(plist,x);
subsysB->setParams(plist,x); // just to ensure that A and B are synchronized
subsysB->calcGrad(plist,grad);
subsysA->calcJacobi(plist,JA);
subsysA->calcResidual(resA);
double convergence = (isFine > 0) ? XconvergenceFine : XconvergenceRough;
int maxIterNumber = MaxIterations * xsize;
double mu = 0;
lambda.setZero();
for (int iter=1; iter < maxIterNumber; iter++) {
int status = qp_eq(B, grad, JA, resA, xdir, Y, Z);
if (status)
break;
x0 = x;
lambda0 = lambda;
lambda = Y.transpose() * (B * xdir + grad);
lambdadir = lambda - lambda0;
// line search
{
double eta=0.25;
double tau=0.5;
double rho=0.5;
double alpha=1;
alpha = std::min(alpha, subsysA->maxStep(plist,xdir));
// Eq. 18.32
// double mu = lambda.lpNorm<Eigen::Infinity>() + 0.01;
// Eq. 18.33
// double mu = grad.dot(xdir) / ( (1.-rho) * resA.lpNorm<1>());
// Eq. 18.36
mu = std::max(mu,
(grad.dot(xdir) + std::max(0., 0.5*xdir.dot(B*xdir))) /
( (1. - rho) * resA.lpNorm<1>() ) );
// Eq. 18.27
double f0 = subsysB->error() + mu * resA.lpNorm<1>();
// Eq. 18.29
double deriv = grad.dot(xdir) - mu * resA.lpNorm<1>();
x = x0 + alpha * xdir;
subsysA->setParams(plist,x);
subsysB->setParams(plist,x);
subsysA->calcResidual(resA);
double f = subsysB->error() + mu * resA.lpNorm<1>();
// line search, Eq. 18.28
bool first = true;
while (f > f0 + eta * alpha * deriv) {
if (first) { // try a second order step
// xdir1 = JA.jacobiSvd(Eigen::ComputeThinU |
// Eigen::ComputeThinV).solve(-resA);
xdir1 = -Y*resA;
x += xdir1; // = x0 + alpha * xdir + xdir1
subsysA->setParams(plist,x);
subsysB->setParams(plist,x);
subsysA->calcResidual(resA);
f = subsysB->error() + mu * resA.lpNorm<1>();
if (f < f0 + eta * alpha * deriv)
break;
}
alpha = tau * alpha;
x = x0 + alpha * xdir;
subsysA->setParams(plist,x);
subsysB->setParams(plist,x);
subsysA->calcResidual(resA);
f = subsysB->error() + mu * resA.lpNorm<1>();
}
lambda = lambda0 + alpha * lambdadir;
}
h = x - x0;
y = grad - JA.transpose() * lambda;
{
subsysB->calcGrad(plist,grad);
subsysA->calcJacobi(plist,JA);
subsysA->calcResidual(resA);
}
y = grad - JA.transpose() * lambda - y; // Eq. 18.13
if (iter > 1) {
double yTh = y.dot(h);
if (yTh != 0) {
Bh = B * h;
//Now calculate the BFGS update on B
B += 1./yTh * y * y.transpose();
B -= 1./h.dot(Bh) * (Bh * Bh.transpose());
}
}
if (h.norm() <= convergence && subsysA->error() <= smallF)
break;
}
int ret;
if (subsysA->error() <= smallF)
ret = Success;
else if (h.norm() <= convergence)
ret = Converged;
else
ret = Failed;
subsysA->revertParams();
subsysB->revertParams();
return ret;
}
void System::getSubSystems(std::vector<SubSystem *> &subsysvec)
{
subsysvec = subsystems;
}
void System::applySolution()
{
if (subsystems.size() > 1)
subsystems[1]->applySolution();
if (subsystems.size() > 0)
subsystems[0]->applySolution();
for (MAP_pD_pD::const_iterator it=reductionmap.begin();
it != reductionmap.end(); ++it)
*(it->first) = *(it->second);
}
int System::diagnose(VEC_pD &params, VEC_I &conflicting)
{
// Analyses the constrainess grad of the system and provides feedback
// The vector "conflicting" will hold a group of conflicting constraints
conflicting.clear();
std::vector<VEC_I> conflictingIndex;
std::vector<int> tags;
Eigen::MatrixXd J(clist.size(), params.size());
int count=0;
for (std::vector<Constraint *>::iterator constr=clist.begin();
constr != clist.end(); ++constr) {
(*constr)->revertParams();
if ((*constr)->getTag() >= 0) {
count++;
tags.push_back((*constr)->getTag());
for (int j=0; j < int(params.size()); j++)
J(count-1,j) = (*constr)->grad(params[j]);
}
}
if (J.rows() > 0) {
Eigen::FullPivHouseholderQR<Eigen::MatrixXd> qrJT(J.topRows(count).transpose());
Eigen::MatrixXd Q = qrJT.matrixQ ();
int params_num = qrJT.rows();
int constr_num = qrJT.cols();
int rank = qrJT.rank();
Eigen::MatrixXd R;
if (constr_num >= params_num)
R = qrJT.matrixQR().triangularView<Eigen::Upper>();
else
R = qrJT.matrixQR().topRows(constr_num)
.triangularView<Eigen::Upper>();
if (constr_num > rank) { // conflicting constraints
for (int i=1; i < rank; i++) {
// eliminate non zeros above pivot
assert(R(i,i) != 0);
for (int row=0; row < i; row++) {
if (R(row,i) != 0) {
double coef=R(row,i)/R(i,i);
R.block(row,i+1,1,constr_num-i-1) -= coef * R.block(i,i+1,1,constr_num-i-1);
R(row,i) = 0;
}
}
}
conflictingIndex.resize(constr_num-rank);
for (int j=rank; j < constr_num; j++) {
for (int row=0; row < rank; row++) {
if (R(row,j) != 0) {
int orig_col = qrJT.colsPermutation().indices()[row];
conflictingIndex[j-rank].push_back(orig_col);
}
}
int orig_col = qrJT.colsPermutation().indices()[j];
conflictingIndex[j-rank].push_back(orig_col);
}
SET_I tags_set;
for (int i=0; i < conflictingIndex.size(); i++) {
for (int j=0; j < conflictingIndex[i].size(); j++) {
tags_set.insert(tags[conflictingIndex[i][j]]);
}
}
tags_set.erase(0); // exclude constraints tagged with zero
conflicting.resize(tags_set.size());
std::copy(tags_set.begin(), tags_set.end(), conflicting.begin());
if (params_num == rank) // over-constrained
return params_num - constr_num;
}
return params_num - rank;
}
return params.size();
}
void System::clearSubSystems()
{
init = false;
free(subsystems);
}
double lineSearch(SubSystem *subsys, Eigen::VectorXd &xdir)
{
double f1,f2,f3,alpha1,alpha2,alpha3,alphaStar;
Eigen::VectorXd x0, x;
//Save initial values
subsys->getParams(x0);
//Start at the initial position alpha1 = 0
alpha1 = 0.;
f1 = subsys->error();
//Take a step of alpha2 = 1
alpha2 = 1.;
x = x0 + alpha2 * xdir;
subsys->setParams(x);
f2 = subsys->error();
//Take a step of alpha3 = 2*alpha2
alpha3 = alpha2*2;
x = x0 + alpha3 * xdir;
subsys->setParams(x);
f3 = subsys->error();
//Now reduce or lengthen alpha2 and alpha3 until the minimum is
//Bracketed by the triplet f1>f2<f3
while (f2 > f1 || f2 > f3) {
if (f2 > f1) {
//If f2 is greater than f1 then we shorten alpha2 and alpha3 closer to f1
//Effectively both are shortened by a factor of two.
alpha3 = alpha2;
f3 = f2;
alpha2 = alpha2 / 2;
x = x0 + alpha2 * xdir;
subsys->setParams(x);
f2 = subsys->error();
}
else if (f2 > f3) {
//If f2 is greater than f3 then we increase alpha2 and alpha3 away from f1
//Effectively both are lengthened by a factor of two.
alpha2 = alpha3;
f2 = f3;
alpha3 = alpha3 * 2;
x = x0 + alpha3 * xdir;
subsys->setParams(x);
f3 = subsys->error();
}
}
//Get the alpha for the minimum f of the quadratic approximation
alphaStar = alpha2 + ((alpha2-alpha1)*(f1-f3))/(3*(f1-2*f2+f3));
//Guarantee that the new alphaStar is within the bracket
if (alphaStar >= alpha3 || alphaStar <= alpha1)
alphaStar = alpha2;
if (alphaStar != alphaStar)
alphaStar = 0.;
//Take a final step to alphaStar
x = x0 + alphaStar * xdir;
subsys->setParams(x);
return alphaStar;
}
void free(VEC_pD &doublevec)
{
for (VEC_pD::iterator it = doublevec.begin();
it != doublevec.end(); ++it)
if (*it) delete *it;
doublevec.clear();
}
void free(std::vector<Constraint *> &constrvec)
{
for (std::vector<Constraint *>::iterator constr=constrvec.begin();
constr != constrvec.end(); ++constr) {
if (*constr) {
switch ((*constr)->getTypeId()) {
case Equal:
delete static_cast<ConstraintEqual *>(*constr);
break;
case Difference:
delete static_cast<ConstraintDifference *>(*constr);
break;
case P2PDistance:
delete static_cast<ConstraintP2PDistance *>(*constr);
break;
case P2PAngle:
delete static_cast<ConstraintP2PAngle *>(*constr);
break;
case P2LDistance:
delete static_cast<ConstraintP2LDistance *>(*constr);
break;
case PointOnLine:
delete static_cast<ConstraintPointOnLine *>(*constr);
break;
case Parallel:
delete static_cast<ConstraintParallel *>(*constr);
break;
case Perpendicular:
delete static_cast<ConstraintPerpendicular *>(*constr);
break;
case L2LAngle:
delete static_cast<ConstraintL2LAngle *>(*constr);
break;
case None:
default:
delete *constr;
}
}
}
constrvec.clear();
}
void free(std::vector<SubSystem *> &subsysvec)
{
for (std::vector<SubSystem *>::iterator it=subsysvec.begin();
it != subsysvec.end(); ++it)
if (*it) delete *it;
subsysvec.clear();
}
} //namespace GCS

View File

@@ -0,0 +1,149 @@
/***************************************************************************
* Copyright (c) Konstantinos Poulios (logari81@gmail.com) 2011 *
* *
* 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 *
* *
***************************************************************************/
#ifndef FREEGCS_GCS_H
#define FREEGCS_GCS_H
#include "SubSystem.h"
namespace GCS
{
///////////////////////////////////////
// Solver
///////////////////////////////////////
enum SolveStatus {
Success = 0, // Found a solution zeroing the error function
Converged = 1, // Found a solution minimizing the error function
Failed = 2 // Failed to find any solution
};
class System
{
// This is the main class. It holds all constraints and information
// about partitioning into subsystems and solution strategies
private:
std::vector<Constraint *> clist;
std::map<Constraint *,VEC_pD > c2p; // constraint to parameter adjacency list
std::map<double *,std::vector<Constraint *> > p2c; // parameter to constraint adjacency list
std::vector<SubSystem *> subsystems;
void clearSubSystems();
MAP_pD_D reference;
void clearReference();
void resetToReference();
MAP_pD_pD reductionmap; // for simplification of equality constraints
bool init;
public:
System();
System(std::vector<Constraint *> clist_);
~System();
void clear();
void clearByTag(int tagId);
int addConstraint(Constraint *constr);
void removeConstraint(Constraint *constr);
// basic constraints
int addConstraintEqual(double *param1, double *param2, int tagId=0);
int addConstraintDifference(double *param1, double *param2,
double *difference, int tagId=0);
int addConstraintP2PDistance(Point &p1, Point &p2, double *distance, int tagId=0);
int addConstraintP2PAngle(Point &p1, Point &p2, double *angle,
double incr_angle, int tagId=0);
int addConstraintP2PAngle(Point &p1, Point &p2, double *angle, int tagId=0);
int addConstraintP2LDistance(Point &p, Line &l, double *distance, int tagId=0);
int addConstraintPointOnLine(Point &p, Line &l, int tagId=0);
int addConstraintParallel(Line &l1, Line &l2, int tagId=0);
int addConstraintPerpendicular(Line &l1, Line &l2, int tagId=0);
int addConstraintPerpendicular(Point &l1p1, Point &l1p2,
Point &l2p1, Point &l2p2, int tagId=0);
int addConstraintL2LAngle(Line &l1, Line &l2, double *angle, int tagId=0);
int addConstraintL2LAngle(Point &l1p1, Point &l1p2, Point &l2p1, Point &l2p2,
double *angle, int tagId=0);
int addConstraintMidpointOnLine(Line &l1, Line &l2, int tagId=0);
int addConstraintMidpointOnLine(Point &l1p1, Point &l1p2, Point &l2p1, Point &l2p2,
int tagId=0);
// derived constraints
int addConstraintP2PCoincident(Point &p1, Point &p2, int tagId=0);
int addConstraintHorizontal(Line &l, int tagId=0);
int addConstraintHorizontal(Point &p1, Point &p2, int tagId=0);
int addConstraintVertical(Line &l, int tagId=0);
int addConstraintVertical(Point &p1, Point &p2, int tagId=0);
int addConstraintCoordinateX(Point &p, double *x, int tagId=0);
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 addConstraintPointOnArc(Point &p, Arc &a, int tagId=0);
int addConstraintTangent(Line &l, Circle &c, int tagId=0);
int addConstraintTangent(Line &l, Arc &a, 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 addConstraintCircleRadius(Circle &c, double *radius, 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 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);
void initSolution(VEC_pD &params);
int solve(int isFine=1);
int solve(VEC_pD &params, int isFine=1);
int solve(SubSystem *subsys, int isFine=1);
int solve(SubSystem *subsysA, SubSystem *subsysB, int isFine=1);
void getSubSystems(std::vector<SubSystem *> &subsysvec);
void applySolution();
bool isInit() const { return init; }
int diagnose(VEC_pD &params, VEC_I &conflicting);
};
///////////////////////////////////////
// BFGS Solver parameters
///////////////////////////////////////
#define XconvergenceRough 1e-8
#define XconvergenceFine 1e-10
#define smallF 1e-20
#define MaxIterations 100 //Note that the total number of iterations allowed is MaxIterations *xLength
///////////////////////////////////////
// Helper elements
///////////////////////////////////////
void free(VEC_pD &doublevec);
void free(std::vector<Constraint *> &constrvec);
void free(std::vector<SubSystem *> &subsysvec);
} //namespace GCS
#endif // FREEGCS_GCS_H

View File

@@ -0,0 +1,71 @@
/***************************************************************************
* Copyright (c) Konstantinos Poulios (logari81@gmail.com) 2011 *
* *
* 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 *
* *
***************************************************************************/
#ifndef FREEGCS_GEO_H
#define FREEGCS_GEO_H
namespace GCS
{
///////////////////////////////////////
// Geometries
///////////////////////////////////////
class Point
{
public:
Point(){x = 0; y = 0;}
double *x;
double *y;
};
class Line
{
public:
Line(){}
Point p1;
Point p2;
};
class Arc
{
public:
Arc(){startAngle=0;endAngle=0;rad=0;}
double *startAngle;
double *endAngle;
double *rad;
Point start;
Point end;
Point center;
};
class Circle
{
public:
Circle(){rad = 0;}
Point center;
double *rad;
};
} //namespace GCS
#endif // FREEGCS_GEO_H

View File

@@ -0,0 +1,18 @@
noinst_LTLIBRARIES=libfreegcs.la
libfreegcs_la_SOURCES = \
GCS.cpp \
GCS.h \
Util.h \
Geo.h \
Constraints.cpp \
Constraints.h \
SubSystem.cpp \
SubSystem.h \
qp_eq.cpp \
qp_eq.h
# set the include path found by configure
AM_CXXFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/Mod/Sketcher/App \
-I$(top_builddir)/src -I$(top_builddir)/src/Mod/Sketcher/App $(all_includes) \
-I$(EIGEN3_INC)

View File

@@ -0,0 +1,350 @@
/***************************************************************************
* Copyright (c) Konstantinos Poulios (logari81@gmail.com) 2011 *
* *
* 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 <iostream>
#include "SubSystem.h"
namespace GCS
{
// SubSystem
SubSystem::SubSystem(std::vector<Constraint *> &clist_, VEC_pD &params)
: clist(clist_)
{
MAP_pD_pD dummymap;
initialize(params, dummymap);
}
SubSystem::SubSystem(std::vector<Constraint *> &clist_, VEC_pD &params,
MAP_pD_pD &reductionmap)
: clist(clist_)
{
initialize(params, reductionmap);
}
SubSystem::~SubSystem()
{
}
void SubSystem::initialize(VEC_pD &params, MAP_pD_pD &reductionmap)
{
csize = clist.size();
// tmpplist will contain the subset of parameters from params that are
// relevant for the constraints listed in clist
VEC_pD tmpplist;
{
SET_pD s1(params.begin(), params.end());
SET_pD s2;
for (std::vector<Constraint *>::iterator constr=clist.begin();
constr != clist.end(); ++constr) {
(*constr)->revertParams(); // ensure that the constraint points to the original parameters
VEC_pD constr_params = (*constr)->params();
s2.insert(constr_params.begin(), constr_params.end());
}
std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(),
std::back_inserter(tmpplist) );
}
plist.clear();
MAP_pD_I rindex;
if (reductionmap.size() > 0) {
int i=0;
MAP_pD_I pindex;
for (VEC_pD::const_iterator itt=tmpplist.begin();
itt != tmpplist.end(); itt++) {
MAP_pD_pD::const_iterator itr = reductionmap.find(*itt);
if (itr != reductionmap.end()) {
MAP_pD_I::const_iterator itp = pindex.find(itr->second);
if (itp == pindex.end()) { // the reduction target is not in plist yet, so add it now
plist.push_back(itr->second);
rindex[itr->first] = i;
pindex[itr->second] = i;
i++;
}
else // the reduction target is already in plist, just inform rindex
rindex[itr->first] = itp->second;
}
else if (pindex.find(*itt) == pindex.end()) { // not in plist yet, so add it now
plist.push_back(*itt);
pindex[*itt] = i;
i++;
}
}
}
else
plist = tmpplist;
psize = plist.size();
pvals.resize(psize);
pmap.clear();
for (int j=0; j < psize; j++) {
pmap[plist[j]] = &pvals[j];
pvals[j] = *plist[j];
}
for (MAP_pD_I::const_iterator itr=rindex.begin(); itr != rindex.end(); ++itr)
pmap[itr->first] = &pvals[itr->second];
c2p.clear();
p2c.clear();
for (std::vector<Constraint *>::iterator constr=clist.begin();
constr != clist.end(); ++constr) {
(*constr)->revertParams(); // ensure that the constraint points to the original parameters
VEC_pD constr_params_orig = (*constr)->params();
SET_pD constr_params;
for (VEC_pD::const_iterator p=constr_params_orig.begin();
p != constr_params_orig.end(); ++p) {
MAP_pD_pD::const_iterator pmapfind = pmap.find(*p);
if (pmapfind != pmap.end())
constr_params.insert(pmapfind->second);
}
for (SET_pD::const_iterator p=constr_params.begin();
p != constr_params.end(); ++p) {
// jacobi.set(*constr, *p, 0.);
c2p[*constr].push_back(*p);
p2c[*p].push_back(*constr);
}
// (*constr)->redirectParams(pmap); // redirect parameters to pvec
}
}
void SubSystem::redirectParams()
{
// copying values to pvals
for (MAP_pD_pD::const_iterator p=pmap.begin();
p != pmap.end(); ++p)
*(p->second) = *(p->first);
// redirect constraints to point to pvals
for (std::vector<Constraint *>::iterator constr=clist.begin();
constr != clist.end(); ++constr) {
(*constr)->revertParams(); // this line will normally not be necessary
(*constr)->redirectParams(pmap);
}
}
void SubSystem::revertParams()
{
for (std::vector<Constraint *>::iterator constr=clist.begin();
constr != clist.end(); ++constr)
(*constr)->revertParams();
}
void SubSystem::getParamMap(MAP_pD_pD &pmapOut)
{
pmapOut = pmap;
}
void SubSystem::getParamList(VEC_pD &plistOut)
{
plistOut = plist;
}
void SubSystem::getParams(VEC_pD &params, Eigen::VectorXd &xOut)
{
if (xOut.size() != int(params.size()))
xOut.setZero(params.size());
for (int j=0; j < int(params.size()); j++) {
MAP_pD_pD::const_iterator
pmapfind = pmap.find(params[j]);
if (pmapfind != pmap.end())
xOut[j] = *(pmapfind->second);
}
}
void SubSystem::getParams(Eigen::VectorXd &xOut)
{
if (xOut.size() != psize)
xOut.setZero(psize);
for (int i=0; i < psize; i++)
xOut[i] = pvals[i];
}
void SubSystem::setParams(VEC_pD &params, Eigen::VectorXd &xIn)
{
assert(xIn.size() == int(params.size()));
for (int j=0; j < int(params.size()); j++) {
MAP_pD_pD::const_iterator
pmapfind = pmap.find(params[j]);
if (pmapfind != pmap.end())
*(pmapfind->second) = xIn[j];
}
}
void SubSystem::setParams(Eigen::VectorXd &xIn)
{
assert(xIn.size() == psize);
for (int i=0; i < psize; i++)
pvals[i] = xIn[i];
}
double SubSystem::error()
{
double err = 0.;
for (std::vector<Constraint *>::const_iterator constr=clist.begin();
constr != clist.end(); ++constr) {
double tmp = (*constr)->error();
err += tmp*tmp;
}
err *= 0.5;
return err;
}
void SubSystem::calcResidual(Eigen::VectorXd &r)
{
assert(r.size() == csize);
int i=0;
for (std::vector<Constraint *>::const_iterator constr=clist.begin();
constr != clist.end(); ++constr, i++) {
r[i] = (*constr)->error();
}
}
void SubSystem::calcResidual(Eigen::VectorXd &r, double &err)
{
assert(r.size() == csize);
int i=0;
err = 0.;
for (std::vector<Constraint *>::const_iterator constr=clist.begin();
constr != clist.end(); ++constr, i++) {
r[i] = (*constr)->error();
err += r[i]*r[i];
}
err *= 0.5;
}
/*
void SubSystem::calcJacobi()
{
assert(grad.size() != xsize);
for (MAP_pD_pD::const_iterator param=pmap.begin();
param != pmap.end(); ++param) {
// assert(p2c.find(param->second) != p2c.end());
std::vector<Constraint *> constrs=p2c[param->second];
for (std::vector<Constraint *>::const_iterator constr = constrs.begin();
constr != constrs.end(); ++constr)
jacobi.set(*constr,param->second,(*constr)->grad(param->second));
}
}
*/
void SubSystem::calcJacobi(VEC_pD &params, Eigen::MatrixXd &jacobi)
{
jacobi.setZero(csize, params.size());
for (int j=0; j < int(params.size()); j++) {
MAP_pD_pD::const_iterator
pmapfind = pmap.find(params[j]);
if (pmapfind != pmap.end())
for (int i=0; i < csize; i++)
jacobi(i,j) = clist[i]->grad(pmapfind->second);
}
}
void SubSystem::calcJacobi(Eigen::MatrixXd &jacobi)
{
calcJacobi(plist, jacobi);
}
void SubSystem::calcGrad(VEC_pD &params, Eigen::VectorXd &grad)
{
assert(grad.size() == int(params.size()));
grad.setZero();
for (int j=0; j < int(params.size()); j++) {
MAP_pD_pD::const_iterator
pmapfind = pmap.find(params[j]);
if (pmapfind != pmap.end()) {
// assert(p2c.find(pmapfind->second) != p2c.end());
std::vector<Constraint *> constrs=p2c[pmapfind->second];
for (std::vector<Constraint *>::const_iterator constr = constrs.begin();
constr != constrs.end(); ++constr)
grad[j] += (*constr)->error() * (*constr)->grad(pmapfind->second);
}
}
}
void SubSystem::calcGrad(Eigen::VectorXd &grad)
{
calcGrad(plist, grad);
}
double SubSystem::maxStep(VEC_pD &params, Eigen::VectorXd &xdir)
{
assert(xdir.size() == int(params.size()));
MAP_pD_D dir;
for (int j=0; j < int(params.size()); j++) {
MAP_pD_pD::const_iterator pmapfind = pmap.find(params[j]);
if (pmapfind != pmap.end())
dir[pmapfind->second] = xdir[j];
}
double alpha=1e10;
for (std::vector<Constraint *>::iterator constr=clist.begin();
constr != clist.end(); ++constr)
alpha = (*constr)->maxStep(dir, alpha);
return alpha;
}
double SubSystem::maxStep(Eigen::VectorXd &xdir)
{
return maxStep(plist, xdir);
}
void SubSystem::applySolution()
{
for (MAP_pD_pD::const_iterator it=pmap.begin();
it != pmap.end(); ++it)
*(it->first) = *(it->second);
}
void SubSystem::analyse(Eigen::MatrixXd &J, Eigen::MatrixXd &ker, Eigen::MatrixXd &img)
{
}
void SubSystem::report()
{
}
void SubSystem::printResidual()
{
Eigen::VectorXd r(csize);
int i=0;
double err = 0.;
for (std::vector<Constraint *>::const_iterator constr=clist.begin();
constr != clist.end(); ++constr, i++) {
r[i] = (*constr)->error();
err += r[i]*r[i];
}
err *= 0.5;
std::cout << "Residual r = " << r.transpose() << std::endl;
std::cout << "Residual err = " << err << std::endl;
}
} //namespace GCS

View File

@@ -0,0 +1,89 @@
/***************************************************************************
* Copyright (c) Konstantinos Poulios (logari81@gmail.com) 2011 *
* *
* 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 *
* *
***************************************************************************/
#ifndef FREEGCS_SUBSYSTEM_H
#define FREEGCS_SUBSYSTEM_H
#undef min
#undef max
#include <Eigen/Core>
#include "Constraints.h"
namespace GCS
{
class SubSystem
{
private:
int psize, csize;
std::vector<Constraint *> clist;
VEC_pD plist; // pointers to the original parameters
MAP_pD_pD pmap; // redirection map from the original parameters to pvals
VEC_D pvals; // current variables vector (psize)
// JacobianMatrix jacobi; // jacobi matrix of the residuals
std::map<Constraint *,VEC_pD > c2p; // constraint to parameter adjacency list
std::map<double *,std::vector<Constraint *> > p2c; // parameter to constraint adjacency list
void initialize(VEC_pD &params, MAP_pD_pD &reductionmap); // called by the constructors
public:
SubSystem(std::vector<Constraint *> &clist_, VEC_pD &params);
SubSystem(std::vector<Constraint *> &clist_, VEC_pD &params,
MAP_pD_pD &reductionmap);
~SubSystem();
int pSize() { return psize; };
int cSize() { return csize; };
void redirectParams();
void revertParams();
void getParamMap(MAP_pD_pD &pmapOut);
void getParamList(VEC_pD &plistOut);
void getParams(VEC_pD &params, Eigen::VectorXd &xOut);
void getParams(Eigen::VectorXd &xOut);
void setParams(VEC_pD &params, Eigen::VectorXd &xIn);
void setParams(Eigen::VectorXd &xIn);
double error();
void calcResidual(Eigen::VectorXd &r);
void calcResidual(Eigen::VectorXd &r, double &err);
void calcJacobi(VEC_pD &params, Eigen::MatrixXd &jacobi);
void calcJacobi(Eigen::MatrixXd &jacobi);
void calcGrad(VEC_pD &params, Eigen::VectorXd &grad);
void calcGrad(Eigen::VectorXd &grad);
double maxStep(VEC_pD &params, Eigen::VectorXd &xdir);
double maxStep(Eigen::VectorXd &xdir);
void applySolution();
void analyse(Eigen::MatrixXd &J, Eigen::MatrixXd &ker, Eigen::MatrixXd &img);
void report();
void printResidual();
};
double lineSearch(SubSystem *subsys, Eigen::VectorXd &xdir);
} //namespace GCS
#endif // FREEGCS_SUBSYSTEM_H

View File

@@ -0,0 +1,47 @@
/***************************************************************************
* Copyright (c) Konstantinos Poulios (logari81@gmail.com) 2011 *
* *
* 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 *
* *
***************************************************************************/
#ifndef FREEGCS_UTIL_H
#define FREEGCS_UTIL_H
#include <vector>
#include <map>
#include <set>
namespace GCS
{
typedef std::vector<double *> VEC_pD;
typedef std::vector<double> VEC_D;
typedef std::vector<int> VEC_I;
typedef std::map<double *, double *> MAP_pD_pD;
typedef std::map<double *, double> MAP_pD_D;
typedef std::map<double *, int> MAP_pD_I;
typedef std::set<double *> SET_pD;
typedef std::set<int> SET_I;
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
} //namespace GCS
#endif // FREEGCS_UTIL_H

View File

@@ -0,0 +1,65 @@
/***************************************************************************
* Copyright (c) Konstantinos Poulios (logari81@gmail.com) 2011 *
* *
* 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 <iostream>
#include <Eigen/QR>
using namespace Eigen;
// minimizes ( 0.5 * x^T * H * x + g^T * x ) under the condition ( A*x + c = 0 )
// it returns the solution in x, the row-space of A in Y, and the null space of A in Z
int qp_eq(MatrixXd &H, VectorXd &g, MatrixXd &A, VectorXd &c,
VectorXd &x, MatrixXd &Y, MatrixXd &Z)
{
FullPivHouseholderQR<MatrixXd> qrAT(A.transpose());
MatrixXd Q = qrAT.matrixQ ();
size_t params_num = qrAT.rows();
size_t constr_num = qrAT.cols();
size_t rank = qrAT.rank();
if (rank != constr_num || constr_num > params_num)
return -1;
// A^T = Q*R*P^T = Q1*R1*P^T
// Q = [Q1,Q2], R=[R1;0]
// Y = Q1 * inv(R^T) * P^T
// Z = Q2
Y = qrAT.matrixQR().topRows(constr_num)
.triangularView<Upper>()
.transpose()
.solve<OnTheRight>(Q.leftCols(rank))
* qrAT.colsPermutation().transpose();
if (params_num == rank)
x = - Y * c;
else {
Z = Q.rightCols(params_num-rank);
MatrixXd ZTHZ = Z.transpose() * H * Z;
VectorXd rhs = Z.transpose() * (H * Y * c - g);
VectorXd y = ZTHZ.colPivHouseholderQr().solve(rhs);
x = - Y * c + Z * y;
}
return 0;
}

View File

@@ -0,0 +1,25 @@
/***************************************************************************
* Copyright (c) Konstantinos Poulios (logari81@gmail.com) 2011 *
* *
* 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 <Eigen/Dense>
int qp_eq(Eigen::MatrixXd &H, Eigen::VectorXd &g, Eigen::MatrixXd &A, Eigen::VectorXd &c,
Eigen::VectorXd &x, Eigen::MatrixXd &Y, Eigen::MatrixXd &Z);