+ 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:
89
src/Mod/Sketcher/App/AppSketcher.cpp
Normal file
89
src/Mod/Sketcher/App/AppSketcher.cpp
Normal 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());
|
||||
}
|
||||
134
src/Mod/Sketcher/App/AppSketcherPy.cpp
Normal file
134
src/Mod/Sketcher/App/AppSketcherPy.cpp
Normal 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 */
|
||||
};
|
||||
126
src/Mod/Sketcher/App/CMakeLists.txt
Normal file
126
src/Mod/Sketcher/App/CMakeLists.txt
Normal 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)
|
||||
126
src/Mod/Sketcher/App/Constraint.cpp
Normal file
126
src/Mod/Sketcher/App/Constraint.cpp
Normal 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");
|
||||
}
|
||||
91
src/Mod/Sketcher/App/Constraint.h
Normal file
91
src/Mod/Sketcher/App/Constraint.h
Normal 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
|
||||
32
src/Mod/Sketcher/App/ConstraintPy.xml
Normal file
32
src/Mod/Sketcher/App/ConstraintPy.xml
Normal 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>
|
||||
342
src/Mod/Sketcher/App/ConstraintPyImp.cpp
Normal file
342
src/Mod/Sketcher/App/ConstraintPyImp.cpp
Normal 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;
|
||||
}
|
||||
108
src/Mod/Sketcher/App/Makefile.am
Normal file
108
src/Mod/Sketcher/App/Makefile.am
Normal 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
|
||||
|
||||
24
src/Mod/Sketcher/App/PreCompiled.cpp
Normal file
24
src/Mod/Sketcher/App/PreCompiled.cpp
Normal 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"
|
||||
60
src/Mod/Sketcher/App/PreCompiled.h
Normal file
60
src/Mod/Sketcher/App/PreCompiled.h
Normal 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
|
||||
|
||||
195
src/Mod/Sketcher/App/PropertyConstraintList.cpp
Normal file
195
src/Mod/Sketcher/App/PropertyConstraintList.cpp
Normal 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;
|
||||
}
|
||||
95
src/Mod/Sketcher/App/PropertyConstraintList.h
Normal file
95
src/Mod/Sketcher/App/PropertyConstraintList.h
Normal 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
|
||||
1662
src/Mod/Sketcher/App/Sketch.cpp
Normal file
1662
src/Mod/Sketcher/App/Sketch.cpp
Normal file
File diff suppressed because it is too large
Load Diff
222
src/Mod/Sketcher/App/Sketch.h
Normal file
222
src/Mod/Sketcher/App/Sketch.h
Normal 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
|
||||
1016
src/Mod/Sketcher/App/SketchObject.cpp
Normal file
1016
src/Mod/Sketcher/App/SketchObject.cpp
Normal file
File diff suppressed because it is too large
Load Diff
134
src/Mod/Sketcher/App/SketchObject.h
Normal file
134
src/Mod/Sketcher/App/SketchObject.h
Normal 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
|
||||
104
src/Mod/Sketcher/App/SketchObjectPy.xml
Normal file
104
src/Mod/Sketcher/App/SketchObjectPy.xml
Normal 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>
|
||||
324
src/Mod/Sketcher/App/SketchObjectPyImp.cpp
Normal file
324
src/Mod/Sketcher/App/SketchObjectPyImp.cpp
Normal 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;
|
||||
}
|
||||
58
src/Mod/Sketcher/App/SketchObjectSF.cpp
Normal file
58
src/Mod/Sketcher/App/SketchObjectSF.cpp
Normal 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;
|
||||
}
|
||||
67
src/Mod/Sketcher/App/SketchObjectSF.h
Normal file
67
src/Mod/Sketcher/App/SketchObjectSF.h
Normal 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
|
||||
17
src/Mod/Sketcher/App/SketchObjectSFPy.xml
Normal file
17
src/Mod/Sketcher/App/SketchObjectSFPy.xml
Normal 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>
|
||||
51
src/Mod/Sketcher/App/SketchObjectSFPyImp.cpp
Normal file
51
src/Mod/Sketcher/App/SketchObjectSFPyImp.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
79
src/Mod/Sketcher/App/SketchPy.xml
Normal file
79
src/Mod/Sketcher/App/SketchPy.xml
Normal 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>
|
||||
179
src/Mod/Sketcher/App/SketchPyImp.cpp
Normal file
179
src/Mod/Sketcher/App/SketchPyImp.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
774
src/Mod/Sketcher/App/freegcs/Constraints.cpp
Normal file
774
src/Mod/Sketcher/App/freegcs/Constraints.cpp
Normal 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
|
||||
267
src/Mod/Sketcher/App/freegcs/Constraints.h
Normal file
267
src/Mod/Sketcher/App/freegcs/Constraints.h
Normal 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
|
||||
954
src/Mod/Sketcher/App/freegcs/GCS.cpp
Normal file
954
src/Mod/Sketcher/App/freegcs/GCS.cpp
Normal 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 ¶ms)
|
||||
{
|
||||
// - 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 ¶ms, 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 ¶ms, 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
|
||||
149
src/Mod/Sketcher/App/freegcs/GCS.h
Normal file
149
src/Mod/Sketcher/App/freegcs/GCS.h
Normal 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 ¶ms);
|
||||
|
||||
int solve(int isFine=1);
|
||||
int solve(VEC_pD ¶ms, 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 ¶ms, 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
|
||||
71
src/Mod/Sketcher/App/freegcs/Geo.h
Normal file
71
src/Mod/Sketcher/App/freegcs/Geo.h
Normal 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
|
||||
18
src/Mod/Sketcher/App/freegcs/Makefile.am
Normal file
18
src/Mod/Sketcher/App/freegcs/Makefile.am
Normal 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)
|
||||
350
src/Mod/Sketcher/App/freegcs/SubSystem.cpp
Normal file
350
src/Mod/Sketcher/App/freegcs/SubSystem.cpp
Normal 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 ¶ms)
|
||||
: clist(clist_)
|
||||
{
|
||||
MAP_pD_pD dummymap;
|
||||
initialize(params, dummymap);
|
||||
}
|
||||
|
||||
SubSystem::SubSystem(std::vector<Constraint *> &clist_, VEC_pD ¶ms,
|
||||
MAP_pD_pD &reductionmap)
|
||||
: clist(clist_)
|
||||
{
|
||||
initialize(params, reductionmap);
|
||||
}
|
||||
|
||||
SubSystem::~SubSystem()
|
||||
{
|
||||
}
|
||||
|
||||
void SubSystem::initialize(VEC_pD ¶ms, 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 ¶ms, 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 ¶ms, 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 ¶ms, 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 ¶ms, 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 ¶ms, 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
|
||||
89
src/Mod/Sketcher/App/freegcs/SubSystem.h
Normal file
89
src/Mod/Sketcher/App/freegcs/SubSystem.h
Normal 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 ¶ms, MAP_pD_pD &reductionmap); // called by the constructors
|
||||
public:
|
||||
SubSystem(std::vector<Constraint *> &clist_, VEC_pD ¶ms);
|
||||
SubSystem(std::vector<Constraint *> &clist_, VEC_pD ¶ms,
|
||||
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 ¶ms, Eigen::VectorXd &xOut);
|
||||
void getParams(Eigen::VectorXd &xOut);
|
||||
void setParams(VEC_pD ¶ms, 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 ¶ms, Eigen::MatrixXd &jacobi);
|
||||
void calcJacobi(Eigen::MatrixXd &jacobi);
|
||||
void calcGrad(VEC_pD ¶ms, Eigen::VectorXd &grad);
|
||||
void calcGrad(Eigen::VectorXd &grad);
|
||||
|
||||
double maxStep(VEC_pD ¶ms, 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
|
||||
47
src/Mod/Sketcher/App/freegcs/Util.h
Normal file
47
src/Mod/Sketcher/App/freegcs/Util.h
Normal 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
|
||||
65
src/Mod/Sketcher/App/freegcs/qp_eq.cpp
Normal file
65
src/Mod/Sketcher/App/freegcs/qp_eq.cpp
Normal 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;
|
||||
}
|
||||
25
src/Mod/Sketcher/App/freegcs/qp_eq.h
Normal file
25
src/Mod/Sketcher/App/freegcs/qp_eq.h
Normal 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);
|
||||
Reference in New Issue
Block a user