======================================================================== Until now BSpline poles were circles relying on physical length units. This lead to several problems: - While the BSpline weight follows the circle size, weights do not have length units, but are adimensinal - As representation of the BSpline depends on the physical size of the circle, the numerical value to be set to a pole circle differs from the numerical value of the weight. The present commit: 1. Separates pole circle representation (physical size), from the numerical value used in the radius constraint, so that the value in the constraint is the weight, the value representation is a factor of the weight value (in this commit is getScaleFactor(), but this will change in the next commit). Dragging accounts for this scale factor too. 2. While Radius constraint button is used to constraint a B-Spline weight as before, this creates a Weight constraint, which is a new type of constraint. This is done so that the value is truly adimensional and is so presented in all kind of editors that rely on the units indicated by the constraint. It is obviously also shown as adimensional (thus without units), in the 3D view and in the datum dialogs. 3. Because the circle of the pole of a B-Spline is not a geometric circle, but a graphical representation of the pole and how it affects the corresponding B-Spline, constraint creation commands are limited so that no point on object, tangent, perpendicular or SnellLaw constraints can be created on a B-Spline weight circle. This is also the case for the Diameter constraint, which won't accept the circle. Equality constraints work either on only circles or only weights, but not on a mixture of them. Bonus: This commit fixes a bug in master, that using the select equality constraint then click in two geometric elements mode, you could make a circle equal to an ellipse resulting in malformed solver constraints.
220 lines
7.9 KiB
C++
220 lines
7.9 KiB
C++
/***************************************************************************
|
|
* 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 <cmath>
|
|
# include <QDateTime>
|
|
#endif
|
|
|
|
#include <Base/Writer.h>
|
|
#include <Base/Reader.h>
|
|
#include <Base/Tools.h>
|
|
#include <App/Property.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()
|
|
: Value(0.0),
|
|
Type(None),
|
|
AlignmentType(Undef),
|
|
Name(""),
|
|
First(GeoUndef),
|
|
FirstPos(none),
|
|
Second(GeoUndef),
|
|
SecondPos(none),
|
|
Third(GeoUndef),
|
|
ThirdPos(none),
|
|
LabelDistance(10.f),
|
|
LabelPosition(0.f),
|
|
isDriving(true),
|
|
InternalAlignmentIndex(-1),
|
|
isInVirtualSpace(false),
|
|
isActive(true)
|
|
{
|
|
// Initialize a random number generator, to avoid Valgrind false positives.
|
|
static boost::mt19937 ran;
|
|
static bool seeded = false;
|
|
|
|
if (!seeded) {
|
|
ran.seed(QDateTime::currentMSecsSinceEpoch() & 0xffffffff);
|
|
seeded = true;
|
|
}
|
|
static boost::uuids::basic_random_generator<boost::mt19937> gen(&ran);
|
|
|
|
tag = gen();
|
|
}
|
|
|
|
Constraint *Constraint::clone(void) const
|
|
{
|
|
return new Constraint(*this);
|
|
}
|
|
|
|
Constraint *Constraint::copy(void) const
|
|
{
|
|
Constraint *temp = new Constraint();
|
|
temp->Value = this->Value;
|
|
temp->Type = this->Type;
|
|
temp->AlignmentType = this->AlignmentType;
|
|
temp->Name = this->Name;
|
|
temp->First = this->First;
|
|
temp->FirstPos = this->FirstPos;
|
|
temp->Second = this->Second;
|
|
temp->SecondPos = this->SecondPos;
|
|
temp->Third = this->Third;
|
|
temp->ThirdPos = this->ThirdPos;
|
|
temp->LabelDistance = this->LabelDistance;
|
|
temp->LabelPosition = this->LabelPosition;
|
|
temp->isDriving = this->isDriving;
|
|
temp->InternalAlignmentIndex = this->InternalAlignmentIndex;
|
|
temp->isInVirtualSpace = this->isInVirtualSpace;
|
|
temp->isActive = this->isActive;
|
|
// Do not copy tag, otherwise it is considered a clone, and a "rename" by the expression engine.
|
|
return temp;
|
|
}
|
|
|
|
PyObject *Constraint::getPyObject(void)
|
|
{
|
|
return new ConstraintPy(new Constraint(*this));
|
|
}
|
|
|
|
Quantity Constraint::getPresentationValue() const
|
|
{
|
|
Quantity quantity;
|
|
switch (Type) {
|
|
case Distance:
|
|
case Radius:
|
|
case Diameter:
|
|
case DistanceX:
|
|
case DistanceY:
|
|
quantity.setValue(Value);
|
|
quantity.setUnit(Unit::Length);
|
|
break;
|
|
case Angle:
|
|
quantity.setValue(toDegrees<double>(Value));
|
|
quantity.setUnit(Unit::Angle);
|
|
break;
|
|
case SnellsLaw:
|
|
case Weight:
|
|
quantity.setValue(Value);
|
|
break;
|
|
default:
|
|
quantity.setValue(Value);
|
|
break;
|
|
}
|
|
|
|
QuantityFormat format = quantity.getFormat();
|
|
format.option = QuantityFormat::None;
|
|
format.format = QuantityFormat::Default;
|
|
format.precision = 6; // QString's default
|
|
quantity.setFormat(format);
|
|
return quantity;
|
|
}
|
|
|
|
unsigned int Constraint::getMemSize (void) const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void Constraint::Save (Writer &writer) const
|
|
{
|
|
std::string encodeName = encodeAttribute(Name);
|
|
writer.Stream() << writer.ind() << "<Constrain "
|
|
<< "Name=\"" << encodeName << "\" "
|
|
<< "Type=\"" << (int)Type << "\" ";
|
|
if(this->Type==InternalAlignment)
|
|
writer.Stream()
|
|
<< "InternalAlignmentType=\"" << (int)AlignmentType << "\" "
|
|
<< "InternalAlignmentIndex=\"" << InternalAlignmentIndex << "\" ";
|
|
writer.Stream()
|
|
<< "Value=\"" << Value << "\" "
|
|
<< "First=\"" << First << "\" "
|
|
<< "FirstPos=\"" << (int) FirstPos << "\" "
|
|
<< "Second=\"" << Second << "\" "
|
|
<< "SecondPos=\"" << (int) SecondPos << "\" "
|
|
<< "Third=\"" << Third << "\" "
|
|
<< "ThirdPos=\"" << (int) ThirdPos << "\" "
|
|
<< "LabelDistance=\"" << LabelDistance << "\" "
|
|
<< "LabelPosition=\"" << LabelPosition << "\" "
|
|
<< "IsDriving=\"" << (int)isDriving << "\" "
|
|
<< "IsInVirtualSpace=\"" << (int)isInVirtualSpace << "\" "
|
|
<< "IsActive=\"" << (int)isActive << "\" />"
|
|
|
|
<< 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");
|
|
|
|
if(this->Type==InternalAlignment) {
|
|
AlignmentType = (InternalAlignmentType) reader.getAttributeAsInteger("InternalAlignmentType");
|
|
|
|
if (reader.hasAttribute("InternalAlignmentIndex"))
|
|
InternalAlignmentIndex = reader.getAttributeAsInteger("InternalAlignmentIndex");
|
|
}
|
|
else {
|
|
AlignmentType = Undef;
|
|
}
|
|
|
|
// 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");
|
|
|
|
if (reader.hasAttribute("LabelPosition"))
|
|
LabelPosition = (float)reader.getAttributeAsFloat("LabelPosition");
|
|
|
|
if (reader.hasAttribute("IsDriving"))
|
|
isDriving = reader.getAttributeAsInteger("IsDriving") ? true : false;
|
|
|
|
if (reader.hasAttribute("IsInVirtualSpace"))
|
|
isInVirtualSpace = reader.getAttributeAsInteger("IsInVirtualSpace") ? true : false;
|
|
|
|
if (reader.hasAttribute("IsActive"))
|
|
isActive = reader.getAttributeAsInteger("IsActive") ? true : false;
|
|
}
|