Add cut face chamfer tool.
parent
86978d0ac3
commit
cbaccb0116
|
@ -8,7 +8,6 @@
|
||||||
enum class CutTemplate
|
enum class CutTemplate
|
||||||
{
|
{
|
||||||
Quad = 0,
|
Quad = 0,
|
||||||
Triangle,
|
|
||||||
Count
|
Count
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,8 +18,6 @@ QString CutTemplateToDispName(CutTemplate cutTemplate) \
|
||||||
switch (cutTemplate) { \
|
switch (cutTemplate) { \
|
||||||
case CutTemplate::Quad: \
|
case CutTemplate::Quad: \
|
||||||
return QObject::tr("Quad"); \
|
return QObject::tr("Quad"); \
|
||||||
case CutTemplate::Triangle: \
|
|
||||||
return QObject::tr("Triangle"); \
|
|
||||||
default: \
|
default: \
|
||||||
return ""; \
|
return ""; \
|
||||||
} \
|
} \
|
||||||
|
@ -37,12 +34,6 @@ std::vector<QVector2D> CutTemplateToPoints(CutTemplate cutTemplate) \
|
||||||
{ 1.0, 1.0}, \
|
{ 1.0, 1.0}, \
|
||||||
{-1.0, 1.0}, \
|
{-1.0, 1.0}, \
|
||||||
}; \
|
}; \
|
||||||
case CutTemplate::Triangle: \
|
|
||||||
return { \
|
|
||||||
{0, -1.0}, \
|
|
||||||
{1.732, 0}, \
|
|
||||||
{0, 1.0}, \
|
|
||||||
}; \
|
|
||||||
default: \
|
default: \
|
||||||
return { \
|
return { \
|
||||||
{-1.0, -1.0}, \
|
{-1.0, -1.0}, \
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <QSizePolicy>
|
#include <QSizePolicy>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QSizePolicy>
|
#include <QSizePolicy>
|
||||||
|
#include <nodemesh/misc.h>
|
||||||
#include "partwidget.h"
|
#include "partwidget.h"
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
#include "floatnumberwidget.h"
|
#include "floatnumberwidget.h"
|
||||||
|
@ -495,9 +496,10 @@ void PartWidget::showCutTemplateSettingPopup(const QPoint &pos)
|
||||||
initShortCuts(popup, graphicsWidget);
|
initShortCuts(popup, graphicsWidget);
|
||||||
|
|
||||||
std::vector<QPushButton *> presetButtons;
|
std::vector<QPushButton *> presetButtons;
|
||||||
for (size_t i = 0; i < (size_t)CutTemplate::Count; ++i) {
|
|
||||||
CutTemplate cutTemplate = (CutTemplate)i;
|
{
|
||||||
QPushButton *button = new QPushButton(CutTemplateToDispName(cutTemplate));
|
CutTemplate cutTemplate = CutTemplate::Quad;
|
||||||
|
QPushButton *button = new QPushButton(tr("Reset"));
|
||||||
connect(button, &QPushButton::clicked, [cutTemplate, &cutDocument, this]() {
|
connect(button, &QPushButton::clicked, [cutTemplate, &cutDocument, this]() {
|
||||||
auto points = CutTemplateToPoints(cutTemplate);
|
auto points = CutTemplateToPoints(cutTemplate);
|
||||||
cutDocument.fromCutTemplate(points);
|
cutDocument.fromCutTemplate(points);
|
||||||
|
@ -508,6 +510,36 @@ void PartWidget::showCutTemplateSettingPopup(const QPoint &pos)
|
||||||
presetButtons.push_back(button);
|
presetButtons.push_back(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
QPushButton *button = new QPushButton(tr("Subdivide"));
|
||||||
|
connect(button, &QPushButton::clicked, [&cutDocument, this]() {
|
||||||
|
std::vector<QVector2D> cutTemplate;
|
||||||
|
cutDocument.toCutTemplate(cutTemplate);
|
||||||
|
nodemesh::subdivideFace2D(&cutTemplate);
|
||||||
|
cutDocument.fromCutTemplate(cutTemplate);
|
||||||
|
emit setPartCutTemplate(m_partId, cutTemplate);
|
||||||
|
emit groupOperationAdded();
|
||||||
|
});
|
||||||
|
Theme::initToolButton(button);
|
||||||
|
presetButtons.push_back(button);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
QPushButton *button = new QPushButton(tr("Chamfer"));
|
||||||
|
connect(button, &QPushButton::clicked, [&cutDocument, this]() {
|
||||||
|
std::vector<QVector2D> cutTemplate;
|
||||||
|
cutDocument.toCutTemplate(cutTemplate);
|
||||||
|
nodemesh::chamferFace2D(&cutTemplate);
|
||||||
|
cutDocument.fromCutTemplate(cutTemplate);
|
||||||
|
emit setPartCutTemplate(m_partId, cutTemplate);
|
||||||
|
emit groupOperationAdded();
|
||||||
|
});
|
||||||
|
Theme::initToolButton(button);
|
||||||
|
presetButtons.push_back(button);
|
||||||
|
}
|
||||||
|
|
||||||
QVBoxLayout *layout = new QVBoxLayout;
|
QVBoxLayout *layout = new QVBoxLayout;
|
||||||
QHBoxLayout *presetButtonsLayout = new QHBoxLayout;
|
QHBoxLayout *presetButtonsLayout = new QHBoxLayout;
|
||||||
for (const auto &it: presetButtons)
|
for (const auto &it: presetButtons)
|
||||||
|
|
|
@ -491,3 +491,27 @@ void nodemesh::trim(std::vector<QVector3D> *vertices, bool normalize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nodemesh::subdivideFace2D(std::vector<QVector2D> *face)
|
||||||
|
{
|
||||||
|
auto oldFace = *face;
|
||||||
|
face->clear();
|
||||||
|
for (size_t i = 0; i < oldFace.size(); ++i) {
|
||||||
|
size_t j = (i + 1) % oldFace.size();
|
||||||
|
QVector2D direct = (oldFace[i] + oldFace[j]).normalized();
|
||||||
|
float length = (oldFace[i].length() + oldFace[j].length()) * 0.4; // 0.4 = 0.5 * 0.8
|
||||||
|
face->push_back(oldFace[i] * 0.8);
|
||||||
|
face->push_back(direct * length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nodemesh::chamferFace2D(std::vector<QVector2D> *face)
|
||||||
|
{
|
||||||
|
auto oldFace = *face;
|
||||||
|
face->clear();
|
||||||
|
for (size_t i = 0; i < oldFace.size(); ++i) {
|
||||||
|
size_t j = (i + 1) % oldFace.size();
|
||||||
|
face->push_back(oldFace[i] * 0.8 + oldFace[j] * 0.2);
|
||||||
|
face->push_back(oldFace[i] * 0.2 + oldFace[j] * 0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef NODEMESH_MISC_H
|
#ifndef NODEMESH_MISC_H
|
||||||
#define NODEMESH_MISC_H
|
#define NODEMESH_MISC_H
|
||||||
#include <QVector3D>
|
#include <QVector3D>
|
||||||
|
#include <QVector2D>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
@ -31,6 +32,8 @@ size_t weldSeam(const std::vector<QVector3D> &sourceVertices, const std::vector<
|
||||||
std::vector<QVector3D> &destVertices, std::vector<std::vector<size_t>> &destTriangles);
|
std::vector<QVector3D> &destVertices, std::vector<std::vector<size_t>> &destTriangles);
|
||||||
bool isManifold(const std::vector<std::vector<size_t>> &faces);
|
bool isManifold(const std::vector<std::vector<size_t>> &faces);
|
||||||
void trim(std::vector<QVector3D> *vertices, bool normalize=false);
|
void trim(std::vector<QVector3D> *vertices, bool normalize=false);
|
||||||
|
void subdivideFace2D(std::vector<QVector2D> *face);
|
||||||
|
void chamferFace2D(std::vector<QVector2D> *face);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <nodemesh/modifier.h>
|
#include <nodemesh/modifier.h>
|
||||||
|
#include <nodemesh/misc.h>
|
||||||
#include <QVector2D>
|
#include <QVector2D>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
|
@ -47,15 +48,7 @@ void Modifier::createIntermediateNode(const Node &firstNode, const Node &secondN
|
||||||
void Modifier::subdivide()
|
void Modifier::subdivide()
|
||||||
{
|
{
|
||||||
for (auto &node: m_nodes) {
|
for (auto &node: m_nodes) {
|
||||||
auto oldCutTemplate = node.cutTemplate;
|
subdivideFace2D(&node.cutTemplate);
|
||||||
node.cutTemplate.clear();
|
|
||||||
for (size_t i = 0; i < oldCutTemplate.size(); ++i) {
|
|
||||||
size_t j = (i + 1) % oldCutTemplate.size();
|
|
||||||
QVector2D direct = (oldCutTemplate[i] + oldCutTemplate[j]).normalized();
|
|
||||||
float length = (oldCutTemplate[i].length() + oldCutTemplate[j].length()) * 0.4; // 0.4 = 0.5 * 0.8
|
|
||||||
node.cutTemplate.push_back(oldCutTemplate[i] * 0.8);
|
|
||||||
node.cutTemplate.push_back(direct * length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue