Core: Add App::LocalCoordinateSystem.
Most of App::Origin is moved into this sub class of App::Origin. Add App::Point. Change graphics of the planes/axis. Remove scale-by-content behavior and make it fixed size on screen.
This commit is contained in:
@@ -2150,6 +2150,8 @@ void Application::initTypes()
|
||||
App::DatumElement ::init();
|
||||
App::Plane ::init();
|
||||
App::Line ::init();
|
||||
App::Point ::init();
|
||||
App::LocalCoordinateSystem ::init();
|
||||
App::Part ::init();
|
||||
App::Origin ::init();
|
||||
App::Link ::init();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.net> *
|
||||
* Copyright (c) 2015 Alexander Golubev (Fat-Zer) <fatzer2@gmail.com> *
|
||||
* Copyright (c) 2024 Ondsel (PL Boyer) <development@ondsel.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
@@ -21,42 +23,318 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
#include <App/Document.h>
|
||||
#include <Base/Exception.h>
|
||||
#include <Base/Placement.h>
|
||||
|
||||
#include "Datums.h"
|
||||
#include "Document.h"
|
||||
#include "Origin.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
using namespace App;
|
||||
|
||||
PROPERTY_SOURCE(App::DatumElement, App::GeoFeature)
|
||||
PROPERTY_SOURCE(App::Plane, App::DatumElement)
|
||||
PROPERTY_SOURCE(App::Line, App::DatumElement)
|
||||
PROPERTY_SOURCE(App::Point, App::DatumElement)
|
||||
PROPERTY_SOURCE(App::LocalCoordinateSystem, App::GeoFeature)
|
||||
|
||||
DatumElement::DatumElement()
|
||||
DatumElement::DatumElement(bool hideRole)
|
||||
{
|
||||
ADD_PROPERTY_TYPE(Role, (""), 0, App::Prop_ReadOnly, "Role of the feature in the Origin");
|
||||
ADD_PROPERTY_TYPE(Role,
|
||||
(""),
|
||||
0,
|
||||
App::Prop_ReadOnly,
|
||||
"Role of the datum in the local coordinate system.");
|
||||
|
||||
// Set placement to read-only
|
||||
Placement.setStatus(Property::Hidden, true);
|
||||
// The role is hidden by default. It is visible only when the datum is in a LCS
|
||||
if (hideRole) {
|
||||
Role.setStatus(Property::Hidden, true);
|
||||
}
|
||||
}
|
||||
|
||||
DatumElement::~DatumElement() = default;
|
||||
|
||||
Origin* DatumElement::getOrigin()
|
||||
bool DatumElement::getCameraAlignmentDirection(Base::Vector3d& direction, const char* subname) const
|
||||
{
|
||||
Q_UNUSED(subname);
|
||||
Placement.getValue().getRotation().multVec(Base::Vector3d(0., 0., 1.), direction);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
App::LocalCoordinateSystem* DatumElement::getLCS()
|
||||
{
|
||||
auto inList = getInList();
|
||||
for (auto* obj : inList) {
|
||||
auto* lcs = dynamic_cast<App::LocalCoordinateSystem*>(obj);
|
||||
if (lcs) {
|
||||
return lcs;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool DatumElement::isOriginFeature()
|
||||
{
|
||||
auto lcs = getLCS();
|
||||
return lcs ? lcs->isOrigin() : false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
LocalCoordinateSystem::LocalCoordinateSystem()
|
||||
: extension(this)
|
||||
{
|
||||
ADD_PROPERTY_TYPE(OriginFeatures,
|
||||
(nullptr),
|
||||
0,
|
||||
App::Prop_Hidden,
|
||||
"Axis and baseplanes controlled by the LCS");
|
||||
|
||||
setStatus(App::NoAutoExpand, true);
|
||||
extension.initExtension(this);
|
||||
}
|
||||
|
||||
|
||||
LocalCoordinateSystem::~LocalCoordinateSystem() = default;
|
||||
|
||||
bool LocalCoordinateSystem::getCameraAlignmentDirection(Base::Vector3d& direction,
|
||||
const char* subname) const
|
||||
{
|
||||
Q_UNUSED(subname);
|
||||
Placement.getValue().getRotation().multVec(Base::Vector3d(0., 0., 1.), direction);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
App::DatumElement* LocalCoordinateSystem::getDatumElement(const char* role) const
|
||||
{
|
||||
const auto& features = OriginFeatures.getValues();
|
||||
auto featIt = std::find_if(features.begin(), features.end(), [role](App::DocumentObject* obj) {
|
||||
return obj->isDerivedFrom(App::DatumElement::getClassTypeId())
|
||||
&& strcmp(static_cast<App::DatumElement*>(obj)->Role.getValue(), role) == 0;
|
||||
});
|
||||
if (featIt != features.end()) {
|
||||
return static_cast<App::DatumElement*>(*featIt);
|
||||
}
|
||||
std::stringstream err;
|
||||
err << "LocalCoordinateSystem \"" << getFullName() << "\" doesn't contain feature with role \""
|
||||
<< role << '"';
|
||||
throw Base::RuntimeError(err.str().c_str());
|
||||
}
|
||||
|
||||
App::Line* LocalCoordinateSystem::getAxis(const char* role) const
|
||||
{
|
||||
App::DatumElement* feat = getDatumElement(role);
|
||||
if (feat->isDerivedFrom(App::Line::getClassTypeId())) {
|
||||
return static_cast<App::Line*>(feat);
|
||||
}
|
||||
std::stringstream err;
|
||||
err << "LocalCoordinateSystem \"" << getFullName() << "\" contains bad Axis object for role \""
|
||||
<< role << '"';
|
||||
throw Base::RuntimeError(err.str().c_str());
|
||||
}
|
||||
|
||||
App::Plane* LocalCoordinateSystem::getPlane(const char* role) const
|
||||
{
|
||||
App::DatumElement* feat = getDatumElement(role);
|
||||
if (feat->isDerivedFrom(App::Plane::getClassTypeId())) {
|
||||
return static_cast<App::Plane*>(feat);
|
||||
}
|
||||
std::stringstream err;
|
||||
err << "LocalCoordinateSystem \"" << getFullName() << "\" contains bad Plane object for role \""
|
||||
<< role << '"';
|
||||
throw Base::RuntimeError(err.str().c_str());
|
||||
}
|
||||
|
||||
App::Point* LocalCoordinateSystem::getPoint(const char* role) const
|
||||
{
|
||||
App::DatumElement* feat = getDatumElement(role);
|
||||
if (feat->isDerivedFrom(App::Point::getClassTypeId())) {
|
||||
return static_cast<App::Point*>(feat);
|
||||
}
|
||||
std::stringstream err;
|
||||
err << "LocalCoordinateSystem \"" << getFullName() << "\" contains bad Point object for role \""
|
||||
<< role << '"';
|
||||
throw Base::RuntimeError(err.str().c_str());
|
||||
}
|
||||
|
||||
bool LocalCoordinateSystem::hasObject(const DocumentObject* obj) const
|
||||
{
|
||||
const auto& features = OriginFeatures.getValues();
|
||||
return std::find(features.begin(), features.end(), obj) != features.end();
|
||||
}
|
||||
|
||||
short LocalCoordinateSystem::mustExecute() const
|
||||
{
|
||||
if (OriginFeatures.isTouched()) {
|
||||
return 1;
|
||||
}
|
||||
return DocumentObject::mustExecute();
|
||||
}
|
||||
|
||||
App::DocumentObjectExecReturn* LocalCoordinateSystem::execute()
|
||||
{
|
||||
try { // try to find all base axis and planes in the origin
|
||||
for (const char* role : AxisRoles) {
|
||||
App::Line* axis = getAxis(role);
|
||||
assert(axis);
|
||||
(void)axis;
|
||||
}
|
||||
for (const char* role : PlaneRoles) {
|
||||
App::Plane* plane = getPlane(role);
|
||||
assert(plane);
|
||||
(void)plane;
|
||||
}
|
||||
}
|
||||
catch (const Base::Exception& ex) {
|
||||
setError();
|
||||
return new App::DocumentObjectExecReturn(ex.what());
|
||||
}
|
||||
|
||||
return DocumentObject::execute();
|
||||
}
|
||||
|
||||
const std::vector<LocalCoordinateSystem::SetupData>& LocalCoordinateSystem::getSetupData()
|
||||
{
|
||||
static const std::vector<SetupData> setupData = {
|
||||
// clang-format off
|
||||
{App::Line::getClassTypeId(), AxisRoles[0], tr("X-axis"), Base::Rotation()},
|
||||
{App::Line::getClassTypeId(), AxisRoles[1], tr("Y-axis"), Base::Rotation(Base::Vector3d(1, 1, 1), M_PI * 2 / 3)},
|
||||
{App::Line::getClassTypeId(), AxisRoles[2], tr("Z-axis"), Base::Rotation(Base::Vector3d(1,-1, 1), M_PI * 2 / 3)},
|
||||
{App::Plane::getClassTypeId(), PlaneRoles[0], tr("XY-plane"), Base::Rotation()},
|
||||
{App::Plane::getClassTypeId(), PlaneRoles[1], tr("XZ-plane"), Base::Rotation(1.0, 0.0, 0.0, 1.0)},
|
||||
{App::Plane::getClassTypeId(), PlaneRoles[2], tr("YZ-plane"), Base::Rotation(Base::Vector3d(1, 1, 1), M_PI * 2 / 3)},
|
||||
{App::Point::getClassTypeId(), PointRoles[0], tr("Origin"), Base::Rotation()}
|
||||
// clang-format on
|
||||
};
|
||||
return setupData;
|
||||
}
|
||||
|
||||
DatumElement* LocalCoordinateSystem::createDatum(SetupData& data)
|
||||
{
|
||||
App::Document* doc = getDocument();
|
||||
auto origins = doc->getObjectsOfType(App::Origin::getClassTypeId());
|
||||
std::string objName = doc->getUniqueObjectName(data.role);
|
||||
App::DocumentObject* featureObj = doc->addObject(data.type.getName(), objName.c_str());
|
||||
|
||||
auto originIt = std::find_if(origins.begin(), origins.end(), [this](DocumentObject* origin) {
|
||||
assert(origin->isDerivedFrom(App::Origin::getClassTypeId()));
|
||||
return static_cast<App::Origin*>(origin)->hasObject(this);
|
||||
});
|
||||
if (originIt == origins.end()) {
|
||||
return nullptr;
|
||||
assert(featureObj && featureObj->isDerivedFrom(App::DatumElement::getClassTypeId()));
|
||||
|
||||
QByteArray byteArray = data.label.toUtf8();
|
||||
featureObj->Label.setValue(byteArray.constData());
|
||||
|
||||
auto* feature = static_cast<App::DatumElement*>(featureObj);
|
||||
feature->Placement.setValue(Base::Placement(Base::Vector3d(), data.rot));
|
||||
feature->Role.setValue(data.role);
|
||||
|
||||
feature->Placement.setStatus(Property::Hidden, true);
|
||||
return feature;
|
||||
}
|
||||
|
||||
LocalCoordinateSystem::SetupData LocalCoordinateSystem::getData(const char* role)
|
||||
{
|
||||
const auto& setupData = getSetupData();
|
||||
for (auto data : setupData) {
|
||||
if (std::strcmp(role, data.role) == 0) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert((*originIt)->isDerivedFrom(App::Origin::getClassTypeId()));
|
||||
return static_cast<App::Origin*>(*originIt);
|
||||
return LocalCoordinateSystem::SetupData();
|
||||
}
|
||||
|
||||
void LocalCoordinateSystem::setupObject()
|
||||
{
|
||||
std::vector<App::DocumentObject*> links;
|
||||
const auto& setupData = getSetupData();
|
||||
for (auto data : setupData) {
|
||||
links.push_back(createDatum(data));
|
||||
}
|
||||
|
||||
OriginFeatures.setValues(links);
|
||||
}
|
||||
|
||||
void LocalCoordinateSystem::unsetupObject()
|
||||
{
|
||||
const auto& objsLnk = OriginFeatures.getValues();
|
||||
// Copy to set to assert we won't call method more then one time for each object
|
||||
std::set<App::DocumentObject*> objs(objsLnk.begin(), objsLnk.end());
|
||||
// Remove all controlled objects
|
||||
for (auto obj : objs) {
|
||||
// Check that previous deletes didn't indirectly remove one of our objects
|
||||
const auto& objsLnk = OriginFeatures.getValues();
|
||||
if (std::find(objsLnk.begin(), objsLnk.end(), obj) != objsLnk.end()) {
|
||||
if (!obj->isRemoving()) {
|
||||
obj->getDocument()->removeObject(obj->getNameInDocument());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
LocalCoordinateSystem::LCSExtension::LCSExtension(LocalCoordinateSystem* obj)
|
||||
: obj(obj)
|
||||
{
|
||||
Group.setStatus(Property::Transient, true);
|
||||
}
|
||||
|
||||
void LocalCoordinateSystem::LCSExtension::initExtension(ExtensionContainer* obj)
|
||||
{
|
||||
App::GroupExtension::initExtension(obj);
|
||||
}
|
||||
|
||||
bool LocalCoordinateSystem::LCSExtension::extensionGetSubObject(DocumentObject*& ret,
|
||||
const char* subname,
|
||||
PyObject** pyobj,
|
||||
Base::Matrix4D* mat,
|
||||
bool,
|
||||
int depth) const
|
||||
{
|
||||
if (!subname || subname[0] == '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// mapping of object name to role name
|
||||
std::string name(subname);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (name.rfind(LocalCoordinateSystem::AxisRoles[i], 0) == 0) {
|
||||
name = LocalCoordinateSystem::AxisRoles[i];
|
||||
break;
|
||||
}
|
||||
if (name.rfind(LocalCoordinateSystem::PlaneRoles[i], 0) == 0) {
|
||||
name = LocalCoordinateSystem::PlaneRoles[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (name.rfind(LocalCoordinateSystem::PointRoles[0], 0) == 0) {
|
||||
name = LocalCoordinateSystem::PointRoles[0];
|
||||
}
|
||||
|
||||
try {
|
||||
ret = obj->getDatumElement(name.c_str());
|
||||
if (!ret) {
|
||||
return false;
|
||||
}
|
||||
const char* dot = strchr(subname, '.');
|
||||
if (dot) {
|
||||
subname = dot + 1;
|
||||
}
|
||||
else {
|
||||
subname = "";
|
||||
}
|
||||
ret = ret->getSubObject(subname, pyobj, mat, true, depth + 1);
|
||||
return true;
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
e.ReportException();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
194
src/App/Datums.h
194
src/App/Datums.h
@@ -1,5 +1,7 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2012 Jürgen Riegel <juergen.riegel@web.de> *
|
||||
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.net> *
|
||||
* Copyright (c) 2015 Alexander Golubev (Fat-Zer) <fatzer2@gmail.com> *
|
||||
* Copyright (c) 2024 Ondsel (PL Boyer) <development@ondsel.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
@@ -24,29 +26,37 @@
|
||||
#define DATUMS_H
|
||||
|
||||
#include "GeoFeature.h"
|
||||
#include "GeoFeatureGroupExtension.h"
|
||||
#include "QCoreApplication"
|
||||
|
||||
namespace Base
|
||||
{
|
||||
class Rotation;
|
||||
}
|
||||
|
||||
namespace App
|
||||
{
|
||||
class LocalCoordinateSystem;
|
||||
|
||||
class Origin;
|
||||
|
||||
/** Plane Object
|
||||
* Used to define planar support for all kind of operations in the document space
|
||||
*/
|
||||
class AppExport DatumElement: public App::GeoFeature
|
||||
{
|
||||
PROPERTY_HEADER_WITH_OVERRIDE(App::DatumElement);
|
||||
|
||||
public:
|
||||
/// additional information about the feature usage (e.g. "BasePlane-XY" or "Axis-X" in a Origin)
|
||||
/// additional information about the feature usage (e.g. "BasePlane-XY" or "Axis-X")
|
||||
PropertyString Role;
|
||||
|
||||
/// Constructor
|
||||
DatumElement();
|
||||
DatumElement(bool hideRole = true);
|
||||
~DatumElement() override;
|
||||
|
||||
/// Finds the origin object this plane belongs to
|
||||
App::Origin* getOrigin();
|
||||
App::LocalCoordinateSystem* getLCS();
|
||||
|
||||
bool getCameraAlignmentDirection(Base::Vector3d& direction, const char* subname) const override;
|
||||
|
||||
/// Returns true if this DatumElement is part of a App::Origin.
|
||||
bool isOriginFeature();
|
||||
};
|
||||
|
||||
class AppExport Plane: public App::DatumElement
|
||||
@@ -71,6 +81,172 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class AppExport Point: public App::DatumElement
|
||||
{
|
||||
PROPERTY_HEADER_WITH_OVERRIDE(App::DatumElement);
|
||||
|
||||
public:
|
||||
const char* getViewProviderName() const override
|
||||
{
|
||||
return "Gui::ViewProviderPoint";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class AppExport LocalCoordinateSystem: public App::GeoFeature
|
||||
{
|
||||
PROPERTY_HEADER_WITH_OVERRIDE(App::LocalCoordinateSystem);
|
||||
Q_DECLARE_TR_FUNCTIONS(App::LocalCoordinateSystem)
|
||||
|
||||
public:
|
||||
/// Constructor
|
||||
LocalCoordinateSystem();
|
||||
~LocalCoordinateSystem() override;
|
||||
|
||||
/// returns the type name of the ViewProvider
|
||||
const char* getViewProviderName() const override
|
||||
{
|
||||
return "Gui::ViewProviderOrigin";
|
||||
}
|
||||
|
||||
bool getCameraAlignmentDirection(Base::Vector3d& direction, const char* subname) const override;
|
||||
|
||||
/** @name Axis and plane access
|
||||
* This functions returns casted axis and planes objects and asserts they are set correctly
|
||||
* otherwise Base::Exception is thrown.
|
||||
*/
|
||||
///@{
|
||||
// returns origin point
|
||||
App::Point* getOrigin() const
|
||||
{
|
||||
return getPoint(PointRoles[0]);
|
||||
}
|
||||
|
||||
// returns X axis
|
||||
App::Line* getX() const
|
||||
{
|
||||
return getAxis(AxisRoles[0]);
|
||||
}
|
||||
// returns Y axis
|
||||
App::Line* getY() const
|
||||
{
|
||||
return getAxis(AxisRoles[1]);
|
||||
}
|
||||
// returns Z axis
|
||||
App::Line* getZ() const
|
||||
{
|
||||
return getAxis(AxisRoles[2]);
|
||||
}
|
||||
|
||||
// returns XY plane
|
||||
App::Plane* getXY() const
|
||||
{
|
||||
return getPlane(PlaneRoles[0]);
|
||||
}
|
||||
// returns XZ plane
|
||||
App::Plane* getXZ() const
|
||||
{
|
||||
return getPlane(PlaneRoles[1]);
|
||||
}
|
||||
// returns YZ plane
|
||||
App::Plane* getYZ() const
|
||||
{
|
||||
return getPlane(PlaneRoles[2]);
|
||||
}
|
||||
|
||||
/// Returns all axis objects to iterate on them
|
||||
std::vector<App::Line*> axes() const
|
||||
{
|
||||
return {getX(), getY(), getZ()};
|
||||
}
|
||||
|
||||
/// Returns all base planes objects to iterate on them
|
||||
std::vector<App::Plane*> planes() const
|
||||
{
|
||||
return {getXY(), getXZ(), getYZ()};
|
||||
}
|
||||
|
||||
/// Returns all controlled objects (both planes and axis) to iterate on them
|
||||
std::vector<App::DatumElement*> baseObjects() const
|
||||
{
|
||||
return {getX(), getY(), getZ(), getXY(), getXZ(), getYZ(), getOrigin()};
|
||||
}
|
||||
|
||||
/// Returns an axis by it's name
|
||||
App::DatumElement* getDatumElement(const char* role) const;
|
||||
|
||||
/// Returns an axis by it's name
|
||||
App::Line* getAxis(const char* role) const;
|
||||
|
||||
/// Returns an axis by it's name
|
||||
App::Plane* getPlane(const char* role) const;
|
||||
|
||||
/// Returns a point by it's name
|
||||
App::Point* getPoint(const char* role) const;
|
||||
///@}
|
||||
|
||||
/// Returns true if the given object is part of the origin
|
||||
bool hasObject(const DocumentObject* obj) const;
|
||||
|
||||
/// Returns true on changing DatumElement set
|
||||
short mustExecute() const override;
|
||||
|
||||
/// Axis types
|
||||
static constexpr const char* AxisRoles[3] = {"X_Axis", "Y_Axis", "Z_Axis"};
|
||||
/// Baseplane types
|
||||
static constexpr const char* PlaneRoles[3] = {"XY_Plane", "XZ_Plane", "YZ_Plane"};
|
||||
/// Points types
|
||||
static constexpr const char* PointRoles[1] = {"Origin"};
|
||||
|
||||
virtual bool isOrigin()
|
||||
{
|
||||
return false;
|
||||
};
|
||||
|
||||
// Axis links
|
||||
PropertyLinkList OriginFeatures;
|
||||
|
||||
protected:
|
||||
/// Checks integrity of the LCS
|
||||
App::DocumentObjectExecReturn* execute() override;
|
||||
/// Creates all corresponding Axes and Planes objects for the LCS if they aren't linked yet
|
||||
void setupObject() override;
|
||||
/// Removes all planes and axis if they are still linked to the document
|
||||
void unsetupObject() override;
|
||||
|
||||
private:
|
||||
struct SetupData;
|
||||
void setupDatumElement(App::PropertyLink& featProp, const SetupData& data);
|
||||
|
||||
class LCSExtension: public GeoFeatureGroupExtension
|
||||
{
|
||||
LocalCoordinateSystem* obj;
|
||||
|
||||
public:
|
||||
explicit LCSExtension(LocalCoordinateSystem* obj);
|
||||
void initExtension(ExtensionContainer* obj) override;
|
||||
bool extensionGetSubObject(DocumentObject*& ret,
|
||||
const char* subname,
|
||||
PyObject**,
|
||||
Base::Matrix4D*,
|
||||
bool,
|
||||
int) const override;
|
||||
};
|
||||
LCSExtension extension;
|
||||
|
||||
struct SetupData
|
||||
{
|
||||
Base::Type type;
|
||||
const char* role = nullptr;
|
||||
QString label;
|
||||
Base::Rotation rot;
|
||||
};
|
||||
static const std::vector<SetupData>& getSetupData();
|
||||
|
||||
DatumElement* createDatum(SetupData& data);
|
||||
SetupData getData(const char* role);
|
||||
};
|
||||
|
||||
} // namespace App
|
||||
|
||||
#endif /* end of include guard: DATUMS_H */
|
||||
|
||||
@@ -312,7 +312,10 @@ void Document::exportGraphviz(std::ostream& out) const
|
||||
}
|
||||
if (!sgraph) {
|
||||
if (docObj->isDerivedFrom(DatumElement::getClassTypeId())) {
|
||||
sgraph = GraphList[static_cast<DatumElement*>(docObj)->getOrigin()];
|
||||
auto* lcs = static_cast<DatumElement*>(docObj)->getLCS();
|
||||
if (lcs) {
|
||||
sgraph = GraphList[lcs];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,240 +23,19 @@
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
#include <App/Document.h>
|
||||
#include <Base/Exception.h>
|
||||
#include <Base/Placement.h>
|
||||
|
||||
#include "Origin.h"
|
||||
#include "Datums.h"
|
||||
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
using namespace App;
|
||||
|
||||
|
||||
PROPERTY_SOURCE(App::Origin, App::DocumentObject)
|
||||
PROPERTY_SOURCE(App::Origin, App::LocalCoordinateSystem)
|
||||
|
||||
Origin::Origin()
|
||||
: extension(this)
|
||||
{
|
||||
ADD_PROPERTY_TYPE(OriginFeatures,
|
||||
(nullptr),
|
||||
0,
|
||||
App::Prop_Hidden,
|
||||
"Axis and baseplanes controlled by the origin");
|
||||
|
||||
setStatus(App::NoAutoExpand, true);
|
||||
extension.initExtension(this);
|
||||
// App::Origin is a LCS for which placement is fixed to identity.
|
||||
Placement.setStatus(Property::Hidden, true);
|
||||
}
|
||||
|
||||
|
||||
Origin::~Origin() = default;
|
||||
|
||||
App::DatumElement* Origin::getOriginFeature(const char* role) const
|
||||
{
|
||||
const auto& features = OriginFeatures.getValues();
|
||||
auto featIt = std::find_if(features.begin(), features.end(), [role](App::DocumentObject* obj) {
|
||||
return obj->isDerivedFrom(App::DatumElement::getClassTypeId())
|
||||
&& strcmp(static_cast<App::DatumElement*>(obj)->Role.getValue(), role) == 0;
|
||||
});
|
||||
if (featIt != features.end()) {
|
||||
return static_cast<App::DatumElement*>(*featIt);
|
||||
}
|
||||
else {
|
||||
|
||||
std::stringstream err;
|
||||
err << "Origin \"" << getFullName() << "\" doesn't contain feature with role \"" << role
|
||||
<< '"';
|
||||
throw Base::RuntimeError(err.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
App::Line* Origin::getAxis(const char* role) const
|
||||
{
|
||||
App::DatumElement* feat = getOriginFeature(role);
|
||||
if (feat->isDerivedFrom(App::Line::getClassTypeId())) {
|
||||
return static_cast<App::Line*>(feat);
|
||||
}
|
||||
else {
|
||||
std::stringstream err;
|
||||
err << "Origin \"" << getFullName() << "\" contains bad Axis object for role \"" << role
|
||||
<< '"';
|
||||
throw Base::RuntimeError(err.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
App::Plane* Origin::getPlane(const char* role) const
|
||||
{
|
||||
App::DatumElement* feat = getOriginFeature(role);
|
||||
if (feat->isDerivedFrom(App::Plane::getClassTypeId())) {
|
||||
return static_cast<App::Plane*>(feat);
|
||||
}
|
||||
else {
|
||||
std::stringstream err;
|
||||
err << "Origin \"" << getFullName() << "\" contains bad Plane object for role \"" << role
|
||||
<< '"';
|
||||
throw Base::RuntimeError(err.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
bool Origin::hasObject(const DocumentObject* obj) const
|
||||
{
|
||||
const auto& features = OriginFeatures.getValues();
|
||||
return std::find(features.begin(), features.end(), obj) != features.end();
|
||||
}
|
||||
|
||||
short Origin::mustExecute() const
|
||||
{
|
||||
if (OriginFeatures.isTouched()) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return DocumentObject::mustExecute();
|
||||
}
|
||||
}
|
||||
|
||||
App::DocumentObjectExecReturn* Origin::execute()
|
||||
{
|
||||
try { // try to find all base axis and planes in the origin
|
||||
for (const char* role : AxisRoles) {
|
||||
App::Line* axis = getAxis(role);
|
||||
assert(axis);
|
||||
(void)axis;
|
||||
}
|
||||
for (const char* role : PlaneRoles) {
|
||||
App::Plane* plane = getPlane(role);
|
||||
assert(plane);
|
||||
(void)plane;
|
||||
}
|
||||
}
|
||||
catch (const Base::Exception& ex) {
|
||||
setError();
|
||||
return new App::DocumentObjectExecReturn(ex.what());
|
||||
}
|
||||
|
||||
return DocumentObject::execute();
|
||||
}
|
||||
|
||||
void Origin::setupObject()
|
||||
{
|
||||
const static struct
|
||||
{
|
||||
const Base::Type type;
|
||||
const char* role;
|
||||
const QString label;
|
||||
Base::Rotation rot;
|
||||
} setupData[] = {
|
||||
// clang-format off
|
||||
{App::Line::getClassTypeId(), AxisRoles[0], tr("X-axis"), Base::Rotation()},
|
||||
{App::Line::getClassTypeId(), AxisRoles[1], tr("Y-axis"), Base::Rotation(Base::Vector3d(1,1,1), M_PI*2/3)},
|
||||
{App::Line::getClassTypeId(), AxisRoles[2], tr("Z-axis"), Base::Rotation(Base::Vector3d(1,-1,1), M_PI*2/3)},
|
||||
{App::Plane::getClassTypeId(), PlaneRoles[0], tr("XY-plane"), Base::Rotation()},
|
||||
{App::Plane::getClassTypeId(), PlaneRoles[1], tr("XZ-plane"), Base::Rotation(1.0, 0.0, 0.0, 1.0 )},
|
||||
{App::Plane::getClassTypeId(), PlaneRoles[2], tr("YZ-plane"), Base::Rotation(Base::Vector3d(1,1,1), M_PI*2/3)}
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
App::Document* doc = getDocument();
|
||||
|
||||
std::vector<App::DocumentObject*> links;
|
||||
for (auto data : setupData) {
|
||||
std::string objName = doc->getUniqueObjectName(data.role);
|
||||
App::DocumentObject* featureObj = doc->addObject(data.type.getName(), objName.c_str());
|
||||
|
||||
assert(featureObj && featureObj->isDerivedFrom(App::DatumElement::getClassTypeId()));
|
||||
|
||||
QByteArray byteArray = data.label.toUtf8();
|
||||
featureObj->Label.setValue(byteArray.constData());
|
||||
|
||||
App::DatumElement* feature = static_cast<App::DatumElement*>(featureObj);
|
||||
feature->Placement.setValue(Base::Placement(Base::Vector3d(), data.rot));
|
||||
feature->Role.setValue(data.role);
|
||||
|
||||
links.push_back(feature);
|
||||
}
|
||||
|
||||
OriginFeatures.setValues(links);
|
||||
}
|
||||
|
||||
void Origin::unsetupObject()
|
||||
{
|
||||
const auto& objsLnk = OriginFeatures.getValues();
|
||||
// Copy to set to assert we won't call methode more then one time for each object
|
||||
std::set<App::DocumentObject*> objs(objsLnk.begin(), objsLnk.end());
|
||||
// Remove all controlled objects
|
||||
for (auto obj : objs) {
|
||||
// Check that previous deletes wasn't inderectly removed one of our objects
|
||||
const auto& objsLnk = OriginFeatures.getValues();
|
||||
if (std::find(objsLnk.begin(), objsLnk.end(), obj) != objsLnk.end()) {
|
||||
if (!obj->isRemoving()) {
|
||||
obj->getDocument()->removeObject(obj->getNameInDocument());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
Origin::OriginExtension::OriginExtension(Origin* obj)
|
||||
: obj(obj)
|
||||
{
|
||||
Group.setStatus(Property::Transient, true);
|
||||
}
|
||||
|
||||
void Origin::OriginExtension::initExtension(ExtensionContainer* obj)
|
||||
{
|
||||
App::GroupExtension::initExtension(obj);
|
||||
}
|
||||
|
||||
bool Origin::OriginExtension::extensionGetSubObject(DocumentObject*& ret,
|
||||
const char* subname,
|
||||
PyObject** pyobj,
|
||||
Base::Matrix4D* mat,
|
||||
bool,
|
||||
int depth) const
|
||||
{
|
||||
if (!subname || subname[0] == '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// mapping of object name to role name
|
||||
std::string name(subname);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (name.rfind(Origin::AxisRoles[i], 0) == 0) {
|
||||
name = Origin::AxisRoles[i];
|
||||
break;
|
||||
}
|
||||
if (name.rfind(Origin::PlaneRoles[i], 0) == 0) {
|
||||
name = Origin::PlaneRoles[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
ret = obj->getOriginFeature(name.c_str());
|
||||
if (!ret) {
|
||||
return false;
|
||||
}
|
||||
const char* dot = strchr(subname, '.');
|
||||
if (dot) {
|
||||
subname = dot + 1;
|
||||
}
|
||||
else {
|
||||
subname = "";
|
||||
}
|
||||
ret = ret->getSubObject(subname, pyobj, mat, true, depth + 1);
|
||||
return true;
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
e.ReportException();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
115
src/App/Origin.h
115
src/App/Origin.h
@@ -26,16 +26,13 @@
|
||||
#define APP_Origin_H
|
||||
|
||||
#include "Datums.h"
|
||||
#include "GeoFeatureGroupExtension.h"
|
||||
|
||||
#include "QCoreApplication"
|
||||
|
||||
namespace App
|
||||
{
|
||||
|
||||
/** Base class of all geometric document objects.
|
||||
*/
|
||||
class AppExport Origin: public App::DocumentObject
|
||||
class AppExport Origin: public App::LocalCoordinateSystem
|
||||
{
|
||||
PROPERTY_HEADER_WITH_OVERRIDE(App::Origin);
|
||||
Q_DECLARE_TR_FUNCTIONS(App::Origin)
|
||||
@@ -51,116 +48,10 @@ public:
|
||||
return "Gui::ViewProviderOrigin";
|
||||
}
|
||||
|
||||
/** @name Axis and plane access
|
||||
* This functions returns casted axis and planes objects and asserts they are set correctly
|
||||
* otherwise Base::Exception is thrown.
|
||||
*/
|
||||
///@{
|
||||
// returns X axis
|
||||
App::Line* getX() const
|
||||
bool isOrigin() override
|
||||
{
|
||||
return getAxis(AxisRoles[0]);
|
||||
}
|
||||
// returns Y axis
|
||||
App::Line* getY() const
|
||||
{
|
||||
return getAxis(AxisRoles[1]);
|
||||
}
|
||||
// returns Z axis
|
||||
App::Line* getZ() const
|
||||
{
|
||||
return getAxis(AxisRoles[2]);
|
||||
}
|
||||
|
||||
// returns XY plane
|
||||
App::Plane* getXY() const
|
||||
{
|
||||
return getPlane(PlaneRoles[0]);
|
||||
}
|
||||
// returns XZ plane
|
||||
App::Plane* getXZ() const
|
||||
{
|
||||
return getPlane(PlaneRoles[1]);
|
||||
}
|
||||
// returns YZ plane
|
||||
App::Plane* getYZ() const
|
||||
{
|
||||
return getPlane(PlaneRoles[2]);
|
||||
}
|
||||
|
||||
/// Returns all axis objects to iterate on them
|
||||
std::vector<App::Line*> axes() const
|
||||
{
|
||||
return {getX(), getY(), getZ()};
|
||||
}
|
||||
|
||||
/// Returns all base planes objects to iterate on them
|
||||
std::vector<App::Plane*> planes() const
|
||||
{
|
||||
return {getXY(), getXZ(), getYZ()};
|
||||
}
|
||||
|
||||
/// Returns all controlled objects (both planes and axis) to iterate on them
|
||||
std::vector<App::DatumElement*> baseObjects() const
|
||||
{
|
||||
return {getX(), getY(), getZ(), getXY(), getXZ(), getYZ()};
|
||||
}
|
||||
|
||||
/// Returns an axis by it's name
|
||||
App::DatumElement* getOriginFeature(const char* role) const;
|
||||
|
||||
/// Returns an axis by it's name
|
||||
App::Line* getAxis(const char* role) const;
|
||||
|
||||
/// Returns an axis by it's name
|
||||
App::Plane* getPlane(const char* role) const;
|
||||
///@}
|
||||
|
||||
/// Returns true if the given object is part of the origin
|
||||
bool hasObject(const DocumentObject* obj) const;
|
||||
|
||||
/// Returns the default bounding box of the origin (use this if you confused what should be s )
|
||||
// TODO Delete me if not really needed (2015-09-01, Fat-Zer)
|
||||
static Base::BoundBox3d defaultBoundBox();
|
||||
|
||||
/// Returns true on changing OriginFeature set
|
||||
short mustExecute() const override;
|
||||
|
||||
/// Axis types
|
||||
static constexpr const char* AxisRoles[3] = {"X_Axis", "Y_Axis", "Z_Axis"};
|
||||
/// Baseplane types
|
||||
static constexpr const char* PlaneRoles[3] = {"XY_Plane", "XZ_Plane", "YZ_Plane"};
|
||||
|
||||
// Axis links
|
||||
PropertyLinkList OriginFeatures;
|
||||
|
||||
protected:
|
||||
/// Checks integrity of the Origin
|
||||
App::DocumentObjectExecReturn* execute() override;
|
||||
/// Creates all corresponding Axes and Planes objects for the origin if they aren't linked yet
|
||||
void setupObject() override;
|
||||
/// Removes all planes and axis if they are still linked to the document
|
||||
void unsetupObject() override;
|
||||
|
||||
private:
|
||||
struct SetupData;
|
||||
void setupOriginFeature(App::PropertyLink& featProp, const SetupData& data);
|
||||
|
||||
class OriginExtension: public GeoFeatureGroupExtension
|
||||
{
|
||||
Origin* obj;
|
||||
|
||||
public:
|
||||
explicit OriginExtension(Origin* obj);
|
||||
void initExtension(ExtensionContainer* obj) override;
|
||||
bool extensionGetSubObject(DocumentObject*& ret,
|
||||
const char* subname,
|
||||
PyObject**,
|
||||
Base::Matrix4D*,
|
||||
bool,
|
||||
int) const override;
|
||||
return true;
|
||||
};
|
||||
OriginExtension extension;
|
||||
};
|
||||
|
||||
} // namespace App
|
||||
|
||||
@@ -121,7 +121,8 @@ App::DocumentObject* OriginGroupExtension::getGroupOfObject(const DocumentObject
|
||||
if (o->hasExtension(App::OriginGroupExtension::getExtensionClassTypeId())) {
|
||||
return o;
|
||||
}
|
||||
else if (isOriginFeature && o->isDerivedFrom(App::Origin::getClassTypeId())) {
|
||||
else if (isOriginFeature
|
||||
&& o->isDerivedFrom(App::LocalCoordinateSystem::getClassTypeId())) {
|
||||
auto result = getGroupOfObject(o);
|
||||
if (result) {
|
||||
return result;
|
||||
@@ -221,16 +222,24 @@ void OriginGroupExtension::relinkToOrigin(App::DocumentObject* obj)
|
||||
std::vector<App::DocumentObject*> result;
|
||||
std::vector<App::Property*> list;
|
||||
obj->getPropertyList(list);
|
||||
auto isOriginFeature = [](App::DocumentObject* obj) -> bool {
|
||||
// Check if the object is a DatumElement
|
||||
if (auto* datumElement = dynamic_cast<App::DatumElement*>(obj)) {
|
||||
// Check if the DatumElement is an origin
|
||||
return datumElement->isOriginFeature();
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
for (App::Property* prop : list) {
|
||||
if (prop->isDerivedFrom<App::PropertyLink>()) {
|
||||
|
||||
auto p = static_cast<App::PropertyLink*>(prop);
|
||||
if (!p->getValue()
|
||||
|| !p->getValue()->isDerivedFrom(App::DatumElement::getClassTypeId())) {
|
||||
if (!p->getValue() || !isOriginFeature(p->getValue())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
p->setValue(getOrigin()->getOriginFeature(
|
||||
p->setValue(getOrigin()->getDatumElement(
|
||||
static_cast<DatumElement*>(p->getValue())->Role.getValue()));
|
||||
}
|
||||
else if (prop->isDerivedFrom<App::PropertyLinkList>()) {
|
||||
@@ -239,11 +248,11 @@ void OriginGroupExtension::relinkToOrigin(App::DocumentObject* obj)
|
||||
std::vector<App::DocumentObject*> result;
|
||||
bool changed = false;
|
||||
for (App::DocumentObject* o : vec) {
|
||||
if (!o || !o->isDerivedFrom(App::DatumElement::getClassTypeId())) {
|
||||
if (!isOriginFeature(o)) {
|
||||
result.push_back(o);
|
||||
}
|
||||
else {
|
||||
result.push_back(getOrigin()->getOriginFeature(
|
||||
result.push_back(getOrigin()->getDatumElement(
|
||||
static_cast<DatumElement*>(o)->Role.getValue()));
|
||||
changed = true;
|
||||
}
|
||||
@@ -254,13 +263,12 @@ void OriginGroupExtension::relinkToOrigin(App::DocumentObject* obj)
|
||||
}
|
||||
else if (prop->isDerivedFrom<App::PropertyLinkSub>()) {
|
||||
auto p = static_cast<App::PropertyLinkSub*>(prop);
|
||||
if (!p->getValue()
|
||||
|| !p->getValue()->isDerivedFrom(App::DatumElement::getClassTypeId())) {
|
||||
if (!p->getValue() || !isOriginFeature(p->getValue())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<std::string> subValues = p->getSubValues();
|
||||
p->setValue(getOrigin()->getOriginFeature(
|
||||
p->setValue(getOrigin()->getDatumElement(
|
||||
static_cast<DatumElement*>(p->getValue())->Role.getValue()),
|
||||
subValues);
|
||||
}
|
||||
@@ -269,8 +277,8 @@ void OriginGroupExtension::relinkToOrigin(App::DocumentObject* obj)
|
||||
auto vec = p->getSubListValues();
|
||||
bool changed = false;
|
||||
for (auto& v : vec) {
|
||||
if (v.first && v.first->isDerivedFrom(App::DatumElement::getClassTypeId())) {
|
||||
v.first = getOrigin()->getOriginFeature(
|
||||
if (isOriginFeature(v.first)) {
|
||||
v.first = getOrigin()->getDatumElement(
|
||||
static_cast<DatumElement*>(v.first)->Role.getValue());
|
||||
changed = true;
|
||||
}
|
||||
|
||||
@@ -120,6 +120,7 @@
|
||||
#include "ViewProviderOriginGroup.h"
|
||||
#include "ViewProviderPlacement.h"
|
||||
#include "ViewProviderPlane.h"
|
||||
#include "ViewProviderPoint.h"
|
||||
#include "ViewProviderPart.h"
|
||||
#include "ViewProviderFeaturePython.h"
|
||||
#include "ViewProviderTextDocument.h"
|
||||
@@ -2070,6 +2071,7 @@ void Application::initTypes()
|
||||
Gui::ViewProviderPlacementPython ::init();
|
||||
Gui::ViewProviderDatum ::init();
|
||||
Gui::ViewProviderPlane ::init();
|
||||
Gui::ViewProviderPoint ::init();
|
||||
Gui::ViewProviderLine ::init();
|
||||
Gui::ViewProviderGeoFeatureGroup ::init();
|
||||
Gui::ViewProviderGeoFeatureGroupPython ::init();
|
||||
|
||||
@@ -963,6 +963,7 @@ SET(Viewprovider_CPP_SRCS
|
||||
ViewProviderPlacement.cpp
|
||||
ViewProviderDatum.cpp
|
||||
ViewProviderPlane.cpp
|
||||
ViewProviderPoint.cpp
|
||||
ViewProviderLine.cpp
|
||||
ViewProviderGeoFeatureGroup.cpp
|
||||
ViewProviderOriginGroup.cpp
|
||||
@@ -1000,6 +1001,7 @@ SET(Viewprovider_SRCS
|
||||
ViewProviderPlacement.h
|
||||
ViewProviderDatum.h
|
||||
ViewProviderPlane.h
|
||||
ViewProviderPoint.h
|
||||
ViewProviderLine.h
|
||||
ViewProviderGeoFeatureGroup.h
|
||||
ViewProviderOriginGroup.h
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <Inventor/nodes/SoAsciiText.h>
|
||||
# include <Inventor/nodes/SoText2.h>
|
||||
# include <Inventor/nodes/SoAnnotation.h>
|
||||
# include <Inventor/nodes/SoDrawStyle.h>
|
||||
# include <Inventor/nodes/SoFont.h>
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <App/Origin.h>
|
||||
|
||||
#include "ViewProviderDatum.h"
|
||||
#include "Inventor/SoAxisCrossKit.h"
|
||||
#include "SoFCSelection.h"
|
||||
#include "ViewProviderOrigin.h"
|
||||
|
||||
@@ -47,32 +48,28 @@ using namespace Gui;
|
||||
PROPERTY_SOURCE(Gui::ViewProviderDatum, Gui::ViewProviderGeometryObject)
|
||||
|
||||
ViewProviderDatum::ViewProviderDatum() {
|
||||
ADD_PROPERTY_TYPE(Size, (ViewProviderOrigin::defaultSize()), 0, App::Prop_ReadOnly,
|
||||
QT_TRANSLATE_NOOP("App::Property", "Visual size of the feature"));
|
||||
|
||||
ShapeAppearance.setDiffuseColor(
|
||||
ViewProviderOrigin::defaultColor); // Set default color for origin (light-blue)
|
||||
// Set default color for origin (light-blue)
|
||||
ShapeAppearance.setDiffuseColor(ViewProviderOrigin::defaultColor);
|
||||
Transparency.setValue(0);
|
||||
BoundingBox.setStatus(App::Property::Hidden, true); // Hide Boundingbox from the user due to it doesn't make sense
|
||||
|
||||
// Create node for scaling the origin
|
||||
pScale = new SoScale();
|
||||
pScale->ref();
|
||||
soScale = new SoShapeScale();
|
||||
|
||||
// Create the separator filled by inherited classes
|
||||
pOriginFeatureRoot = new SoSeparator();
|
||||
pOriginFeatureRoot->ref();
|
||||
pRoot = new SoSeparator();
|
||||
pRoot->ref();
|
||||
|
||||
// Create the Label node
|
||||
pLabel = new SoAsciiText();
|
||||
pLabel = new SoText2();
|
||||
pLabel->ref();
|
||||
pLabel->width.setValue(-1);
|
||||
|
||||
lineThickness = 2.0;
|
||||
}
|
||||
|
||||
|
||||
ViewProviderDatum::~ViewProviderDatum() {
|
||||
pScale->unref();
|
||||
pOriginFeatureRoot->unref();
|
||||
pRoot->unref();
|
||||
pLabel->unref();
|
||||
}
|
||||
|
||||
@@ -82,7 +79,6 @@ void ViewProviderDatum::attach(App::DocumentObject* pcObject)
|
||||
ViewProviderGeometryObject::attach(pcObject);
|
||||
|
||||
float defaultSz = ViewProviderOrigin::defaultSize();
|
||||
float sz = Size.getValue() / defaultSz;
|
||||
|
||||
// Create an external separator
|
||||
auto sep = new SoSeparator();
|
||||
@@ -95,31 +91,9 @@ void ViewProviderDatum::attach(App::DocumentObject* pcObject)
|
||||
matBinding->value = SoMaterialBinding::OVERALL;
|
||||
sep->addChild(matBinding);
|
||||
|
||||
// Scale feature to the given size
|
||||
pScale->scaleFactor = SbVec3f(sz, sz, sz);
|
||||
sep->addChild(pScale);
|
||||
|
||||
// Setup font size
|
||||
auto font = new SoFont();
|
||||
float fontRatio = 10.0f;
|
||||
if (pcObject->is<App::Line>()) {
|
||||
// keep font size on axes equal to font size on planes
|
||||
fontRatio *= ViewProviderOrigin::axesScaling;
|
||||
const char* axisName = pcObject->getNameInDocument();
|
||||
auto axisRoles = App::Origin::AxisRoles;
|
||||
if (strncmp(axisName, axisRoles[0], strlen(axisRoles[0])) == 0) {
|
||||
// X-axis: red
|
||||
ShapeAppearance.setDiffuseColor(0xFF0000FF);
|
||||
}
|
||||
else if (strncmp(axisName, axisRoles[1], strlen(axisRoles[1])) == 0) {
|
||||
// Y-axis: green
|
||||
ShapeAppearance.setDiffuseColor(0x00FF00FF);
|
||||
}
|
||||
else if (strncmp(axisName, axisRoles[2], strlen(axisRoles[2])) == 0) {
|
||||
// Z-axis: blue
|
||||
ShapeAppearance.setDiffuseColor(0x0000FFFF);
|
||||
}
|
||||
}
|
||||
float fontRatio = 4.0f;
|
||||
font->size.setValue(defaultSz / fontRatio);
|
||||
sep->addChild(font);
|
||||
|
||||
@@ -135,46 +109,42 @@ void ViewProviderDatum::attach(App::DocumentObject* pcObject)
|
||||
|
||||
// Style for normal (visible) lines
|
||||
auto style = new SoDrawStyle();
|
||||
style->lineWidth = 2.0f;
|
||||
style->lineWidth = lineThickness;
|
||||
highlight->addChild(style);
|
||||
|
||||
// Visible lines
|
||||
highlight->addChild(pOriginFeatureRoot);
|
||||
highlight->addChild(pRoot);
|
||||
|
||||
// Hidden features
|
||||
auto hidden = new SoAnnotation();
|
||||
|
||||
// Style for hidden lines
|
||||
style = new SoDrawStyle();
|
||||
style->lineWidth = 2.0f;
|
||||
style->linePattern.setValue(0xF000); // (dash-skip-skip-skip)
|
||||
style->lineWidth = lineThickness;
|
||||
style->linePattern.setValue(0xFF00); // (dash-skip)
|
||||
hidden->addChild(style);
|
||||
|
||||
// Hidden lines
|
||||
hidden->addChild(pOriginFeatureRoot);
|
||||
hidden->addChild(pRoot);
|
||||
|
||||
highlight->addChild(hidden);
|
||||
|
||||
sep->addChild(highlight);
|
||||
|
||||
// Setup the object label as it's text
|
||||
pLabel->string.setValue(SbString(pcObject->Label.getValue()));
|
||||
|
||||
addDisplayMaskMode(sep, "Base");
|
||||
// Scale feature to the given size
|
||||
float sz = App::GetApplication()
|
||||
.GetParameterGroupByPath("User parameter:BaseApp/Preferences/View")
|
||||
->GetFloat("LocalCoordinateSystemSize", 2.0); // NOLINT
|
||||
|
||||
soScale->setPart("shape", sep);
|
||||
soScale->scaleFactor = sz;
|
||||
|
||||
addDisplayMaskMode(soScale, "Base");
|
||||
}
|
||||
|
||||
void ViewProviderDatum::updateData(const App::Property* prop) {
|
||||
if (prop == &getObject()->Label) {
|
||||
pLabel->string.setValue(SbString(getObject()->Label.getValue()));
|
||||
}
|
||||
ViewProviderGeometryObject::updateData(prop);
|
||||
}
|
||||
|
||||
void ViewProviderDatum::onChanged(const App::Property* prop) {
|
||||
if (prop == &Size) {
|
||||
float sz = Size.getValue() / ViewProviderOrigin::defaultSize();
|
||||
pScale->scaleFactor = SbVec3f(sz, sz, sz);
|
||||
}
|
||||
ViewProviderGeometryObject::onChanged(prop);
|
||||
}
|
||||
|
||||
@@ -188,19 +158,14 @@ std::vector<std::string> ViewProviderDatum::getDisplayModes() const
|
||||
|
||||
void ViewProviderDatum::setDisplayMode(const char* ModeName)
|
||||
{
|
||||
if (strcmp(ModeName, "Base") == 0)
|
||||
if (strcmp(ModeName, "Base") == 0) {
|
||||
setDisplayMaskMode("Base");
|
||||
}
|
||||
ViewProviderGeometryObject::setDisplayMode(ModeName);
|
||||
}
|
||||
|
||||
bool ViewProviderDatum::onDelete(const std::vector<std::string>&) {
|
||||
auto feat = static_cast <App::DatumElement*>(getObject());
|
||||
// Forbid deletion if there is an origin this feature belongs to
|
||||
|
||||
if (feat->getOrigin()) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
return !feat->getLCS();
|
||||
}
|
||||
|
||||
@@ -25,12 +25,14 @@
|
||||
|
||||
#include "ViewProviderGeometryObject.h"
|
||||
|
||||
class SoAsciiText;
|
||||
class SoText2;
|
||||
class SoScale;
|
||||
|
||||
namespace Gui
|
||||
{
|
||||
|
||||
class SoShapeScale;
|
||||
|
||||
/**
|
||||
* View provider associated with an App::DatumElement.
|
||||
*/
|
||||
@@ -38,20 +40,16 @@ namespace Gui
|
||||
PROPERTY_HEADER_WITH_OVERRIDE(Gui::ViewProviderDatum);
|
||||
|
||||
public:
|
||||
/// The display size of the feature
|
||||
App::PropertyFloat Size;
|
||||
|
||||
ViewProviderDatum();
|
||||
~ViewProviderDatum() override;
|
||||
|
||||
/// Get point derived classes will add their specific stuff
|
||||
SoSeparator* getOriginFeatureRoot() { return pOriginFeatureRoot; }
|
||||
SoSeparator* getRoot() { return pRoot; }
|
||||
|
||||
/// Get pointer to the text label associated with the feature
|
||||
SoAsciiText* getLabel() { return pLabel; }
|
||||
SoText2* getLabel() { return pLabel; }
|
||||
|
||||
void attach(App::DocumentObject*) override;
|
||||
void updateData(const App::Property*) override;
|
||||
std::vector<std::string> getDisplayModes() const override;
|
||||
void setDisplayMode(const char* ModeName) override;
|
||||
|
||||
@@ -69,9 +67,10 @@ namespace Gui
|
||||
void onChanged(const App::Property* prop) override;
|
||||
bool onDelete(const std::vector<std::string>&) override;
|
||||
protected:
|
||||
SoSeparator* pOriginFeatureRoot;
|
||||
SoScale* pScale;
|
||||
SoAsciiText* pLabel;
|
||||
SoSeparator* pRoot;
|
||||
SoShapeScale* soScale;
|
||||
SoText2* pLabel;
|
||||
double lineThickness;
|
||||
};
|
||||
|
||||
} /* Gui */
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <Inventor/nodes/SoText2.h>
|
||||
# include <Inventor/nodes/SoAsciiText.h>
|
||||
# include <Inventor/nodes/SoCoordinate3.h>
|
||||
# include <Inventor/nodes/SoIndexedLineSet.h>
|
||||
@@ -32,6 +33,9 @@
|
||||
# include <Inventor/nodes/SoTranslation.h>
|
||||
#endif
|
||||
|
||||
#include <App/Datums.h>
|
||||
#include <Gui/ViewParams.h>
|
||||
|
||||
#include "ViewProviderLine.h"
|
||||
#include "ViewProviderOrigin.h"
|
||||
|
||||
@@ -51,14 +55,46 @@ ViewProviderLine::~ViewProviderLine() = default;
|
||||
void ViewProviderLine::attach(App::DocumentObject *obj) {
|
||||
ViewProviderDatum::attach(obj);
|
||||
|
||||
static const float size = ViewProviderOrigin::defaultSize ();
|
||||
// Setup label text and line colors
|
||||
const char* name = pcObject->getNameInDocument();
|
||||
|
||||
static const SbVec3f verts[2] = { SbVec3f(size, 0, 0), SbVec3f ( -size, 0, 0 ) };
|
||||
bool noRole = false;
|
||||
auto axisRoles = App::LocalCoordinateSystem::AxisRoles;
|
||||
if (strncmp(name, axisRoles[0], strlen(axisRoles[0])) == 0) {
|
||||
// X-axis: red
|
||||
ShapeAppearance.setDiffuseColor(ViewParams::instance()->getAxisXColor());
|
||||
pLabel->string.setValue(SbString("X"));
|
||||
}
|
||||
else if (strncmp(name, axisRoles[1], strlen(axisRoles[1])) == 0) {
|
||||
// Y-axis: green
|
||||
ShapeAppearance.setDiffuseColor(ViewParams::instance()->getAxisYColor());
|
||||
pLabel->string.setValue(SbString("Y"));
|
||||
}
|
||||
else if (strncmp(name, axisRoles[2], strlen(axisRoles[2])) == 0) {
|
||||
// Z-axis: blue
|
||||
ShapeAppearance.setDiffuseColor(ViewParams::instance()->getAxisZColor());
|
||||
pLabel->string.setValue(SbString("Z"));
|
||||
}
|
||||
else {
|
||||
noRole = true;
|
||||
}
|
||||
|
||||
static const float size = ViewProviderOrigin::defaultSize();
|
||||
|
||||
SbVec3f verts[2];
|
||||
if (noRole) {
|
||||
verts[0] = SbVec3f(2 * size, 0, 0);
|
||||
verts[1] = SbVec3f(0, 0, 0);
|
||||
}
|
||||
else {
|
||||
verts[0] = SbVec3f(size, 0, 0);
|
||||
verts[1] = SbVec3f(0.2 * size, 0, 0);
|
||||
}
|
||||
|
||||
// indexes used to create the edges
|
||||
static const int32_t lines[4] = { 0, 1, -1 };
|
||||
|
||||
SoSeparator *sep = getOriginFeatureRoot ();
|
||||
SoSeparator *sep = getRoot();
|
||||
|
||||
auto pCoords = new SoCoordinate3 ();
|
||||
pCoords->point.setNum (2);
|
||||
@@ -71,11 +107,11 @@ void ViewProviderLine::attach(App::DocumentObject *obj) {
|
||||
sep->addChild ( pLines );
|
||||
|
||||
auto textTranslation = new SoTranslation ();
|
||||
textTranslation->translation.setValue ( SbVec3f ( -size * 49. / 50., size / 30., 0 ) );
|
||||
textTranslation->translation.setValue ( SbVec3f ( size * 1.1, 0, 0 ) );
|
||||
sep->addChild ( textTranslation );
|
||||
|
||||
auto ps = new SoPickStyle();
|
||||
ps->style.setValue(SoPickStyle::BOUNDING_BOX);
|
||||
ps->style.setValue(SoPickStyle::SHAPE_ON_TOP);
|
||||
sep->addChild(ps);
|
||||
|
||||
sep->addChild ( getLabel () );
|
||||
|
||||
@@ -39,22 +39,19 @@
|
||||
#include "Document.h"
|
||||
#include "ViewProviderLine.h"
|
||||
#include "ViewProviderPlane.h"
|
||||
#include "ViewProviderPoint.h"
|
||||
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
|
||||
PROPERTY_SOURCE(Gui::ViewProviderOrigin, Gui::ViewProviderDocumentObject)
|
||||
PROPERTY_SOURCE(Gui::ViewProviderOrigin, Gui::ViewProviderGeoFeatureGroup)
|
||||
|
||||
/**
|
||||
* Creates the view provider for an object group.
|
||||
*/
|
||||
ViewProviderOrigin::ViewProviderOrigin()
|
||||
{
|
||||
ADD_PROPERTY_TYPE ( Size, (Base::Vector3d(10,10,10)), 0, App::Prop_None,
|
||||
QT_TRANSLATE_NOOP("App::Property", "The displayed size of the origin"));
|
||||
Size.setStatus(App::Property::ReadOnly, true);
|
||||
|
||||
sPixmap = "Std_CoordinateSystem";
|
||||
Visibility.setValue(false);
|
||||
|
||||
@@ -71,8 +68,9 @@ ViewProviderOrigin::~ViewProviderOrigin() {
|
||||
pcGroupChildren = nullptr;
|
||||
}
|
||||
|
||||
std::vector<App::DocumentObject*> ViewProviderOrigin::claimChildren() const {
|
||||
return static_cast<App::Origin*>( getObject() )->OriginFeatures.getValues ();
|
||||
std::vector<App::DocumentObject*> ViewProviderOrigin::claimChildren() const
|
||||
{
|
||||
return static_cast<App::Origin*>( getObject() )->OriginFeatures.getValues();
|
||||
}
|
||||
|
||||
std::vector<App::DocumentObject*> ViewProviderOrigin::claimChildren3D() const {
|
||||
@@ -128,7 +126,22 @@ void ViewProviderOrigin::setTemporaryVisibility(bool axis, bool plane) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const Base::Exception &ex) {
|
||||
|
||||
// Remember & Set origin point visibility
|
||||
App::DocumentObject* obj = origin->getOrigin();
|
||||
if (obj) {
|
||||
Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(obj);
|
||||
if (vp) {
|
||||
if (saveState) {
|
||||
tempVisMap[vp] = vp->isVisible();
|
||||
}
|
||||
vp->setVisible(plane);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
catch (const Base::Exception &ex) {
|
||||
Base::Console().Error ("%s\n", ex.what() );
|
||||
}
|
||||
|
||||
@@ -148,70 +161,34 @@ void ViewProviderOrigin::resetTemporaryVisibility() {
|
||||
double ViewProviderOrigin::defaultSize()
|
||||
{
|
||||
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
|
||||
return 0.25 * hGrp->GetFloat("NewDocumentCameraScale",100.0);
|
||||
return hGrp->GetFloat("DatumsSize", 25);
|
||||
}
|
||||
|
||||
bool ViewProviderOrigin::isTemporaryVisibility() {
|
||||
return !tempVisMap.empty();
|
||||
}
|
||||
|
||||
void ViewProviderOrigin::onChanged(const App::Property* prop) {
|
||||
if (prop == &Size) {
|
||||
try {
|
||||
Gui::Application *app = Gui::Application::Instance;
|
||||
Base::Vector3d sz = Size.getValue ();
|
||||
auto origin = static_cast<App::Origin*> ( getObject() );
|
||||
|
||||
// Calculate axes and planes sizes
|
||||
double szXY = std::max ( sz.x, sz.y );
|
||||
double szXZ = std::max ( sz.x, sz.z );
|
||||
double szYZ = std::max ( sz.y, sz.z );
|
||||
|
||||
double szX = std::min ( szXY, szXZ );
|
||||
double szY = std::min ( szXY, szYZ );
|
||||
double szZ = std::min ( szXZ, szYZ );
|
||||
|
||||
// Find view providers
|
||||
Gui::ViewProviderPlane* vpPlaneXY, *vpPlaneXZ, *vpPlaneYZ;
|
||||
Gui::ViewProviderLine* vpLineX, *vpLineY, *vpLineZ;
|
||||
// Planes
|
||||
vpPlaneXY = static_cast<Gui::ViewProviderPlane *> ( app->getViewProvider ( origin->getXY () ) );
|
||||
vpPlaneXZ = static_cast<Gui::ViewProviderPlane *> ( app->getViewProvider ( origin->getXZ () ) );
|
||||
vpPlaneYZ = static_cast<Gui::ViewProviderPlane *> ( app->getViewProvider ( origin->getYZ () ) );
|
||||
// Axes
|
||||
vpLineX = static_cast<Gui::ViewProviderLine *> ( app->getViewProvider ( origin->getX () ) );
|
||||
vpLineY = static_cast<Gui::ViewProviderLine *> ( app->getViewProvider ( origin->getY () ) );
|
||||
vpLineZ = static_cast<Gui::ViewProviderLine *> ( app->getViewProvider ( origin->getZ () ) );
|
||||
|
||||
// set their sizes
|
||||
if (vpPlaneXY) { vpPlaneXY->Size.setValue ( szXY ); }
|
||||
if (vpPlaneXZ) { vpPlaneXZ->Size.setValue ( szXZ ); }
|
||||
if (vpPlaneYZ) { vpPlaneYZ->Size.setValue ( szYZ ); }
|
||||
if (vpLineX) { vpLineX->Size.setValue ( szX * axesScaling ); }
|
||||
if (vpLineY) { vpLineY->Size.setValue ( szY * axesScaling ); }
|
||||
if (vpLineZ) { vpLineZ->Size.setValue ( szZ * axesScaling ); }
|
||||
|
||||
} catch (const Base::Exception &ex) {
|
||||
// While restoring a document don't report errors if one of the lines or planes
|
||||
// cannot be found.
|
||||
App::Document* doc = getObject()->getDocument();
|
||||
if (!doc->testStatus(App::Document::Restoring))
|
||||
Base::Console().Error ("%s\n", ex.what() );
|
||||
void ViewProviderOrigin::updateData(const App::Property* prop) {
|
||||
auto* jcs = dynamic_cast<App::LocalCoordinateSystem*>(getObject());
|
||||
if(jcs) {
|
||||
if (prop == &jcs->Placement) {
|
||||
// Update position
|
||||
}
|
||||
}
|
||||
|
||||
ViewProviderDocumentObject::onChanged ( prop );
|
||||
ViewProviderDocumentObject::updateData(prop);
|
||||
}
|
||||
|
||||
bool ViewProviderOrigin::onDelete(const std::vector<std::string> &) {
|
||||
auto origin = static_cast<App::Origin*>( getObject() );
|
||||
auto lcs = static_cast<App::LocalCoordinateSystem*>(getObject());
|
||||
|
||||
if ( !origin->getInList().empty() ) {
|
||||
auto origin = dynamic_cast<App::Origin*>(lcs);
|
||||
if (origin && !origin->getInList().empty()) {
|
||||
// Do not allow deletion of origin objects that are not lost.
|
||||
return false;
|
||||
}
|
||||
|
||||
auto objs = origin->OriginFeatures.getValues();
|
||||
origin->OriginFeatures.setValues({});
|
||||
auto objs = lcs->OriginFeatures.getValues();
|
||||
lcs->OriginFeatures.setValues({});
|
||||
|
||||
for (auto obj: objs ) {
|
||||
Gui::Command::doCommand( Gui::Command::Doc, "App.getDocument(\"%s\").removeObject(\"%s\")",
|
||||
|
||||
@@ -26,21 +26,18 @@
|
||||
|
||||
#include <App/PropertyGeo.h>
|
||||
|
||||
#include "ViewProviderDocumentObject.h"
|
||||
#include "ViewProviderGeoFeatureGroup.h"
|
||||
|
||||
|
||||
namespace Gui {
|
||||
|
||||
class Document;
|
||||
|
||||
class GuiExport ViewProviderOrigin : public ViewProviderDocumentObject
|
||||
class GuiExport ViewProviderOrigin : public ViewProviderGeoFeatureGroup
|
||||
{
|
||||
PROPERTY_HEADER_WITH_OVERRIDE(Gui::ViewProviderOrigin);
|
||||
|
||||
public:
|
||||
/// Size of the origin as set by the part.
|
||||
App::PropertyVector Size;
|
||||
|
||||
/// constructor.
|
||||
ViewProviderOrigin();
|
||||
/// destructor.
|
||||
@@ -83,7 +80,7 @@ public:
|
||||
// default color for origini: light-blue (50, 150, 250, 255 stored as 0xRRGGBBAA)
|
||||
static const uint32_t defaultColor = 0x3296faff;
|
||||
protected:
|
||||
void onChanged(const App::Property* prop) override;
|
||||
void updateData(const App::Property*) override;
|
||||
bool onDelete(const std::vector<std::string> &) override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -55,8 +55,6 @@ ViewProviderOriginGroupExtension::ViewProviderOriginGroupExtension()
|
||||
|
||||
ViewProviderOriginGroupExtension::~ViewProviderOriginGroupExtension()
|
||||
{
|
||||
connectChangedObjectApp.disconnect();
|
||||
connectChangedObjectGui.disconnect();
|
||||
}
|
||||
|
||||
std::vector<App::DocumentObject*> ViewProviderOriginGroupExtension::constructChildren (
|
||||
@@ -89,126 +87,6 @@ std::vector<App::DocumentObject*> ViewProviderOriginGroupExtension::extensionCla
|
||||
return constructChildren ( ViewProviderGeoFeatureGroupExtension::extensionClaimChildren3D () );
|
||||
}
|
||||
|
||||
void ViewProviderOriginGroupExtension::extensionAttach(App::DocumentObject *pcObject) {
|
||||
ViewProviderGeoFeatureGroupExtension::extensionAttach ( pcObject );
|
||||
|
||||
App::Document *adoc = pcObject->getDocument ();
|
||||
Gui::Document *gdoc = Gui::Application::Instance->getDocument ( adoc ) ;
|
||||
|
||||
assert ( adoc );
|
||||
assert ( gdoc );
|
||||
|
||||
//NOLINTBEGIN
|
||||
connectChangedObjectApp = adoc->signalChangedObject.connect (
|
||||
std::bind ( &ViewProviderOriginGroupExtension::slotChangedObjectApp, this, sp::_1) );
|
||||
|
||||
connectChangedObjectGui = gdoc->signalChangedObject.connect (
|
||||
std::bind ( &ViewProviderOriginGroupExtension::slotChangedObjectGui, this, sp::_1) );
|
||||
//NOLINTEND
|
||||
}
|
||||
|
||||
void ViewProviderOriginGroupExtension::extensionUpdateData( const App::Property* prop ) {
|
||||
|
||||
auto* obj = getExtendedViewProvider()->getObject();
|
||||
auto* group = obj ? obj->getExtensionByType<App::OriginGroupExtension>() : nullptr;
|
||||
if ( group && prop == &group->Group ) {
|
||||
updateOriginSize();
|
||||
}
|
||||
|
||||
ViewProviderGeoFeatureGroupExtension::extensionUpdateData ( prop );
|
||||
}
|
||||
|
||||
void ViewProviderOriginGroupExtension::slotChangedObjectApp ( const App::DocumentObject& obj) {
|
||||
auto* ext = getExtendedViewProvider()->getObject();
|
||||
auto* group = ext ? ext->getExtensionByType<App::OriginGroupExtension>() : nullptr;
|
||||
if ( group && group->hasObject (&obj, /*recursive=*/ true ) ) {
|
||||
updateOriginSize ();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewProviderOriginGroupExtension::slotChangedObjectGui ( const Gui::ViewProviderDocumentObject& vp) {
|
||||
if ( !vp.isDerivedFrom ( Gui::ViewProviderDatum::getClassTypeId () )) {
|
||||
// Ignore origins to avoid infinite recursion (not likely in a well-formed document,
|
||||
// but may happen in documents designed in old versions of assembly branch )
|
||||
auto* ext = getExtendedViewProvider()->getObject();
|
||||
auto* group = ext ? ext->getExtensionByType<App::OriginGroupExtension>() : nullptr;
|
||||
App::DocumentObject *obj = vp.getObject ();
|
||||
|
||||
if ( group && obj && group->hasObject (obj, /*recursive=*/ true ) ) {
|
||||
updateOriginSize ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ViewProviderOriginGroupExtension::updateOriginSize () {
|
||||
auto owner = getExtendedViewProvider()->getObject();
|
||||
|
||||
if(!owner->isAttachedToDocument() ||
|
||||
owner->isRemoving() ||
|
||||
owner->getDocument()->testStatus(App::Document::Restoring))
|
||||
return;
|
||||
|
||||
auto* group = owner->getExtensionByType<App::OriginGroupExtension>();
|
||||
if(!group)
|
||||
return;
|
||||
|
||||
// obtain an Origin and it's ViewProvider
|
||||
App::Origin* origin = nullptr;
|
||||
Gui::ViewProviderOrigin* vpOrigin = nullptr;
|
||||
try {
|
||||
origin = group->getOrigin ();
|
||||
assert (origin);
|
||||
|
||||
Gui::ViewProvider *vp = Gui::Application::Instance->getViewProvider(origin);
|
||||
if (!vp) {
|
||||
Base::Console().Error ("No view provider linked to the Origin\n");
|
||||
return;
|
||||
}
|
||||
assert ( vp->isDerivedFrom ( Gui::ViewProviderOrigin::getClassTypeId () ) );
|
||||
vpOrigin = static_cast <Gui::ViewProviderOrigin *> ( vp );
|
||||
} catch (const Base::Exception &ex) {
|
||||
Base::Console().Error ("%s\n", ex.what() );
|
||||
return;
|
||||
}
|
||||
|
||||
Gui::Document* gdoc = getExtendedViewProvider()->getDocument();
|
||||
if(!gdoc)
|
||||
return;
|
||||
|
||||
Gui::MDIView* view = gdoc->getViewOfViewProvider(getExtendedViewProvider());
|
||||
if(!view)
|
||||
return;
|
||||
|
||||
Gui::View3DInventorViewer* viewer = static_cast<Gui::View3DInventor*>(view)->getViewer();
|
||||
SoGetBoundingBoxAction bboxAction(viewer->getSoRenderManager()->getViewportRegion());
|
||||
|
||||
// calculate the bounding box for out content
|
||||
SbBox3f bbox(0,0,0, 0,0,0);
|
||||
for(App::DocumentObject* obj : group->Group.getValues()) {
|
||||
ViewProvider *vp = Gui::Application::Instance->getViewProvider(obj);
|
||||
if (!vp) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bboxAction.apply ( vp->getRoot () );
|
||||
bbox.extendBy ( bboxAction.getBoundingBox () );
|
||||
};
|
||||
|
||||
// get the bounding box values
|
||||
SbVec3f max = bbox.getMax();
|
||||
SbVec3f min = bbox.getMin();
|
||||
|
||||
Base::Vector3d size;
|
||||
|
||||
for (uint_fast8_t i=0; i<3; i++) {
|
||||
size[i] = std::max ( fabs ( max[i] ), fabs ( min[i] ) );
|
||||
if (size[i] < 1e-7) { // TODO replace the magic values (2015-08-31, Fat-Zer)
|
||||
size[i] = ViewProviderOrigin::defaultSize();
|
||||
}
|
||||
}
|
||||
|
||||
vpOrigin->Size.setValue ( size * 1.3 );
|
||||
}
|
||||
|
||||
namespace Gui {
|
||||
EXTENSION_PROPERTY_SOURCE_TEMPLATE(Gui::ViewProviderOriginGroupExtensionPython, Gui::ViewProviderOriginGroupExtension)
|
||||
|
||||
@@ -42,21 +42,9 @@ public:
|
||||
std::vector<App::DocumentObject*> extensionClaimChildren()const override;
|
||||
std::vector<App::DocumentObject*> extensionClaimChildren3D()const override;
|
||||
|
||||
void extensionAttach(App::DocumentObject *pcObject) override;
|
||||
void extensionUpdateData(const App::Property* prop) override;
|
||||
|
||||
void updateOriginSize();
|
||||
|
||||
protected:
|
||||
void slotChangedObjectApp ( const App::DocumentObject& obj );
|
||||
void slotChangedObjectGui ( const Gui::ViewProviderDocumentObject& obj );
|
||||
|
||||
private:
|
||||
std::vector<App::DocumentObject*> constructChildren (
|
||||
const std::vector<App::DocumentObject*> &children ) const;
|
||||
|
||||
boost::signals2::connection connectChangedObjectApp;
|
||||
boost::signals2::connection connectChangedObjectGui;
|
||||
};
|
||||
|
||||
using ViewProviderOriginGroupExtensionPython = ViewProviderExtensionPythonT<Gui::ViewProviderOriginGroupExtension>;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <Inventor/nodes/SoText2.h>
|
||||
# include <Inventor/nodes/SoAsciiText.h>
|
||||
# include <Inventor/nodes/SoCoordinate3.h>
|
||||
# include <Inventor/nodes/SoFaceSet.h>
|
||||
@@ -36,6 +37,9 @@
|
||||
# include <Inventor/SbColor.h>
|
||||
#endif
|
||||
|
||||
#include <App/Datums.h>
|
||||
#include <Gui/ViewParams.h>
|
||||
|
||||
#include "ViewProviderPlane.h"
|
||||
#include "ViewProviderOrigin.h"
|
||||
|
||||
@@ -48,43 +52,85 @@ PROPERTY_SOURCE(Gui::ViewProviderPlane, Gui::ViewProviderDatum)
|
||||
ViewProviderPlane::ViewProviderPlane()
|
||||
{
|
||||
sPixmap = "Std_Plane";
|
||||
lineThickness = 1.0;
|
||||
}
|
||||
|
||||
ViewProviderPlane::~ViewProviderPlane() = default;
|
||||
|
||||
void ViewProviderPlane::attach(App::DocumentObject * obj) {
|
||||
ViewProviderDatum::attach(obj);
|
||||
static const float size = ViewProviderOrigin::defaultSize ();
|
||||
|
||||
static const SbVec3f verts[4] = {
|
||||
SbVec3f(size,size,0), SbVec3f(size,-size,0),
|
||||
SbVec3f(-size,-size,0), SbVec3f(-size,size,0),
|
||||
};
|
||||
const char* name = pcObject->getNameInDocument();
|
||||
|
||||
// Setup colors
|
||||
auto material = new SoMaterial();
|
||||
SbColor color;
|
||||
material->transparency.setValue(0.95f);
|
||||
float alpha = 0.0f;
|
||||
float lineTransparency = 0.5;
|
||||
bool noRole = false;
|
||||
auto planesRoles = App::LocalCoordinateSystem::PlaneRoles;
|
||||
if (strncmp(name, planesRoles[0], strlen(planesRoles[0])) == 0) {
|
||||
// XY-axis: blue
|
||||
ShapeAppearance.setDiffuseColor(ViewParams::instance()->getAxisZColor());
|
||||
ShapeAppearance.setTransparency(lineTransparency);
|
||||
color.setPackedValue(ViewParams::instance()->getAxisZColor(), alpha);
|
||||
}
|
||||
else if (strncmp(name, planesRoles[1], strlen(planesRoles[1])) == 0) {
|
||||
// XZ-axis: green
|
||||
ShapeAppearance.setDiffuseColor(ViewParams::instance()->getAxisYColor());
|
||||
ShapeAppearance.setTransparency(lineTransparency);
|
||||
color.setPackedValue(ViewParams::instance()->getAxisYColor(), alpha);
|
||||
}
|
||||
else if (strncmp(name, planesRoles[2], strlen(planesRoles[2])) == 0) {
|
||||
// YZ-axis: red
|
||||
ShapeAppearance.setDiffuseColor(ViewParams::instance()->getAxisXColor());
|
||||
ShapeAppearance.setTransparency(lineTransparency);
|
||||
color.setPackedValue(ViewParams::instance()->getAxisXColor(), alpha);
|
||||
}
|
||||
else {
|
||||
noRole = true;
|
||||
}
|
||||
|
||||
static const float size = ViewProviderOrigin::defaultSize() * 0.6; //NOLINT
|
||||
static const float startSize = 0.25 * size; //NOLINT
|
||||
|
||||
|
||||
SbVec3f verts[4];
|
||||
if (noRole) {
|
||||
verts[0] = SbVec3f(size, size, 0);
|
||||
verts[1] = SbVec3f(size, -size, 0);
|
||||
verts[2] = SbVec3f(-size, -size, 0);
|
||||
verts[3] = SbVec3f(-size, size, 0);
|
||||
}
|
||||
else {
|
||||
verts[0] = SbVec3f(size, size, 0);
|
||||
verts[1] = SbVec3f(size, startSize, 0);
|
||||
verts[2] = SbVec3f(startSize, startSize, 0);
|
||||
verts[3] = SbVec3f(startSize, size, 0);
|
||||
}
|
||||
|
||||
|
||||
// indexes used to create the edges
|
||||
static const int32_t lines[6] = { 0, 1, 2, 3, 0, -1 };
|
||||
|
||||
SoSeparator *sep = getOriginFeatureRoot ();
|
||||
SoSeparator* sep = getRoot();
|
||||
|
||||
auto pCoords = new SoCoordinate3 ();
|
||||
pCoords->point.setNum (4);
|
||||
pCoords->point.setValues ( 0, 4, verts );
|
||||
sep->addChild ( pCoords );
|
||||
auto pCoords = new SoCoordinate3();
|
||||
pCoords->point.setNum(4);
|
||||
pCoords->point.setValues(0, 4, verts);
|
||||
sep->addChild(pCoords);
|
||||
|
||||
auto pLines = new SoIndexedLineSet ();
|
||||
auto pLines = new SoIndexedLineSet();
|
||||
pLines->coordIndex.setNum(6);
|
||||
pLines->coordIndex.setValues(0, 6, lines);
|
||||
sep->addChild ( pLines );
|
||||
sep->addChild(pLines);
|
||||
|
||||
// add semi transparent face
|
||||
auto faceSeparator = new SoSeparator();
|
||||
sep->addChild(faceSeparator);
|
||||
|
||||
auto material = new SoMaterial();
|
||||
material->transparency.setValue(0.95f);
|
||||
SbColor color;
|
||||
float alpha = 0.0f;
|
||||
color.setPackedValue(ViewProviderOrigin::defaultColor, alpha);
|
||||
|
||||
material->ambientColor.setValue(color);
|
||||
material->diffuseColor.setValue(color);
|
||||
faceSeparator->addChild(material);
|
||||
@@ -95,9 +141,8 @@ void ViewProviderPlane::attach(App::DocumentObject * obj) {
|
||||
shapeHints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE;
|
||||
faceSeparator->addChild(shapeHints);
|
||||
|
||||
// disable picking
|
||||
auto pickStyle = new SoPickStyle();
|
||||
pickStyle->style = SoPickStyle::UNPICKABLE;
|
||||
pickStyle->style = SoPickStyle::SHAPE_ON_TOP;
|
||||
faceSeparator->addChild(pickStyle);
|
||||
|
||||
auto faceSet = new SoFaceSet();
|
||||
@@ -106,13 +151,9 @@ void ViewProviderPlane::attach(App::DocumentObject * obj) {
|
||||
faceSet->vertexProperty.setValue(vertexProperty);
|
||||
faceSeparator->addChild(faceSet);
|
||||
|
||||
auto textTranslation = new SoTranslation ();
|
||||
textTranslation->translation.setValue ( SbVec3f ( -size * 49. / 50., size * 9./10., 0 ) );
|
||||
sep->addChild ( textTranslation );
|
||||
|
||||
auto ps = new SoPickStyle();
|
||||
ps->style.setValue(SoPickStyle::BOUNDING_BOX);
|
||||
sep->addChild(ps);
|
||||
|
||||
sep->addChild ( getLabel () );
|
||||
sep->addChild(getLabel());
|
||||
}
|
||||
|
||||
70
src/Gui/ViewProviderPoint.cpp
Normal file
70
src/Gui/ViewProviderPoint.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/****************************************************************************
|
||||
* *
|
||||
* Copyright (c) 2024 Ondsel (PL Boyer) <development@ondsel.com> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD 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 *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <Inventor/nodes/SoSphere.h>
|
||||
# include <Inventor/nodes/SoCoordinate3.h>
|
||||
# include <Inventor/nodes/SoIndexedLineSet.h>
|
||||
# include <Inventor/nodes/SoPickStyle.h>
|
||||
# include <Inventor/nodes/SoSeparator.h>
|
||||
# include <Inventor/nodes/SoTranslation.h>
|
||||
#endif
|
||||
|
||||
#include "ViewProviderPoint.h"
|
||||
#include "ViewProviderOrigin.h"
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
PROPERTY_SOURCE(Gui::ViewProviderPoint, Gui::ViewProviderDatum)
|
||||
|
||||
ViewProviderPoint::ViewProviderPoint()
|
||||
{
|
||||
sPixmap = "Std_Point"; // Set the icon for the point
|
||||
}
|
||||
|
||||
ViewProviderPoint::~ViewProviderPoint() = default;
|
||||
|
||||
void ViewProviderPoint::attach(App::DocumentObject * obj) {
|
||||
ViewProviderDatum::attach(obj);
|
||||
|
||||
// The coordinates for the point (single vertex at the origin)
|
||||
static const SbVec3f point = SbVec3f(0, 0, 0);
|
||||
|
||||
SoSeparator* sep = getRoot();
|
||||
|
||||
auto pCoords = new SoCoordinate3();
|
||||
pCoords->point.setNum(1);
|
||||
pCoords->point.setValue(point);
|
||||
sep->addChild(pCoords);
|
||||
|
||||
auto sphere = new SoSphere();
|
||||
sphere->radius.setValue(1.0);
|
||||
sep->addChild(sphere);
|
||||
|
||||
// Add pick style to define how the point can be selected
|
||||
auto ps = new SoPickStyle();
|
||||
ps->style.setValue(SoPickStyle::BOUNDING_BOX);
|
||||
sep->addChild(ps);
|
||||
}
|
||||
46
src/Gui/ViewProviderPoint.h
Normal file
46
src/Gui/ViewProviderPoint.h
Normal file
@@ -0,0 +1,46 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/****************************************************************************
|
||||
* *
|
||||
* Copyright (c) 2024 Ondsel (PL Boyer) <development@ondsel.com> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD 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 *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef GUI_ViewProviderPoint_H
|
||||
#define GUI_ViewProviderPoint_H
|
||||
|
||||
#include "ViewProviderDatum.h"
|
||||
|
||||
namespace Gui
|
||||
{
|
||||
|
||||
class GuiExport ViewProviderPoint : public ViewProviderDatum {
|
||||
PROPERTY_HEADER_WITH_OVERRIDE(Gui::ViewProviderPoint);
|
||||
public:
|
||||
/// Constructor
|
||||
ViewProviderPoint();
|
||||
~ViewProviderPoint() override;
|
||||
|
||||
void attach ( App::DocumentObject * ) override;
|
||||
};
|
||||
|
||||
} //namespace Gui
|
||||
|
||||
|
||||
#endif // GUI_ViewProviderPoint_H
|
||||
@@ -31,6 +31,7 @@
|
||||
# include <BRepBndLib.hxx>
|
||||
# include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
# include <BRepBuilderAPI_MakeFace.hxx>
|
||||
# include <BRepBuilderAPI_MakeVertex.hxx>
|
||||
# include <BRepBuilderAPI_MakeShape.hxx>
|
||||
# include <BRepBuilderAPI_MakeVertex.hxx>
|
||||
# include <BRepExtrema_DistShapeShape.hxx>
|
||||
@@ -1020,6 +1021,14 @@ static TopoShape _getTopoShape(const App::DocumentObject* obj,
|
||||
}
|
||||
shape = TopoShape(tag, hasher, _shape);
|
||||
}
|
||||
else if (linked->isDerivedFrom(App::Point::getClassTypeId())) {
|
||||
static TopoDS_Shape _shape;
|
||||
if (_shape.IsNull()) {
|
||||
BRepBuilderAPI_MakeVertex builder(gp_Pnt(0, 0, 0));
|
||||
_shape = builder.Shape();
|
||||
}
|
||||
shape = TopoShape(tag, hasher, _shape);
|
||||
}
|
||||
else if (linked->isDerivedFrom(App::Placement::getClassTypeId())) {
|
||||
auto element = Data::findElementName(subname);
|
||||
if (element) {
|
||||
|
||||
@@ -64,6 +64,6 @@ class ColorTransparencyTest(unittest.TestCase):
|
||||
obj = self._doc.addObject('App::Origin')
|
||||
t = self._doc.findObjects('App::Plane')[0].ViewObject.Transparency
|
||||
|
||||
self.assertEqual(t, 0,
|
||||
'transparency of App::Plane object is {} instead of 0'.format(t))
|
||||
self.assertEqual(t, 50,
|
||||
'transparency of App::Plane object is {} instead of 50'.format(t))
|
||||
|
||||
|
||||
@@ -74,8 +74,6 @@ ViewProviderBody::ViewProviderBody()
|
||||
|
||||
ViewProviderBody::~ViewProviderBody()
|
||||
{
|
||||
connectChangedObjectApp.disconnect();
|
||||
connectChangedObjectGui.disconnect();
|
||||
}
|
||||
|
||||
void ViewProviderBody::attach(App::DocumentObject *pcFeat)
|
||||
@@ -85,20 +83,6 @@ void ViewProviderBody::attach(App::DocumentObject *pcFeat)
|
||||
|
||||
//set default display mode
|
||||
onChanged(&DisplayModeBody);
|
||||
|
||||
App::Document *adoc = pcObject->getDocument ();
|
||||
Gui::Document *gdoc = Gui::Application::Instance->getDocument ( adoc ) ;
|
||||
|
||||
assert ( adoc );
|
||||
assert ( gdoc );
|
||||
|
||||
//NOLINTBEGIN
|
||||
connectChangedObjectApp = adoc->signalChangedObject.connect (
|
||||
std::bind ( &ViewProviderBody::slotChangedObjectApp, this, sp::_1, sp::_2) );
|
||||
|
||||
connectChangedObjectGui = gdoc->signalChangedObject.connect (
|
||||
std::bind ( &ViewProviderBody::slotChangedObjectGui, this, sp::_1, sp::_2) );
|
||||
//NOLINTEND
|
||||
}
|
||||
|
||||
// TODO on activating the body switch to the "Through" mode (2015-09-05, Fat-Zer)
|
||||
@@ -228,8 +212,6 @@ void ViewProviderBody::updateData(const App::Property* prop)
|
||||
PartDesign::Body* body = static_cast<PartDesign::Body*>(getObject());
|
||||
|
||||
if (prop == &body->Group || prop == &body->BaseFeature) {
|
||||
// update sizes of origins and datums
|
||||
updateOriginDatumSize ();
|
||||
//ensure all model features are in visual body mode
|
||||
setVisualBodyMode(true);
|
||||
}
|
||||
@@ -252,122 +234,6 @@ void ViewProviderBody::updateData(const App::Property* prop)
|
||||
PartGui::ViewProviderPart::updateData(prop);
|
||||
}
|
||||
|
||||
void ViewProviderBody::slotChangedObjectApp ( const App::DocumentObject& obj, const App::Property& prop ) {
|
||||
|
||||
if(App::GetApplication().isRestoring())
|
||||
return;
|
||||
|
||||
if (!obj.isDerivedFrom ( Part::Feature::getClassTypeId () ) ||
|
||||
obj.isDerivedFrom ( Part::BodyBase::getClassTypeId () ) ) { // we are interested only in Part::Features, not in bodies
|
||||
return;
|
||||
}
|
||||
|
||||
const Part::Feature *feat = static_cast <const Part::Feature *>(&obj);
|
||||
|
||||
if ( &feat->Shape != &prop && &feat->Placement != &prop) { // react only on changes in shapes and placement
|
||||
return;
|
||||
}
|
||||
|
||||
PartDesign::Body *body = static_cast<PartDesign::Body*> ( getObject() );
|
||||
if ( body && body->hasObject (&obj ) ) {
|
||||
updateOriginDatumSize ();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewProviderBody::slotChangedObjectGui (
|
||||
const Gui::ViewProviderDocumentObject& vp, const App::Property& prop )
|
||||
{
|
||||
if (&vp.Visibility != &prop) { // react only on visibility changes
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !vp.isDerivedFrom ( Gui::ViewProviderOrigin::getClassTypeId () ) &&
|
||||
!vp.isDerivedFrom ( Gui::ViewProviderDatum::getClassTypeId () ) ) {
|
||||
// Ignore origins to avoid infinite recursion (not likely in a well-formed document,
|
||||
// but may happen in documents designed in old versions of assembly branch )
|
||||
return;
|
||||
}
|
||||
|
||||
PartDesign::Body *body = static_cast<PartDesign::Body*> ( getObject() );
|
||||
App::DocumentObject *obj = vp.getObject ();
|
||||
|
||||
if ( body && obj && body->hasObject ( obj ) ) {
|
||||
updateOriginDatumSize ();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewProviderBody::updateOriginDatumSize () {
|
||||
PartDesign::Body *body = static_cast<PartDesign::Body *> ( getObject() );
|
||||
|
||||
// Use different bounding boxes for datums and for origins:
|
||||
Gui::Document* gdoc = Gui::Application::Instance->getDocument(getObject()->getDocument());
|
||||
if(!gdoc)
|
||||
return;
|
||||
|
||||
Gui::MDIView* view = gdoc->getViewOfViewProvider(this);
|
||||
if(!view)
|
||||
return;
|
||||
|
||||
Gui::View3DInventorViewer* viewer = static_cast<Gui::View3DInventor*>(view)->getViewer();
|
||||
SoGetBoundingBoxAction bboxAction(viewer->getSoRenderManager()->getViewportRegion());
|
||||
|
||||
const auto & model = body->getFullModel ();
|
||||
|
||||
// BBox for Datums is calculated from all visible objects but treating datums as their basepoints only
|
||||
SbBox3f bboxDatums = ViewProviderDatum::getRelevantBoundBox ( bboxAction, model );
|
||||
// BBox for origin should take into account datums size also
|
||||
SbBox3f bboxOrigins = bboxDatums;
|
||||
|
||||
for(App::DocumentObject* obj : model) {
|
||||
if ( obj->isDerivedFrom ( Part::Datum::getClassTypeId () ) ) {
|
||||
ViewProvider *vp = Gui::Application::Instance->getViewProvider(obj);
|
||||
if (!vp) { continue; }
|
||||
|
||||
ViewProviderDatum *vpDatum = static_cast <ViewProviderDatum *> (vp) ;
|
||||
|
||||
vpDatum->setExtents ( bboxDatums );
|
||||
|
||||
bboxAction.apply ( vp->getRoot () );
|
||||
bboxOrigins.extendBy ( bboxAction.getBoundingBox () );
|
||||
}
|
||||
}
|
||||
|
||||
// get the bounding box values
|
||||
SbVec3f max = bboxOrigins.getMax();
|
||||
SbVec3f min = bboxOrigins.getMin();
|
||||
|
||||
// obtain an Origin and it's ViewProvider
|
||||
App::Origin* origin = nullptr;
|
||||
Gui::ViewProviderOrigin* vpOrigin = nullptr;
|
||||
try {
|
||||
origin = body->getOrigin ();
|
||||
assert (origin);
|
||||
|
||||
Gui::ViewProvider *vp = Gui::Application::Instance->getViewProvider(origin);
|
||||
if (!vp) {
|
||||
throw Base::ValueError ("No view provider linked to the Origin");
|
||||
}
|
||||
assert ( vp->isDerivedFrom ( Gui::ViewProviderOrigin::getClassTypeId () ) );
|
||||
vpOrigin = static_cast <Gui::ViewProviderOrigin *> ( vp );
|
||||
} catch (const Base::Exception &ex) {
|
||||
if(!getExtendedViewProvider()->getDocument()->getDocument()->testStatus(App::Document::Restoring))
|
||||
Base::Console().Error ("%s\n", ex.what() );
|
||||
return;
|
||||
}
|
||||
|
||||
// calculate the desired origin size
|
||||
Base::Vector3d size;
|
||||
|
||||
for (uint_fast8_t i=0; i<3; i++) {
|
||||
size[i] = std::max ( fabs ( max[i] ), fabs ( min[i] ) );
|
||||
if (size[i] < Precision::Confusion() ) {
|
||||
size[i] = Gui::ViewProviderOrigin::defaultSize();
|
||||
}
|
||||
}
|
||||
|
||||
vpOrigin->Size.setValue ( size*1.2 );
|
||||
}
|
||||
|
||||
void ViewProviderBody::onChanged(const App::Property* prop) {
|
||||
|
||||
if(prop == &DisplayModeBody) {
|
||||
|
||||
@@ -72,9 +72,6 @@ public:
|
||||
///unify children visuals
|
||||
void onChanged(const App::Property* prop) override;
|
||||
|
||||
/// Update the sizes of origin and datums
|
||||
void updateOriginDatumSize ();
|
||||
|
||||
/**
|
||||
* Return the bounding box of visible features
|
||||
* @note datums are counted as their base point only
|
||||
@@ -89,9 +86,6 @@ public:
|
||||
void dropObject(App::DocumentObject*) override;
|
||||
|
||||
protected:
|
||||
void slotChangedObjectApp ( const App::DocumentObject& obj, const App::Property& prop );
|
||||
void slotChangedObjectGui ( const Gui::ViewProviderDocumentObject& obj, const App::Property& prop );
|
||||
|
||||
/// Copy over all visual properties to the child features
|
||||
void unifyVisualProperty(const App::Property* prop);
|
||||
/// Set Feature viewprovider into visual body mode
|
||||
@@ -99,9 +93,6 @@ protected:
|
||||
|
||||
private:
|
||||
static const char* BodyModeEnum[];
|
||||
|
||||
boost::signals2::connection connectChangedObjectApp;
|
||||
boost::signals2::connection connectChangedObjectGui;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user