Skip to content

Commit

Permalink
Merge branch 'FreeCAD:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
rostskadat authored Feb 14, 2024
2 parents ccae2e7 + 69741a7 commit 88b7335
Show file tree
Hide file tree
Showing 79 changed files with 9,185 additions and 678 deletions.
4 changes: 4 additions & 0 deletions cMake/FreeCAD_Helpers/SetupLibOndselSolver.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
macro(SetupOndselSolverCpp)
# -------------------------------- OndselSolver --------------------------------
find_package(OndselSolver REQUIRED)
endmacro(SetupOndselSolverCpp)
2 changes: 1 addition & 1 deletion src/3rdParty/OndselSolver
Submodule OndselSolver updated 433 files
28 changes: 0 additions & 28 deletions src/App/Expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
#include <sstream>
#include <stack>
#include <string>
#include <regex>

#include <App/Application.h>
#include <App/DocumentObject.h>
Expand Down Expand Up @@ -518,29 +517,6 @@ Py::Object pyFromQuantity(const Quantity &quantity) {
}
}

static const std::regex REGEX_QUANTITY(
R"(\s*)"
R"(([-+]?[0-9]*[.]?[0-9]+([eE][-+]?[0-9]+)?))" // value
R"(\s*)"
R"(([^\s]+)?)" // unit
R"(\s*)"
);

// https://github.com/FreeCAD/FreeCAD/issues/11825
Quantity parseQuantityFromText(std::string text) {
std::smatch match;
if (std::regex_match(text, match, REGEX_QUANTITY)) {
std::string value_text = match[1];
std::string unit_text = match[3];
double value = std::stod(value_text);
Unit unit = Unit(QString::fromStdString(unit_text));
return Quantity(value, unit);
} else {
std::string error_message = "Failed to parse to Quantity: text='" + text + "'";
PARSER_THROW(error_message);
}
}

Quantity anyToQuantity(const App::any &value, const char *msg) {
if (is_type(value,typeid(Quantity))) {
return cast<Quantity>(value);
Expand All @@ -554,10 +530,6 @@ Quantity anyToQuantity(const App::any &value, const char *msg) {
return Quantity(cast<float>(value));
} else if (is_type(value,typeid(double))) {
return Quantity(cast<double>(value));
} else if (is_type(value,typeid(const char*))) {
return parseQuantityFromText(std::string(cast<const char*>(value)));
} else if (is_type(value,typeid(std::string))) {
return parseQuantityFromText(cast<std::string>(value));
}
if(!msg)
msg = "Failed to convert to Quantity";
Expand Down
1 change: 0 additions & 1 deletion src/App/Expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ using ExpressionPtr = std::unique_ptr<Expression>;

AppExport bool isAnyEqual(const App::any &v1, const App::any &v2);
AppExport Base::Quantity anyToQuantity(const App::any &value, const char *errmsg = nullptr);
AppExport Base::Quantity parseQuantityFromText(std::string text);

// Map of depending objects to a map of depending property name to the full referencing object identifier
using ExpressionDeps = std::map<App::DocumentObject*, std::map<std::string, std::vector<ObjectIdentifier> > >;
Expand Down
16 changes: 16 additions & 0 deletions src/Base/Vector3D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,22 @@ float_type Vector3<float_type>::GetAngle(const Vector3& rcVect) const
return float_type(acos(dot));
}

template<class float_type>
float_type Vector3<float_type>::GetAngleOriented(const Vector3& rcVect, const Vector3& norm) const
{
float_type angle = GetAngle(rcVect);

Vector3<float_type> crossProduct = Cross(rcVect);

// Use dot product to determine the sign
float_type dot = crossProduct.Dot(norm);
if (dot < 0) {
angle = 2 * traits_type::pi() - angle;
}

return angle;
}

template<class float_type>
void Vector3<float_type>::TransformToCoordinateSystem(const Vector3& rclBase,
const Vector3& rclDirX,
Expand Down
3 changes: 3 additions & 0 deletions src/Base/Vector3D.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,9 @@ class Vector3
bool IsNull() const;
/// Get angle between both vectors. The returned value lies in the interval [0,pi].
float_type GetAngle(const Vector3& rcVect) const;
/// Get oriented angle between both vectors using a normal. The returned value lies in the
/// interval [0,2*pi].
float_type GetAngleOriented(const Vector3& rcVect, const Vector3& norm) const;
/** Transforms this point to the coordinate system defined by origin \a rclBase,
* vector \a vector rclDirX and vector \a vector rclDirY.
* \note \a rclDirX must be perpendicular to \a rclDirY, i.e. \a rclDirX * \a rclDirY = 0..
Expand Down
2 changes: 1 addition & 1 deletion src/Gui/CommandDoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1341,7 +1341,7 @@ void StdCmdDelete::activated(int iMsg)
ViewProviderDocumentObject *vpedit = nullptr;
if(editDoc)
vpedit = dynamic_cast<ViewProviderDocumentObject*>(editDoc->getInEdit());
if(vpedit) {
if(vpedit && !vpedit->acceptDeletionsInEdit()) {
for(auto &sel : Selection().getSelectionEx(editDoc->getDocument()->getName())) {
if(sel.getObject() == vpedit->getObject()) {
if (!sel.getSubNames().empty()) {
Expand Down
2 changes: 1 addition & 1 deletion src/Gui/PreferencePages/DlgSettingsWorkbenchesImp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ QStringList DlgSettingsWorkbenchesImp::getDisabledWorkbenches()
ParameterGrp::handle hGrp;

hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Workbenches");
disabled_wbs = QString::fromStdString(hGrp->GetASCII("Disabled", "NoneWorkbench,TestWorkbench,AssemblyWorkbench"));
disabled_wbs = QString::fromStdString(hGrp->GetASCII("Disabled", "NoneWorkbench,TestWorkbench"));
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
unfiltered_disabled_wbs_list = disabled_wbs.split(QLatin1String(","), Qt::SkipEmptyParts);
#else
Expand Down
104 changes: 103 additions & 1 deletion src/Gui/View3DInventorViewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2647,6 +2647,108 @@ SbVec2f View3DInventorViewer::getNormalizedPosition(const SbVec2s& pnt) const
return {pX, pY};
}

SbVec3f View3DInventorViewer::getPointOnXYPlaneOfPlacement(const SbVec2s& pnt, Base::Placement& plc) const
{
SbVec2f pnt2d = getNormalizedPosition(pnt);
SoCamera* pCam = this->getSoRenderManager()->getCamera();

if (!pCam) {
// return invalid point
return {};
}

SbViewVolume vol = pCam->getViewVolume();
SbLine line;
vol.projectPointToLine(pnt2d, line);

// Calculate the plane using plc
Base::Rotation rot = plc.getRotation();
Base::Vector3d normalVector = rot.multVec(Base::Vector3d(0, 0, 1));
SbVec3f planeNormal(normalVector.x, normalVector.y, normalVector.z);

// Get the position and convert Base::Vector3d to SbVec3f
Base::Vector3d pos = plc.getPosition();
SbVec3f planePosition(pos.x, pos.y, pos.z);
SbPlane xyPlane(planeNormal, planePosition);

SbVec3f pt;
if (xyPlane.intersect(line, pt)) {
return pt; // Intersection point on the XY plane
}
else {
// No intersection found
return {};
}

return pt;
}

SbVec3f projectPointOntoPlane(const SbVec3f& point, const SbPlane& plane) {
SbVec3f planeNormal = plane.getNormal();
float d = plane.getDistanceFromOrigin();
float distance = planeNormal.dot(point) + d;
return point - planeNormal * distance;
}

// Project a line onto a plane
SbLine projectLineOntoPlane(const SbVec3f& p1, const SbVec3f& p2, const SbPlane& plane) {
SbVec3f projectedPoint1 = projectPointOntoPlane(p1, plane);
SbVec3f projectedPoint2 = projectPointOntoPlane(p2, plane);
return SbLine(projectedPoint1, projectedPoint2);
}

SbVec3f intersection(const SbVec3f& p11, const SbVec3f& p12, const SbVec3f& p21, const SbVec3f& p22)
{
SbVec3f da = p12 - p11;
SbVec3f db = p22 - p21;
SbVec3f dc = p21 - p11;

double s = (dc.cross(db)).dot(da.cross(db)) / da.cross(db).sqrLength();
return p11 + da * s;
}

SbVec3f View3DInventorViewer::getPointOnLine(const SbVec2s& pnt, const SbVec3f& axisCenter, const SbVec3f& axis) const
{
SbVec2f pnt2d = getNormalizedPosition(pnt);
SoCamera* pCam = this->getSoRenderManager()->getCamera();

if (!pCam) {
// return invalid point
return {};
}

// First we get pnt projection on the focal plane
SbViewVolume vol = pCam->getViewVolume();

float nearDist = pCam->nearDistance.getValue();
float farDist = pCam->farDistance.getValue();
float focalDist = pCam->focalDistance.getValue();

if (focalDist < nearDist || focalDist > farDist) {
focalDist = 0.5F * (nearDist + farDist); // NOLINT
}

SbLine line;
SbVec3f pt, ptOnFocalPlaneAndOnLine, ptOnFocalPlane;
SbPlane focalPlane = vol.getPlane(focalDist);
vol.projectPointToLine(pnt2d, line);
focalPlane.intersect(line, ptOnFocalPlane);

SbLine projectedLine = projectLineOntoPlane(axisCenter, axisCenter + axis, focalPlane);
ptOnFocalPlaneAndOnLine = projectedLine.getClosestPoint(ptOnFocalPlane);

// now we need the intersection point between
// - the line passing by ptOnFocalPlaneAndOnLine normal to focalPlane
// - The line (axisCenter, axisCenter + axis)

// Line normal to focal plane through ptOnFocalPlane
SbLine normalLine(ptOnFocalPlane, ptOnFocalPlane + focalPlane.getNormal());
SbLine axisLine(axisCenter, axisCenter + axis);
pt = intersection(ptOnFocalPlane, ptOnFocalPlane + focalPlane.getNormal(), axisCenter, axisCenter + axis);

return pt;
}

SbVec3f View3DInventorViewer::getPointOnFocalPlane(const SbVec2s& pnt) const
{
SbVec2f pnt2d = getNormalizedPosition(pnt);
Expand Down Expand Up @@ -3975,4 +4077,4 @@ void View3DInventorViewer::dragLeaveEvent(QDragLeaveEvent* ev)
inherited::dragLeaveEvent(ev);
}

#include "moc_View3DInventorViewer.cpp"
#include "moc_View3DInventorViewer.cpp" // NOLINT
6 changes: 6 additions & 0 deletions src/Gui/View3DInventorViewer.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,12 @@ class GuiExport View3DInventorViewer : public Quarter::SoQTQuarterAdaptor, publi
/** Returns the 3d point on the focal plane to the given 2d point. */
SbVec3f getPointOnFocalPlane(const SbVec2s&) const;

/** Returns the 3d point on a line to the given 2d point. */
SbVec3f getPointOnLine(const SbVec2s&, const SbVec3f& axisCenter, const SbVec3f& axis) const;

/** Returns the 3d point on the XY plane of a placement to the given 2d point. */
SbVec3f getPointOnXYPlaneOfPlacement(const SbVec2s&, Base::Placement&) const;

/** Returns the 2d coordinates on the viewport to the given 3d point. */
SbVec2s getPointOnViewport(const SbVec3f&) const;

Expand Down
2 changes: 2 additions & 0 deletions src/Gui/ViewProviderDocumentObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ class GuiExport ViewProviderDocumentObject : public ViewProvider
App::DocumentObject *getObject() const {return pcObject;}
/// Asks the view provider if the given object can be deleted.
bool canDelete(App::DocumentObject* obj) const override;
/// Ask the view provider if it accepts object deletions while in edit
virtual bool acceptDeletionsInEdit() { return false; }
/// Get the GUI document to this ViewProvider object
Gui::Document* getDocument() const;
/// Get the python wrapper for that ViewProvider
Expand Down
4 changes: 2 additions & 2 deletions src/Mod/AddonManager/Addon.py
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ def disable_workbench(self):
wbName = self.get_workbench_name()

# Add the wb to the list of disabled if it was not already
disabled_wbs = pref.GetString("Disabled", "NoneWorkbench,TestWorkbench,AssemblyWorkbench")
disabled_wbs = pref.GetString("Disabled", "NoneWorkbench,TestWorkbench")
# print(f"start disabling {disabled_wbs}")
disabled_wbs_list = disabled_wbs.split(",")
if not (wbName in disabled_wbs_list):

Check warning on line 627 in src/Mod/AddonManager/Addon.py

View workflow job for this annotation

GitHub Actions / Lint / Lint

Unnecessary parens after 'not' keyword (superfluous-parens)
Expand Down Expand Up @@ -652,7 +652,7 @@ def desinstall_workbench(self):
def remove_from_disabled_wbs(self, wbName: str):
pref = fci.ParamGet("User parameter:BaseApp/Preferences/Workbenches")

disabled_wbs = pref.GetString("Disabled", "NoneWorkbench,TestWorkbench,AssemblyWorkbench")
disabled_wbs = pref.GetString("Disabled", "NoneWorkbench,TestWorkbench")
# print(f"start enabling : {disabled_wbs}")
disabled_wbs_list = disabled_wbs.split(",")
disabled_wbs = ""
Expand Down
63 changes: 63 additions & 0 deletions src/Mod/Assembly/App/AppAssembly.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/****************************************************************************
* *
* Copyright (c) 2023 Ondsel <[email protected]> *
* *
* 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"

#include <Base/Console.h>
#include <Base/Interpreter.h>
#include <Base/PyObjectBase.h>

#include "AssemblyObject.h"
#include "JointGroup.h"


namespace Assembly
{
extern PyObject* initModule();
}

/* Python entry */
PyMOD_INIT_FUNC(AssemblyApp)
{
// load dependent module
try {
Base::Interpreter().runString("import Part");
}
catch (const Base::Exception& e) {
PyErr_SetString(PyExc_ImportError, e.what());
PyMOD_Return(nullptr);
}

PyObject* mod = Assembly::initModule();
Base::Console().Log("Loading Assembly module... done\n");


// 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.

Assembly::AssemblyObject ::init();
Assembly::JointGroup ::init();

PyMOD_Return(mod);
}
47 changes: 47 additions & 0 deletions src/Mod/Assembly/App/AppAssemblyPy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/****************************************************************************
* *
* Copyright (c) 2023 Ondsel <[email protected]> *
* *
* 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"

#include <Base/Interpreter.h>
#include <Base/Tools.h>


namespace Assembly
{
class Module: public Py::ExtensionModule<Module>
{
public:
Module()
: Py::ExtensionModule<Module>("AssemblyApp")
{
initialize("This module is the Assembly module."); // register with Python
}
};

PyObject* initModule()
{
return Base::Interpreter().addModule(new Module);
}

} // namespace Assembly
Loading

0 comments on commit 88b7335

Please sign in to comment.