Add branch sperate joint wrap

master
Jeremy Hu 2018-03-29 09:46:43 +08:00
parent 64ce4e6843
commit 7df312cff5
9 changed files with 118 additions and 5 deletions

View File

@ -169,6 +169,12 @@ MainWindow::MainWindow()
"selection")); "selection"));
connect(pasteAct, &QAction::triggered, this, &MainWindow::paste); connect(pasteAct, &QAction::triggered, this, &MainWindow::paste);
QAction *markAsBranchAct = new QAction(tr("Mark as &Branch"), this);
connect(markAsBranchAct, &QAction::triggered, skeletonWidget->graphicsView(), &SkeletonEditGraphicsView::markAsBranch);
QAction *markAsTrunkAct = new QAction(tr("Mark as &Trunk"), this);
connect(markAsTrunkAct, &QAction::triggered, skeletonWidget->graphicsView(), &SkeletonEditGraphicsView::markAsTrunk);
QAction *changeTurnaroundAct = new QAction(tr("&Change Turnaround..."), this); QAction *changeTurnaroundAct = new QAction(tr("&Change Turnaround..."), this);
connect(changeTurnaroundAct, &QAction::triggered, skeletonWidget, &SkeletonWidget::changeTurnaround); connect(changeTurnaroundAct, &QAction::triggered, skeletonWidget, &SkeletonWidget::changeTurnaround);
@ -187,6 +193,9 @@ MainWindow::MainWindow()
editMenu->addAction(copyAct); editMenu->addAction(copyAct);
editMenu->addAction(pasteAct); editMenu->addAction(pasteAct);
editMenu->addSeparator(); editMenu->addSeparator();
editMenu->addAction(markAsBranchAct);
editMenu->addAction(markAsTrunkAct);
editMenu->addSeparator();
editMenu->addAction(changeTurnaroundAct); editMenu->addAction(changeTurnaroundAct);
bool connectResult = false; bool connectResult = false;

View File

@ -508,6 +508,7 @@ void SkeletonEditGraphicsView::loadFromSnapshot(SkeletonSnapshot *snapshot)
(*snapshotNode)["y"].toFloat() * yMul, (*snapshotNode)["y"].toFloat() * yMul,
(*snapshotNode)["radius"].toFloat() * radiusMul); (*snapshotNode)["radius"].toFloat() * radiusMul);
nodeItem->setSideColorName((*snapshotNode)["sideColorName"]); nodeItem->setSideColorName((*snapshotNode)["sideColorName"]);
nodeItem->markAsBranch("true" == (*snapshotNode)["isBranch"]);
nodeItemMap[nodeIterator->first] = nodeItem; nodeItemMap[nodeIterator->first] = nodeItem;
} }
for (nodeIterator = snapshot->nodes.begin(); nodeIterator != snapshot->nodes.end(); nodeIterator++) { for (nodeIterator = snapshot->nodes.begin(); nodeIterator != snapshot->nodes.end(); nodeIterator++) {
@ -543,6 +544,7 @@ void SkeletonEditGraphicsView::saveToSnapshot(SkeletonSnapshot *snapshot)
(*snapshotNode)["id"] = nodeId; (*snapshotNode)["id"] = nodeId;
(*snapshotNode)["sideColorName"] = nodeItem->sideColorName(); (*snapshotNode)["sideColorName"] = nodeItem->sideColorName();
(*snapshotNode)["radius"] = QString("%1").arg(nodeItem->radius()); (*snapshotNode)["radius"] = QString("%1").arg(nodeItem->radius());
(*snapshotNode)["isBranch"] = QString("%1").arg(nodeItem->isBranch() ? "true" : "false");
QPointF origin = nodeItem->origin(); QPointF origin = nodeItem->origin();
(*snapshotNode)["x"] = QString("%1").arg(origin.x()); (*snapshotNode)["x"] = QString("%1").arg(origin.x());
(*snapshotNode)["y"] = QString("%1").arg(origin.y()); (*snapshotNode)["y"] = QString("%1").arg(origin.y());
@ -574,4 +576,20 @@ void SkeletonEditGraphicsView::saveToSnapshot(SkeletonSnapshot *snapshot)
} }
} }
void SkeletonEditGraphicsView::markAsBranch()
{
if (m_nextStartNodeItem) {
m_nextStartNodeItem->markAsBranch(true);
m_nextStartNodeItem->nextSidePair()->markAsBranch(true);
emit nodesChanged();
}
}
void SkeletonEditGraphicsView::markAsTrunk()
{
if (m_nextStartNodeItem) {
m_nextStartNodeItem->markAsBranch(false);
m_nextStartNodeItem->nextSidePair()->markAsBranch(false);
emit nodesChanged();
}
}

View File

@ -20,6 +20,8 @@ signals:
public slots: public slots:
void turnOffAddNodeMode(); void turnOffAddNodeMode();
void turnOnAddNodeMode(); void turnOnAddNodeMode();
void markAsBranch();
void markAsTrunk();
public: public:
SkeletonEditGraphicsView(QWidget *parent = 0); SkeletonEditGraphicsView(QWidget *parent = 0);
void updateBackgroundImage(const QImage &image); void updateBackgroundImage(const QImage &image);

View File

@ -8,12 +8,24 @@ SkeletonEditNodeItem::SkeletonEditNodeItem(const QRectF &rect, QGraphicsItem *pa
m_checked(false), m_checked(false),
m_nextSidePair(NULL), m_nextSidePair(NULL),
m_sideColor(Theme::red), m_sideColor(Theme::red),
m_sideColorName("red") m_sideColorName("red"),
m_isBranch(false)
{ {
setData(0, "node"); setData(0, "node");
updateAppearance(); updateAppearance();
} }
void SkeletonEditNodeItem::markAsBranch(bool isBranch)
{
m_isBranch = isBranch;
updateAppearance();
}
bool SkeletonEditNodeItem::isBranch()
{
return m_isBranch;
}
const QString &SkeletonEditNodeItem::sideColorName() const QString &SkeletonEditNodeItem::sideColorName()
{ {
return m_sideColorName; return m_sideColorName;
@ -98,7 +110,7 @@ void SkeletonEditNodeItem::setOrigin(QPointF point)
void SkeletonEditNodeItem::updateAppearance() void SkeletonEditNodeItem::updateAppearance()
{ {
QColor penColor = m_sideColor; QColor penColor = m_sideColor;
penColor.setAlphaF(m_checked ? Theme::checkedAlpha : Theme::normalAlpha); penColor.setAlphaF(m_checked ? Theme::checkedAlpha : (m_isBranch ? Theme::branchAlpha : Theme::normalAlpha));
QPen pen(penColor); QPen pen(penColor);
pen.setWidth(Theme::skeletonNodeBorderSize); pen.setWidth(Theme::skeletonNodeBorderSize);
setPen(pen); setPen(pen);

View File

@ -19,6 +19,8 @@ public:
void setHovered(bool hovered); void setHovered(bool hovered);
bool checked(); bool checked();
void setChecked(bool checked); void setChecked(bool checked);
void markAsBranch(bool isBranch);
bool isBranch();
SkeletonEditNodeItem *nextSidePair(); SkeletonEditNodeItem *nextSidePair();
void setNextSidePair(SkeletonEditNodeItem *nodeItem); void setNextSidePair(SkeletonEditNodeItem *nodeItem);
const QColor &sideColor(); const QColor &sideColor();
@ -32,6 +34,7 @@ private:
SkeletonEditNodeItem *m_nextSidePair; SkeletonEditNodeItem *m_nextSidePair;
QColor m_sideColor; QColor m_sideColor;
QString m_sideColorName; QString m_sideColorName;
bool m_isBranch;
private: private:
void updateAppearance(); void updateAppearance();
}; };

View File

@ -33,6 +33,71 @@ void SkeletonSnapshot::splitByConnectivity(std::vector<SkeletonSnapshot> *groups
{ {
std::map<QString, std::vector<QString>> nodeLinkMap; std::map<QString, std::vector<QString>> nodeLinkMap;
std::map<QString, std::map<QString, QString>>::iterator edgeIterator; std::map<QString, std::map<QString, QString>>::iterator edgeIterator;
std::map<QString, int> neighborCountMap;
for (edgeIterator = edges.begin(); edgeIterator != edges.end(); edgeIterator++) {
neighborCountMap[edgeIterator->second["from"]]++;
neighborCountMap[edgeIterator->second["to"]]++;
}
int nextNewXnodeId = 1;
std::vector<std::pair<QString, QString>> newPendingEdges;
for (edgeIterator = edges.begin(); edgeIterator != edges.end(); ) {
std::map<QString, QString> *oneNode = &nodes[edgeIterator->second["from"]];
std::map<QString, QString> *linkNode = &nodes[edgeIterator->second["to"]];
if ("true" != (*oneNode)["isBranch"]) {
oneNode = &nodes[edgeIterator->second["to"]];
linkNode = &nodes[edgeIterator->second["from"]];
if ("true" != (*oneNode)["isBranch"]) {
edgeIterator++;
continue;
} else {
if (neighborCountMap[(*linkNode)["id"]] < 3) {
edgeIterator++;
continue;
}
}
} else {
if (neighborCountMap[(*linkNode)["id"]] < 3) {
edgeIterator++;
continue;
}
}
if ("red" == (*oneNode)["sideColorName"]) {
QString nodeId = QString("nodex%1").arg(nextNewXnodeId++);
std::map<QString, QString> *newNode = &nodes[nodeId];
*newNode = *linkNode;
(*newNode)["id"] = nodeId;
(*newNode)["radius"] = (*newNode)["radius"].toFloat() / 2;
std::map<QString, QString> *pairNode = &nodes[(*oneNode)["nextSidePair"]];
QString pairNodeId = QString("nodex%1").arg(nextNewXnodeId++);
std::map<QString, QString> *newPairNode = &nodes[pairNodeId];
*newPairNode = *pairNode;
(*newPairNode)["id"] = pairNodeId;
(*newPairNode)["radius"] = (*newPairNode)["radius"].toFloat() / 2;
(*newNode)["nextSidePair"] = pairNodeId;
(*newPairNode)["nextSidePair"] = nodeId;
newPendingEdges.push_back(std::make_pair((*oneNode)["id"], nodeId));
}
edgeIterator = edges.erase(edgeIterator);
}
int nextNewXedgeId = 1;
for (size_t i = 0; i < newPendingEdges.size(); i++) {
QString edgeId = QString("edgex%1").arg(nextNewXedgeId++);
std::map<QString, QString> *newEdge = &edges[edgeId];
(*newEdge)["id"] = edgeId;
(*newEdge)["from"] = newPendingEdges[i].first;
(*newEdge)["to"] = newPendingEdges[i].second;
edgeId = QString("edgex%1").arg(nextNewXedgeId++);
newEdge = &edges[edgeId];
(*newEdge)["id"] = edgeId;
(*newEdge)["from"] = nodes[newPendingEdges[i].first]["nextSidePair"];
(*newEdge)["to"] = nodes[newPendingEdges[i].second]["nextSidePair"];
}
for (edgeIterator = edges.begin(); edgeIterator != edges.end(); edgeIterator++) { for (edgeIterator = edges.begin(); edgeIterator != edges.end(); edgeIterator++) {
nodeLinkMap[edgeIterator->second["from"]].push_back(edgeIterator->second["to"]); nodeLinkMap[edgeIterator->second["from"]].push_back(edgeIterator->second["to"]);
nodeLinkMap[edgeIterator->second["to"]].push_back(edgeIterator->second["from"]); nodeLinkMap[edgeIterator->second["to"]].push_back(edgeIterator->second["from"]);

View File

@ -236,6 +236,8 @@ Mesh *SkeletonToMesh::takeResultMesh()
void SkeletonToMesh::process() void SkeletonToMesh::process()
{ {
std::vector<SkeletonSnapshot> groups; std::vector<SkeletonSnapshot> groups;
QRectF globalFront = m_snapshot.boundingBoxFront();
QRectF globalSide = m_snapshot.boundingBoxSide();
m_snapshot.splitByConnectivity(&groups); m_snapshot.splitByConnectivity(&groups);
std::vector<int> meshIds; std::vector<int> meshIds;
@ -257,9 +259,9 @@ void SkeletonToMesh::process()
std::map<QString, std::map<QString, QString>>::iterator nextSidePair = skeleton->nodes.find(nodeIterator->second["nextSidePair"]); std::map<QString, std::map<QString, QString>>::iterator nextSidePair = skeleton->nodes.find(nodeIterator->second["nextSidePair"]);
if (nextSidePair == skeleton->nodes.end()) if (nextSidePair == skeleton->nodes.end())
continue; continue;
float x = (nodeIterator->second["x"].toFloat() - front.left()) / canvasHeight; float x = (nodeIterator->second["x"].toFloat() - globalFront.left()) / canvasHeight;
float y = (nodeIterator->second["y"].toFloat()) / canvasHeight; float y = (nodeIterator->second["y"].toFloat() - globalFront.top()) / canvasHeight;
float z = (nextSidePair->second["x"].toFloat() - side.left()) / canvasHeight; float z = (nextSidePair->second["x"].toFloat() - globalSide.left()) / canvasHeight;
float r = nodeIterator->second["radius"].toFloat() / canvasHeight; float r = nodeIterator->second["radius"].toFloat() / canvasHeight;
float t = nextSidePair->second["radius"].toFloat() / canvasHeight; float t = nextSidePair->second["radius"].toFloat() / canvasHeight;
int bmeshNodeId = meshlite_bmesh_add_node(meshliteContext, bmeshId, x, y, z, r, t); int bmeshNodeId = meshlite_bmesh_add_node(meshliteContext, bmeshId, x, y, z, r, t);

View File

@ -18,6 +18,7 @@ QColor Theme::red = QColor(0xfc, 0x66, 0x21);
QColor Theme::green = QColor(0xaa, 0xeb, 0xc4); QColor Theme::green = QColor(0xaa, 0xeb, 0xc4);
QColor Theme::blue = QColor(0x2a, 0x5a, 0xac); QColor Theme::blue = QColor(0x2a, 0x5a, 0xac);
float Theme::normalAlpha = 128.0 / 255; float Theme::normalAlpha = 128.0 / 255;
float Theme::branchAlpha = 64.0 / 255;
float Theme::checkedAlpha = 1.0; float Theme::checkedAlpha = 1.0;
float Theme::fillAlpha = 50.0 / 255; float Theme::fillAlpha = 50.0 / 255;
int Theme::skeletonNodeBorderSize = 1; int Theme::skeletonNodeBorderSize = 1;

View File

@ -12,6 +12,7 @@ public:
static QColor blue; static QColor blue;
static float normalAlpha; static float normalAlpha;
static float checkedAlpha; static float checkedAlpha;
static float branchAlpha;
static float fillAlpha; static float fillAlpha;
static int skeletonNodeBorderSize; static int skeletonNodeBorderSize;
static int skeletonEdgeWidth; static int skeletonEdgeWidth;