Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/Mod/Sketcher/App/GeoList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ Base::Vector3d GeoListModel<T>::getPoint(const Part::Geometry* geo, Sketcher::Po
else if (pos == PointPos::end) {
return lineSeg->getEndPoint();
}
else if (pos == PointPos::mid) {
// Experimental line-midpoint vertex (see commit revert note).
return (lineSeg->getStartPoint() + lineSeg->getEndPoint()) / 2.0;
}
}
else if (geo->is<Part::GeomCircle>()) {
const Part::GeomCircle* circle = static_cast<const Part::GeomCircle*>(geo);
Expand Down Expand Up @@ -304,6 +308,10 @@ void GeoListModel<T>::rebuildVertexIndex() const
) {
addGeoElement(geoId, PointPos::start);
addGeoElement(geoId, PointPos::end);
// Experimental line-midpoint vertex (see commit revert note).
if (type == Part::GeomLineSegment::getClassTypeId()) {
addGeoElement(geoId, PointPos::mid);
}
}
else if (
type == Part::GeomCircle::getClassTypeId() || type == Part::GeomEllipse::getClassTypeId()
Expand Down
20 changes: 20 additions & 0 deletions src/Mod/Sketcher/App/Sketch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,19 @@ int Sketch::addLineSegment(const Part::GeomLineSegment& lineSegment, bool fixed)
Points.push_back(p1);
Points.push_back(p2);

// Expose the line midpoint as a real vertex so it can be snapped to and
// constrained like any other point. It is a free parameter tied to the
// endpoints by an internal (solver-only, never serialized) symmetric
// constraint below, so constraining the midpoint moves the line.
// (Experimental: see the revert note in the commit message.)
GCS::Point pmid;
params.push_back(new double((start.x + end.x) / 2));
params.push_back(new double((start.y + end.y) / 2));
pmid.x = params[params.size() - 2];
pmid.y = params[params.size() - 1];
def.midPointId = Points.size();
Points.push_back(pmid);

// set the line for later constraints
GCS::Line l;
l.p1 = p1;
Expand All @@ -954,6 +967,13 @@ int Sketch::addLineSegment(const Part::GeomLineSegment& lineSegment, bool fixed)
// store complete set
Geoms.push_back(def);

// Internal midpoint rule (like the internal ArcRules of arcs): pmid is the
// midpoint of p1 and p2. Lives only in the solver, so it is rebuilt from
// the geometry on load and needs no file-format change.
if (!fixed) {
GCSsys.addConstraintP2PSymmetric(p1, p2, pmid);
}

if (!fixed) {
param2geoelement.emplace(
std::piecewise_construct,
Expand Down
4 changes: 4 additions & 0 deletions src/Mod/Sketcher/App/SketchGeometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ class SketchLineSegment: public SketchGeometryT<Part::GeomLineSegment>
case PointPos::end: {
return lineSeg->getEndPoint();
}
case PointPos::mid: {
// Experimental line-midpoint vertex (see commit revert note).
return (lineSeg->getStartPoint() + lineSeg->getEndPoint()) / 2.0;
}
default:
break;
}
Expand Down
3 changes: 3 additions & 0 deletions src/Mod/Sketcher/App/SketchObjectGeometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1499,6 +1499,9 @@ void SketchObject::rebuildVertexIndex()
VertexId2PosId.push_back(PointPos::start);
VertexId2GeoId.push_back(i);
VertexId2PosId.push_back(PointPos::end);
// Experimental line-midpoint vertex (see commit revert note).
VertexId2GeoId.push_back(i);
VertexId2PosId.push_back(PointPos::mid);
}
else if ((*it)->is<Part::GeomCircle>()) {
VertexId2GeoId.push_back(i);
Expand Down
7 changes: 7 additions & 0 deletions src/Mod/Sketcher/Gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,13 @@ target_include_directories(

target_link_libraries(SketcherGui ${SketcherGui_LIBS})

# Mirror FreeCADGui's private Vulkan define so the SketcherGui-only Vulkan aids
# (e.g. the hover line-midpoint marker) compile in the Vulkan build and are
# compiled out entirely in the GL/upstream build.
if(FREECAD_USE_VULKAN)
target_compile_definitions(SketcherGui PRIVATE FREECAD_USE_VULKAN=1)
endif()

if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|FreeBSD|OpenBSD|NetBSD)$")
find_package(Fontconfig REQUIRED)
target_link_libraries(SketcherGui Fontconfig::Fontconfig)
Expand Down
52 changes: 52 additions & 0 deletions src/Mod/Sketcher/Gui/EditModeCoinManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include <memory>
#include <ranges>

#include <FCConfig.h>

#include <Inventor/SbVec2f.h>
#include <Inventor/SbVec3f.h>
#include <Inventor/SoPickedPoint.h>
Expand All @@ -47,6 +49,7 @@
#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/nodes/SoPickStyle.h>
#include <Inventor/nodes/SoSeparator.h>
#include <Inventor/nodes/SoSwitch.h>
#include <Inventor/nodes/SoText2.h>
#include <Inventor/nodes/SoTranslation.h>

Expand Down Expand Up @@ -339,6 +342,28 @@ struct GeometryScreenPreselector
startPoint[0] + (endPoint[0] - startPoint[0]) * interpolation,
startPoint[1] + (endPoint[1] - startPoint[1]) * interpolation
));

#ifdef FREECAD_USE_VULKAN
// Vulkan-only Sketcher aid: when the hovered curve is a
// line and the cursor is close to its center, ask for the
// hover-midpoint marker. Only this hovered line is ever
// considered, so the cost is O(1) per hover.
if (const Part::Geometry* geom = geolist.getGeometryFromGeoId(geoIndex);
geom && geom->is<Part::GeomLineSegment>()) {
const SbVec3f midpoint = (startPoint + endPoint) * 0.5F;
const SbVec2f midpointScreen = projectToScreen(midpoint);
const float mdx = cursorPoint[0] - midpointScreen[0];
const float mdy = cursorPoint[1] - midpointScreen[1];
const float midpointRadius = std::max(
curveHitRadius,
static_cast<float>(drawingParameters.markerSize)
);
if (mdx * mdx + mdy * mdy <= midpointRadius * midpointRadius) {
result.LineMidpoint = Base::Vector3d(midpoint[0], midpoint[1], 0.0);
}
}
#endif

bestDistanceSquared = bestCurveDistanceSquared;
found = true;
}
Expand Down Expand Up @@ -1582,6 +1607,33 @@ EditModeCoinManager::PreselectionResult EditModeCoinManager::detectPreselection(
);
}

void EditModeCoinManager::setHoverMidpoint(const std::optional<Base::Vector3d>& midpoint)
{
#ifdef FREECAD_USE_VULKAN
if (!editModeScenegraphNodes.HoverMidpointSwitch) {
return;
}

if (midpoint) {
editModeScenegraphNodes.HoverMidpointCoordinate->point.set1Value(
0,
SbVec3f(
static_cast<float>(midpoint->x),
static_cast<float>(midpoint->y),
ViewProviderSketchCoinAttorney::getViewOrientationFactor(viewProvider)
* drawingParameters.zHighlight
)
);
editModeScenegraphNodes.HoverMidpointSwitch->whichChild = SO_SWITCH_ALL;
}
else {
editModeScenegraphNodes.HoverMidpointSwitch->whichChild = SO_SWITCH_NONE;
}
#else
(void)midpoint;
#endif
}

SoGroup* EditModeCoinManager::getSelectedConstraints()
{
SoGroup* group = new SoGroup();
Expand Down
18 changes: 18 additions & 0 deletions src/Mod/Sketcher/Gui/EditModeCoinManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ class SketcherGuiExport EditModeCoinManager
std::set<int> ConstrIndices;
ConstraintHitKind ConstraintKind = ConstraintHitKind::None;
std::optional<Base::Vector3d> PickedPoint;
//! Sketch-plane midpoint (z unused) of the hovered line when the cursor
//! is close enough to its center to show the hover-midpoint marker
//! (Vulkan-only aid; see EditModeGeometryCoinManager).
std::optional<Base::Vector3d> LineMidpoint;

[[nodiscard]] inline bool hasWinner() const
{
Expand Down Expand Up @@ -250,6 +254,7 @@ class SketcherGuiExport EditModeCoinManager
ConstrIndices.clear();
ConstraintKind = ConstraintHitKind::None;
PickedPoint.reset();
LineMidpoint.reset();
}
};

Expand Down Expand Up @@ -366,6 +371,19 @@ class SketcherGuiExport EditModeCoinManager

void updateGeometryColor(const GeoListFacade& geolistfacade, bool issketchinvalid);

public:
/** @name Vulkan-only hover line-midpoint marker
*
* Show the marker at the given sketch-plane point (the center of the line
* under the mouse) or hide it when empty. Only the hovered line's center is
* ever handed in, so no per-line geometry is produced. A no-op without
* Vulkan (the marker nodes do not exist).
*/
//@{
void setHoverMidpoint(const std::optional<Base::Vector3d>& midpoint);
//@}

private:
// causes the ViewProvider to draw
void redrawViewProvider();

Expand Down
15 changes: 15 additions & 0 deletions src/Mod/Sketcher/Gui/EditModeCoinManagerParameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <Inventor/nodes/SoMarkerSet.h>
#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/nodes/SoPickStyle.h>
#include <Inventor/nodes/SoSwitch.h>
#include <Inventor/nodes/SoText2.h>
#include <Inventor/nodes/SoTranslation.h>

Expand Down Expand Up @@ -497,6 +498,20 @@ struct EditModeScenegraphNodes
SoDrawStyle* EditMarkersDrawStyle;
//@}

/** @name Hover line-midpoint marker (Vulkan-only Sketcher aid)
*
* A single reusable marker drawn at the center of the line under the mouse
* when the cursor gets close to that center. It is only computed for the
* hovered line (never for every line), so the cost stays O(1) per hover.
* Created and driven from EditModeGeometryCoinManager.
*/
//@{
SoSwitch* HoverMidpointSwitch = nullptr;
SoMaterial* HoverMidpointMaterial = nullptr;
SoCoordinate3* HoverMidpointCoordinate = nullptr;
SoMarkerSet* HoverMidpointSet = nullptr;
//@}

/** @name Temporal edit text nodes*/
//@{
SoText2* textX;
Expand Down
28 changes: 22 additions & 6 deletions src/Mod/Sketcher/Gui/EditModeGeometryCoinConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,11 @@ void EditModeGeometryCoinConverter::convert(const Sketcher::GeoListFacade& geoli
);
}
else if (type == Part::GeomLineSegment::getClassTypeId()) { // add a line
// Experimental: line midpoints are exposed as vertices (see commit
// revert note), so a line draws start, end and mid.
convert<
Part::GeomLineSegment,
EditModeGeometryCoinConverter::PointsMode::InsertStartEnd,
EditModeGeometryCoinConverter::PointsMode::InsertStartEndMid,
EditModeGeometryCoinConverter::CurveMode::StartEndPointsOnly,
EditModeGeometryCoinConverter::AnalyseMode::BoundingBoxMagnitude>(
geom,
Expand All @@ -205,7 +207,7 @@ void EditModeGeometryCoinConverter::convert(const Sketcher::GeoListFacade& geoli
setTracking(
GeoId,
coinLayer,
EditModeGeometryCoinConverter::PointsMode::InsertStartEnd,
EditModeGeometryCoinConverter::PointsMode::InsertStartEndMid,
1,
subLayerId,
isGroupMember
Expand Down Expand Up @@ -284,6 +286,9 @@ void EditModeGeometryCoinConverter::convert(const Sketcher::GeoListFacade& geoli
for (auto l = 0; l < geometryLayerParameters.getCoinLayerCount(); l++) {
geometryLayerNodes.PointsCoordinate[l]->point.setNum(Points[l].size());
geometryLayerNodes.PointsMaterials[l]->diffuseColor.setNum(Points[l].size());
// Per-vertex transparency: line midpoints are hidden until hovered (see
// EditModeGeometryCoinManager::updateGeometryColor).
geometryLayerNodes.PointsMaterials[l]->transparency.setNum(Points[l].size());
SbVec3f* pverts = geometryLayerNodes.PointsCoordinate[l]->point.startEditing();

int i = 0; // setting up the point set
Expand Down Expand Up @@ -354,10 +359,21 @@ void EditModeGeometryCoinConverter::convert(
addPoint(Points[coinLayer], geo->getEndPoint());
}
else if constexpr (pointmode == PointsMode::InsertStartEndMid) {
// All in this group are Trimmed Curves (see Geometry.h)
addPoint(Points[coinLayer], geo->getStartPoint(/*emulateCCW=*/true));
addPoint(Points[coinLayer], geo->getEndPoint(/*emulateCCW=*/true));
addPoint(Points[coinLayer], geo->getCenter());
if constexpr (std::is_same<GeoType, Part::GeomLineSegment>::value) {
// Experimental line-midpoint vertex: plain start/end plus the
// geometric midpoint (lines have no getCenter()).
const Base::Vector3d start = geo->getStartPoint();
const Base::Vector3d end = geo->getEndPoint();
addPoint(Points[coinLayer], start);
addPoint(Points[coinLayer], end);
addPoint(Points[coinLayer], (start + end) / 2.0);
}
else {
// All in this group are Trimmed Curves (see Geometry.h)
addPoint(Points[coinLayer], geo->getStartPoint(/*emulateCCW=*/true));
addPoint(Points[coinLayer], geo->getEndPoint(/*emulateCCW=*/true));
addPoint(Points[coinLayer], geo->getCenter());
}
}
else if constexpr (pointmode == PointsMode::InsertMidOnly) {
addPoint(Points[coinLayer], geo->getCenter());
Expand Down
Loading
Loading