Start building mesh primitives.
This commit is contained in:
parent
a20c0183df
commit
fcd90b5db4
30 changed files with 856 additions and 97 deletions
|
@ -7,6 +7,8 @@ list(APPEND client_HEADERS
|
||||||
audio_editor/AudioEditorView.h
|
audio_editor/AudioEditorView.h
|
||||||
image_editor/ImageEditorView.h
|
image_editor/ImageEditorView.h
|
||||||
image_editor/ImageViewWidget.h
|
image_editor/ImageViewWidget.h
|
||||||
|
canvas/CanvasView.h
|
||||||
|
canvas/CanvasController.h
|
||||||
web_client/WebClientView.h)
|
web_client/WebClientView.h)
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,6 +20,8 @@ list(APPEND client_LIB_INCLUDES
|
||||||
audio_editor/AudioEditorView.cpp
|
audio_editor/AudioEditorView.cpp
|
||||||
image_editor/ImageEditorView.cpp
|
image_editor/ImageEditorView.cpp
|
||||||
image_editor/ImageViewWidget.cpp
|
image_editor/ImageViewWidget.cpp
|
||||||
|
canvas/CanvasView.cpp
|
||||||
|
canvas/CanvasController.cpp
|
||||||
web_client/WebClientView.cpp
|
web_client/WebClientView.cpp
|
||||||
MediaTool.cpp)
|
MediaTool.cpp)
|
||||||
|
|
||||||
|
@ -37,6 +41,7 @@ target_include_directories(sample_gui PUBLIC
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/audio_editor"
|
"${CMAKE_CURRENT_SOURCE_DIR}/audio_editor"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/image_editor"
|
"${CMAKE_CURRENT_SOURCE_DIR}/image_editor"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/web_client"
|
"${CMAKE_CURRENT_SOURCE_DIR}/web_client"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/canvas"
|
||||||
)
|
)
|
||||||
target_link_libraries(sample_gui PUBLIC client windows console core network database geometry audio web)
|
target_link_libraries(sample_gui PUBLIC client windows console core network database geometry audio web)
|
||||||
set_property(TARGET sample_gui PROPERTY FOLDER apps)
|
set_property(TARGET sample_gui PROPERTY FOLDER apps)
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "AudioEditorView.h"
|
#include "AudioEditorView.h"
|
||||||
#include "ImageEditorView.h"
|
#include "ImageEditorView.h"
|
||||||
#include "WebClientView.h"
|
#include "WebClientView.h"
|
||||||
|
#include "CanvasView.h"
|
||||||
|
|
||||||
#include "TabbedPanelWidget.h"
|
#include "TabbedPanelWidget.h"
|
||||||
#include "TopBar.h"
|
#include "TopBar.h"
|
||||||
#include "TextNode.h"
|
#include "TextNode.h"
|
||||||
|
@ -31,9 +33,9 @@ void MediaTool::initializeViews()
|
||||||
auto path = mMainApplication->getCommandLineArgs()->getLaunchPath();
|
auto path = mMainApplication->getCommandLineArgs()->getLaunchPath();
|
||||||
path /= "out.txt";
|
path /= "out.txt";
|
||||||
textEditor->setName("TextEditor");
|
textEditor->setName("TextEditor");
|
||||||
textEditor->GetController()->SetSavePath(path);
|
textEditor->getController()->SetSavePath(path);
|
||||||
textEditor->GetController()->SetLoadPath(path);
|
textEditor->getController()->SetLoadPath(path);
|
||||||
textEditor->Initialize();
|
textEditor->initialize();
|
||||||
tabbedPanel->addPanel(std::move(textEditor), "Text Editor");
|
tabbedPanel->addPanel(std::move(textEditor), "Text Editor");
|
||||||
|
|
||||||
auto audioEditor = AudioEditorView::Create();
|
auto audioEditor = AudioEditorView::Create();
|
||||||
|
@ -48,6 +50,10 @@ void MediaTool::initializeViews()
|
||||||
webClient->setName("webClient");
|
webClient->setName("webClient");
|
||||||
tabbedPanel->addPanel(std::move(webClient), "Web Client");
|
tabbedPanel->addPanel(std::move(webClient), "Web Client");
|
||||||
|
|
||||||
|
auto canvas = CanvasView::Create();
|
||||||
|
canvas->setName("CanvasView");
|
||||||
|
tabbedPanel->addPanel(std::move(canvas), "Canvas");
|
||||||
|
|
||||||
auto topBar = TopBar::Create();
|
auto topBar = TopBar::Create();
|
||||||
auto statusBar = StatusBar::Create();
|
auto statusBar = StatusBar::Create();
|
||||||
|
|
||||||
|
|
6
apps/sample-gui/canvas/CanvasController.cpp
Normal file
6
apps/sample-gui/canvas/CanvasController.cpp
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#include "CanvasController.h"
|
||||||
|
|
||||||
|
std::unique_ptr<CanvasController> CanvasController::Create()
|
||||||
|
{
|
||||||
|
return std::make_unique<CanvasController>();
|
||||||
|
}
|
9
apps/sample-gui/canvas/CanvasController.h
Normal file
9
apps/sample-gui/canvas/CanvasController.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class CanvasController
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static std::unique_ptr<CanvasController> Create();
|
||||||
|
};
|
75
apps/sample-gui/canvas/CanvasView.cpp
Normal file
75
apps/sample-gui/canvas/CanvasView.cpp
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
#include "CanvasView.h"
|
||||||
|
|
||||||
|
#include "HorizontalSpacer.h"
|
||||||
|
#include "VerticalSpacer.h"
|
||||||
|
|
||||||
|
#include "CanvasController.h"
|
||||||
|
|
||||||
|
#include "Theme.h"
|
||||||
|
|
||||||
|
#include "TextNode.h"
|
||||||
|
#include "Label.h"
|
||||||
|
#include "Button.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
CanvasView::CanvasView()
|
||||||
|
: mController(CanvasController::Create())
|
||||||
|
{
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasView::~CanvasView()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<CanvasView> CanvasView::Create()
|
||||||
|
{
|
||||||
|
return std::make_unique<CanvasView>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasView::initialize()
|
||||||
|
{
|
||||||
|
auto label = Label::Create();
|
||||||
|
label->setLabel("Canvas");
|
||||||
|
label->setBackgroundColor(Theme::getBannerBackground());
|
||||||
|
label->setMargin(1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
auto hSpacer = HorizontalSpacer::Create();
|
||||||
|
hSpacer->addWidgetWithScale(std::move(label), 1);
|
||||||
|
//hSpacer->addWidgetWithScale(std::move(textBox), 14);
|
||||||
|
|
||||||
|
auto cache_button_spacer = initializeCacheButtons();
|
||||||
|
hSpacer->addWidgetWithScale(std::move(cache_button_spacer), 1);
|
||||||
|
|
||||||
|
addWidget(std::move(hSpacer));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Widget> CanvasView::initializeCacheButtons()
|
||||||
|
{
|
||||||
|
auto saveButton = Button::Create();
|
||||||
|
saveButton->setLabel("Save");
|
||||||
|
saveButton->setBackgroundColor(Theme::getButtonPrimaryBackground());
|
||||||
|
saveButton->setMargin(2);
|
||||||
|
|
||||||
|
auto clearButton = Button::Create();
|
||||||
|
clearButton->setLabel("Clear");
|
||||||
|
clearButton->setBackgroundColor(Theme::getButtonPrimaryBackground());
|
||||||
|
clearButton->setMargin(2);
|
||||||
|
|
||||||
|
auto loadButton = Button::Create();
|
||||||
|
loadButton->setLabel("Load");
|
||||||
|
loadButton->setBackgroundColor(Theme::getButtonPrimaryBackground());
|
||||||
|
loadButton->setMargin(2);
|
||||||
|
|
||||||
|
auto buttonSpacer = VerticalSpacer::Create();
|
||||||
|
buttonSpacer->AddWidgetWithScale(std::move(saveButton), 1);
|
||||||
|
buttonSpacer->AddWidgetWithScale(std::move(clearButton), 1);
|
||||||
|
buttonSpacer->AddWidgetWithScale(std::move(loadButton), 1);
|
||||||
|
|
||||||
|
return buttonSpacer;
|
||||||
|
}
|
||||||
|
|
26
apps/sample-gui/canvas/CanvasView.h
Normal file
26
apps/sample-gui/canvas/CanvasView.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Widget.h"
|
||||||
|
|
||||||
|
class CanvasController;
|
||||||
|
|
||||||
|
class CanvasView : public Widget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CanvasView();
|
||||||
|
|
||||||
|
~CanvasView();
|
||||||
|
|
||||||
|
static std::unique_ptr<CanvasView> Create();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
|
||||||
|
std::unique_ptr<Widget> initializeCacheButtons();
|
||||||
|
|
||||||
|
//std::unique_ptr<Widget> initializeCacheButtons();
|
||||||
|
|
||||||
|
std::unique_ptr<CanvasController> mController;
|
||||||
|
};
|
||||||
|
using CanvasViewPtr = std::unique_ptr<CanvasView>;
|
|
@ -5,10 +5,6 @@
|
||||||
|
|
||||||
class TextEditorController
|
class TextEditorController
|
||||||
{
|
{
|
||||||
TextEditorModelUPtr mModel;
|
|
||||||
std::filesystem::path mSavePath;
|
|
||||||
std::filesystem::path mLoadPath;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TextEditorController();
|
TextEditorController();
|
||||||
|
@ -28,6 +24,11 @@ public:
|
||||||
void SetSavePath(const std::filesystem::path& path);
|
void SetSavePath(const std::filesystem::path& path);
|
||||||
|
|
||||||
void SetLoadPath(const std::filesystem::path& path);
|
void SetLoadPath(const std::filesystem::path& path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
TextEditorModelUPtr mModel;
|
||||||
|
std::filesystem::path mSavePath;
|
||||||
|
std::filesystem::path mLoadPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
using TextEditorControllerUPtr = std::unique_ptr<TextEditorController>;
|
using TextEditorControllerUPtr = std::unique_ptr<TextEditorController>;
|
||||||
|
|
|
@ -16,12 +16,12 @@ TextEditorView::TextEditorView()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TextEditorController* TextEditorView::GetController()
|
TextEditorController* TextEditorView::getController()
|
||||||
{
|
{
|
||||||
return mController.get();
|
return mController.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEditorView::Initialize()
|
void TextEditorView::initialize()
|
||||||
{
|
{
|
||||||
auto label = Label::Create();
|
auto label = Label::Create();
|
||||||
label->setLabel("Text Editor");
|
label->setLabel("Text Editor");
|
||||||
|
|
|
@ -5,21 +5,23 @@
|
||||||
#include "Label.h"
|
#include "Label.h"
|
||||||
#include "TextBox.h"
|
#include "TextBox.h"
|
||||||
#include "TextEditorController.h"
|
#include "TextEditorController.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
class TextEditorView : public Widget
|
class TextEditorView : public Widget
|
||||||
{
|
{
|
||||||
TextBox* mTextBox;
|
|
||||||
TextEditorControllerUPtr mController;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TextEditorView();
|
TextEditorView();
|
||||||
|
|
||||||
static std::unique_ptr<TextEditorView> Create();
|
static std::unique_ptr<TextEditorView> Create();
|
||||||
|
|
||||||
TextEditorController* GetController();
|
TextEditorController* getController();
|
||||||
|
|
||||||
void Initialize();
|
void initialize();
|
||||||
|
|
||||||
|
private:
|
||||||
|
TextBox* mTextBox;
|
||||||
|
TextEditorControllerUPtr mController;
|
||||||
};
|
};
|
||||||
using TextEditorViewUPtr = std::unique_ptr<TextEditorView>;
|
using TextEditorViewUPtr = std::unique_ptr<TextEditorView>;
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
#include "AbstractFace.h"
|
#include "AbstractFace.h"
|
||||||
|
|
||||||
|
#include "Edge.h"
|
||||||
|
|
||||||
AbstractFace::AbstractFace(unsigned id)
|
AbstractFace::AbstractFace(unsigned id)
|
||||||
: mId(id)
|
: mId(id)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AbstractFace::~AbstractFace()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void AbstractFace::addVectorAttribute(const std::string& tag, const std::vector<double>& values)
|
void AbstractFace::addVectorAttribute(const std::string& tag, const std::vector<double>& values)
|
||||||
{
|
{
|
||||||
mVectorAttributes[tag] = values;
|
mVectorAttributes[tag] = values;
|
||||||
|
@ -20,3 +27,8 @@ std::vector<double> AbstractFace::getVectorAttribute(const std::string& tag) con
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AbstractFace::setIndex(std::size_t idx)
|
||||||
|
{
|
||||||
|
mId = idx;
|
||||||
|
}
|
||||||
|
|
|
@ -5,12 +5,14 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
class Edge;
|
||||||
|
|
||||||
class AbstractFace
|
class AbstractFace
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AbstractFace(unsigned id=0);
|
AbstractFace(unsigned id=0);
|
||||||
|
|
||||||
virtual ~AbstractFace() = default;
|
virtual ~AbstractFace();
|
||||||
|
|
||||||
virtual std::vector<unsigned> getNodeIds() const = 0;
|
virtual std::vector<unsigned> getNodeIds() const = 0;
|
||||||
|
|
||||||
|
@ -18,6 +20,16 @@ public:
|
||||||
|
|
||||||
std::vector<double> getVectorAttribute(const std::string& tag) const;
|
std::vector<double> getVectorAttribute(const std::string& tag) const;
|
||||||
|
|
||||||
|
void setIndex(std::size_t idx);
|
||||||
|
|
||||||
|
virtual unsigned getNumNodes() const = 0;
|
||||||
|
|
||||||
|
virtual void associateWidthEdges() = 0;
|
||||||
|
|
||||||
|
virtual void replaceEdge(Edge* original, Edge* replacement) = 0;
|
||||||
|
|
||||||
|
virtual std::vector<unsigned> getEdgeIds() const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
unsigned mId{0};
|
unsigned mId{0};
|
||||||
std::unordered_map<std::string, std::vector<double> > mVectorAttributes;
|
std::unordered_map<std::string, std::vector<double> > mVectorAttributes;
|
||||||
|
|
|
@ -40,6 +40,8 @@ public:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual std::unique_ptr<AbstractMesh> copy() const = 0;
|
||||||
|
|
||||||
std::vector<std::vector<double> > getNodeVectorAttributes(const std::string& tag);
|
std::vector<std::vector<double> > getNodeVectorAttributes(const std::string& tag);
|
||||||
|
|
||||||
std::vector<double> getVectorAttribute(const std::string& tag) const;
|
std::vector<double> getVectorAttribute(const std::string& tag) const;
|
||||||
|
|
|
@ -7,6 +7,7 @@ list(APPEND mesh_LIB_INCLUDES
|
||||||
Node.cpp
|
Node.cpp
|
||||||
QuadMesh.cpp
|
QuadMesh.cpp
|
||||||
TriMesh.cpp
|
TriMesh.cpp
|
||||||
|
FaceMesh.cpp
|
||||||
LineMesh.cpp
|
LineMesh.cpp
|
||||||
MeshPrimitives.cpp
|
MeshPrimitives.cpp
|
||||||
MeshBuilder.cpp)
|
MeshBuilder.cpp)
|
||||||
|
|
|
@ -28,3 +28,95 @@ unsigned Edge::getNode1Id() const
|
||||||
{
|
{
|
||||||
return mNode1->getIndex();
|
return mNode1->getIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Edge::isOverlapping(Edge* edge) const
|
||||||
|
{
|
||||||
|
auto overlaps = edge->getNode0()->isCoincident(mNode0) && edge->getNode1()->isCoincident(mNode1);
|
||||||
|
if (overlaps)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return edge->getNode1()->isCoincident(mNode0) && edge->getNode0()->isCoincident(mNode1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Edge::hasSameNodes(Edge* edge) const
|
||||||
|
{
|
||||||
|
return edge->getNode0() == edge->getNode1() || edge->getNode1() == edge->getNode0();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Edge::replaceNodes(Node* node0, Node* node1)
|
||||||
|
{
|
||||||
|
mNode0 = node0;
|
||||||
|
mNode1 = node1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* Edge::getNode0() const
|
||||||
|
{
|
||||||
|
return mNode0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* Edge::getNode1() const
|
||||||
|
{
|
||||||
|
return mNode1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* Edge::getOtherNode(Node* node) const
|
||||||
|
{
|
||||||
|
if (node == mNode0)
|
||||||
|
{
|
||||||
|
return mNode1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return mNode0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Edge::getId() const
|
||||||
|
{
|
||||||
|
return mId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Edge::setState(State state)
|
||||||
|
{
|
||||||
|
mState = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
Edge::State Edge::getState() const
|
||||||
|
{
|
||||||
|
return mState;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Edge::clearConnectivity()
|
||||||
|
{
|
||||||
|
mAssociatedFaceIds.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Edge::getNumConnectedFaces() const
|
||||||
|
{
|
||||||
|
return mAssociatedFaceIds.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Edge::associateFace(unsigned faceId)
|
||||||
|
{
|
||||||
|
mAssociatedFaceIds.push_back(faceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Edge::getConnectedFaceId(std::size_t idx) const
|
||||||
|
{
|
||||||
|
return mAssociatedFaceIds[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Edge::associateWithNodes()
|
||||||
|
{
|
||||||
|
mNode0->associateEdge(mId);
|
||||||
|
mNode1->associateEdge(mId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Edge::setIndex(unsigned idx)
|
||||||
|
{
|
||||||
|
mId = idx;
|
||||||
|
}
|
||||||
|
|
|
@ -1,23 +1,65 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
class Node;
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class Node;
|
||||||
|
|
||||||
class Edge
|
class Edge
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum class State
|
||||||
|
{
|
||||||
|
HEALTHY,
|
||||||
|
DIRTY
|
||||||
|
};
|
||||||
|
|
||||||
Edge(Node* node0, Node* node1, unsigned id = 0);
|
Edge(Node* node0, Node* node1, unsigned id = 0);
|
||||||
|
|
||||||
~Edge();
|
~Edge();
|
||||||
|
|
||||||
static std::unique_ptr<Edge> Create(Node* node0, Node* node1, unsigned id = 0);
|
static std::unique_ptr<Edge> Create(Node* node0, Node* node1, unsigned id = 0);
|
||||||
|
|
||||||
|
void associateFace(unsigned faceId);
|
||||||
|
|
||||||
|
void associateWithNodes();
|
||||||
|
|
||||||
|
void clearConnectivity();
|
||||||
|
|
||||||
|
unsigned getConnectedFaceId(std::size_t idx) const;
|
||||||
|
|
||||||
|
State getState() const;
|
||||||
|
|
||||||
|
unsigned getId() const;
|
||||||
|
|
||||||
unsigned getNode0Id() const;
|
unsigned getNode0Id() const;
|
||||||
|
|
||||||
unsigned getNode1Id() const;
|
unsigned getNode1Id() const;
|
||||||
|
|
||||||
|
Node* getNode0() const;
|
||||||
|
|
||||||
|
Node* getNode1() const;
|
||||||
|
|
||||||
|
unsigned getNumConnectedFaces() const;
|
||||||
|
|
||||||
|
Node* getOtherNode(Node* node) const;
|
||||||
|
|
||||||
|
bool isOverlapping(Edge* edge) const;
|
||||||
|
|
||||||
|
bool hasSameNodes(Edge* edge) const;
|
||||||
|
|
||||||
|
void replaceNodes(Node* node0, Node* node1);
|
||||||
|
|
||||||
|
void setState(State state);
|
||||||
|
|
||||||
|
void setIndex(unsigned idx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned mId{0};
|
unsigned mId{0};
|
||||||
Node* mNode0{nullptr};
|
Node* mNode0{nullptr};
|
||||||
Node* mNode1{nullptr};
|
Node* mNode1{nullptr};
|
||||||
|
|
||||||
|
std::vector<unsigned> mAssociatedFaceIds;
|
||||||
|
|
||||||
|
State mState{State::HEALTHY};
|
||||||
};
|
};
|
||||||
|
|
182
src/mesh/FaceMesh.cpp
Normal file
182
src/mesh/FaceMesh.cpp
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
#include "FaceMesh.h"
|
||||||
|
|
||||||
|
#include "Node.h"
|
||||||
|
#include "Edge.h"
|
||||||
|
#include "AbstractFace.h"
|
||||||
|
|
||||||
|
FaceMesh::~FaceMesh()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void FaceMesh::populate(VecNodes& nodes, VecEdges& edges, VecFaces& faces)
|
||||||
|
{
|
||||||
|
mNodes = std::move(nodes);
|
||||||
|
mEdges = std::move(edges);
|
||||||
|
mFaces = std::move(faces);
|
||||||
|
|
||||||
|
resetIds();
|
||||||
|
resetConnectivity();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned> FaceMesh::getFaceNodeIds() const
|
||||||
|
{
|
||||||
|
if (mFaces.empty())
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto nodes_per_face = mFaces[0]->getNumNodes();
|
||||||
|
std::vector<unsigned> ids(nodes_per_face*mFaces.size());
|
||||||
|
|
||||||
|
for(std::size_t idx=0; idx<mFaces.size(); idx++)
|
||||||
|
{
|
||||||
|
const auto nodeIds = mFaces[idx]->getNodeIds();
|
||||||
|
for(std::size_t jdx=0; jdx<nodes_per_face; jdx++)
|
||||||
|
{
|
||||||
|
ids[nodes_per_face*idx + jdx] = nodeIds[jdx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::vector<double> > FaceMesh::getFaceVectorAttributes(const std::string& tag)
|
||||||
|
{
|
||||||
|
std::vector<std::vector<double> > attribs(mFaces.size());
|
||||||
|
for(std::size_t idx=0; idx<mFaces.size(); idx++)
|
||||||
|
{
|
||||||
|
attribs[idx] = {mFaces[idx]->getVectorAttribute(tag)};
|
||||||
|
}
|
||||||
|
return attribs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FaceMesh::addConstantFaceVectorAttribute(const std::string& tag, const std::vector<double>& values)
|
||||||
|
{
|
||||||
|
for (const auto& face : mFaces)
|
||||||
|
{
|
||||||
|
face->addVectorAttribute(tag, values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FaceMesh::resetIds()
|
||||||
|
{
|
||||||
|
unsigned count = 0;
|
||||||
|
for (auto& node : mNodes)
|
||||||
|
{
|
||||||
|
node->setIndex(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
for (auto& edge : mEdges)
|
||||||
|
{
|
||||||
|
edge->setIndex(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
for (auto& face : mFaces)
|
||||||
|
{
|
||||||
|
face->setIndex(count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FaceMesh::resetConnectivity()
|
||||||
|
{
|
||||||
|
for (auto& node : mNodes)
|
||||||
|
{
|
||||||
|
node->clearConnectivity();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& edge : mEdges)
|
||||||
|
{
|
||||||
|
edge->associateWithNodes();
|
||||||
|
edge->clearConnectivity();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& face : mFaces)
|
||||||
|
{
|
||||||
|
face->associateWidthEdges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FaceMesh::replaceIfOverlapping(FaceMesh* mesh, Node* target_node) const
|
||||||
|
{
|
||||||
|
for (auto& node : mNodes)
|
||||||
|
{
|
||||||
|
if (node->getNumConnectedEdges() == 3 && node->isCoincident(target_node))
|
||||||
|
{
|
||||||
|
target_node->setState(Node::State::DIRTY);
|
||||||
|
for (unsigned idx=0; idx<3; idx++)
|
||||||
|
{
|
||||||
|
auto edge = mesh->mEdges[idx].get();
|
||||||
|
edge->replaceNodes(target_node, node.get());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FaceMesh::replaceIfOverlapping(FaceMesh* mesh, Edge* target_edge) const
|
||||||
|
{
|
||||||
|
for (auto& edge : mEdges)
|
||||||
|
{
|
||||||
|
if (edge->getNumConnectedFaces() == 2 && target_edge->hasSameNodes(edge.get()))
|
||||||
|
{
|
||||||
|
target_edge->setState(Edge::State::DIRTY);
|
||||||
|
for (unsigned idx=0; idx<2; idx++)
|
||||||
|
{
|
||||||
|
auto face = mesh->mFaces[idx].get();
|
||||||
|
face->replaceEdge(target_edge, edge.get());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FaceMesh::merge(std::unique_ptr<FaceMesh> mesh)
|
||||||
|
{
|
||||||
|
if (mesh->getType() != getType())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& node : mesh->mNodes)
|
||||||
|
{
|
||||||
|
if (node->getNumConnectedEdges() == 3)
|
||||||
|
{
|
||||||
|
replaceIfOverlapping(mesh.get(), node.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& node : mesh->mNodes)
|
||||||
|
{
|
||||||
|
if (node->getState() == Node::State::HEALTHY)
|
||||||
|
{
|
||||||
|
mNodes.push_back(std::move(node));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& edge : mesh->mEdges)
|
||||||
|
{
|
||||||
|
if (edge->getNumConnectedFaces() == 2)
|
||||||
|
{
|
||||||
|
replaceIfOverlapping(mesh.get(), edge.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& edge : mesh->mEdges)
|
||||||
|
{
|
||||||
|
if (edge->getState() == Edge::State::HEALTHY)
|
||||||
|
{
|
||||||
|
mEdges.push_back(std::move(edge));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& face : mesh->mFaces)
|
||||||
|
{
|
||||||
|
mFaces.push_back(std::move(face));
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh.reset();
|
||||||
|
resetIds();
|
||||||
|
resetConnectivity();
|
||||||
|
}
|
47
src/mesh/FaceMesh.h
Normal file
47
src/mesh/FaceMesh.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AbstractMesh.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
class Edge;
|
||||||
|
class AbstractFace;
|
||||||
|
|
||||||
|
using EdgePtr = std::unique_ptr<Edge>;
|
||||||
|
using AbstractFacePtr = std::unique_ptr<AbstractFace>;
|
||||||
|
|
||||||
|
using VecEdges = std::vector<EdgePtr>;
|
||||||
|
using VecFaces = std::vector<AbstractFacePtr>;
|
||||||
|
|
||||||
|
class FaceMesh : public AbstractMesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FaceMesh() = default;
|
||||||
|
|
||||||
|
~FaceMesh();
|
||||||
|
|
||||||
|
virtual std::unique_ptr<AbstractMesh> copy() const = 0;
|
||||||
|
|
||||||
|
void populate(VecNodes& nodes, VecEdges& edges, VecFaces& faces);
|
||||||
|
|
||||||
|
std::vector<unsigned> getFaceNodeIds() const;
|
||||||
|
|
||||||
|
void addConstantFaceVectorAttribute(const std::string& tag, const std::vector<double>& values);
|
||||||
|
|
||||||
|
std::vector<std::vector<double> > getFaceVectorAttributes(const std::string& tag);
|
||||||
|
|
||||||
|
void merge(std::unique_ptr<FaceMesh> mesh);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void resetConnectivity();
|
||||||
|
|
||||||
|
void resetIds();
|
||||||
|
|
||||||
|
void replaceIfOverlapping(FaceMesh* mesh, Node* node) const;
|
||||||
|
|
||||||
|
void replaceIfOverlapping(FaceMesh* mesh, Edge* edge) const;
|
||||||
|
|
||||||
|
VecEdges mEdges;
|
||||||
|
VecFaces mFaces;
|
||||||
|
};
|
|
@ -13,6 +13,16 @@ void LineMesh::populate(VecNodes& nodes, VecEdges& edges)
|
||||||
mEdges = std::move(edges);
|
mEdges = std::move(edges);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<AbstractMesh> LineMesh::copy() const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
LineMesh::MeshType LineMesh::getType() const
|
||||||
|
{
|
||||||
|
return LineMesh::MeshType::LINE;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<unsigned> LineMesh::getEdgeNodeIds() const
|
std::vector<unsigned> LineMesh::getEdgeNodeIds() const
|
||||||
{
|
{
|
||||||
std::vector<unsigned> ids(2*mEdges.size());
|
std::vector<unsigned> ids(2*mEdges.size());
|
||||||
|
|
|
@ -20,10 +20,9 @@ public:
|
||||||
|
|
||||||
std::vector<unsigned> getEdgeNodeIds() const;
|
std::vector<unsigned> getEdgeNodeIds() const;
|
||||||
|
|
||||||
MeshType getType() const override
|
MeshType getType() const override;
|
||||||
{
|
|
||||||
return MeshType::LINE;
|
std::unique_ptr<AbstractMesh> copy() const override;
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VecEdges mEdges;
|
VecEdges mEdges;
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include "MeshBuilder.h"
|
#include "MeshBuilder.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
std::unique_ptr<TriMesh> MeshPrimitives::buildRectangleAsTriMesh()
|
std::unique_ptr<TriMesh> MeshPrimitives::buildRectangleAsTriMesh()
|
||||||
|
@ -29,6 +31,85 @@ std::unique_ptr<TriMesh> MeshPrimitives::buildRectangleAsTriMesh()
|
||||||
return MeshBuilder::buildTriMesh(locations, edge_ids, face_ids);
|
return MeshBuilder::buildTriMesh(locations, edge_ids, face_ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<TriMesh> MeshPrimitives::buildRoundedRectangleAsTriMesh(double radius, double aspect_ratio, unsigned num_segments)
|
||||||
|
{
|
||||||
|
unsigned num_fans = 4;
|
||||||
|
unsigned num_nodes_per_fan = num_segments + 2;
|
||||||
|
VecPoints locations(num_fans * num_nodes_per_fan);
|
||||||
|
|
||||||
|
double rect_start_x = radius;
|
||||||
|
double rect_end_x = 1.0 - radius;
|
||||||
|
double rect_end_y = 1.0 - radius;
|
||||||
|
|
||||||
|
double delta_theta = (M_PI/4.0) / double (num_segments);
|
||||||
|
double running_theta = 0;
|
||||||
|
|
||||||
|
locations[0] = {rect_end_x, radius};
|
||||||
|
unsigned offset = 1;
|
||||||
|
for (unsigned idx=0; idx<=num_segments; idx++)
|
||||||
|
{
|
||||||
|
locations[offset + idx] = {rect_end_x + radius*sin(running_theta), radius*(1.0 - cos(running_theta))};
|
||||||
|
running_theta += delta_theta;
|
||||||
|
}
|
||||||
|
offset += num_segments;
|
||||||
|
|
||||||
|
locations[offset] = {rect_end_x, rect_end_y};
|
||||||
|
offset++;
|
||||||
|
running_theta = 0;
|
||||||
|
for (unsigned idx=0; idx<=num_segments;idx++)
|
||||||
|
{
|
||||||
|
locations[offset + idx] = {rect_end_x + radius*cos(running_theta), rect_end_y + radius*sin(running_theta)};
|
||||||
|
running_theta += delta_theta;
|
||||||
|
}
|
||||||
|
offset += num_segments;
|
||||||
|
|
||||||
|
locations[offset] = {rect_start_x, rect_end_y};
|
||||||
|
offset ++;
|
||||||
|
running_theta = 0;
|
||||||
|
for (unsigned idx=0; idx<=num_segments;idx++)
|
||||||
|
{
|
||||||
|
locations[offset + idx] = {rect_start_x - radius*sin(running_theta), rect_end_y + radius*cos(running_theta)};
|
||||||
|
running_theta += delta_theta;
|
||||||
|
}
|
||||||
|
offset += num_segments;
|
||||||
|
|
||||||
|
locations[offset] = {rect_start_x, radius};
|
||||||
|
offset++;
|
||||||
|
running_theta = 0;
|
||||||
|
for (unsigned idx=0; idx<=num_segments;idx++)
|
||||||
|
{
|
||||||
|
locations[offset + idx] = {rect_start_x - radius*cos(running_theta), radius *(1 - sin(running_theta))};
|
||||||
|
running_theta += delta_theta;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned num_edges_per_fan = 2*num_segments + 1;
|
||||||
|
unsigned num_inner_rect_edges = 3*num_fans;
|
||||||
|
EdgeIds edge_ids(num_edges_per_fan*num_fans + num_inner_rect_edges + 1);
|
||||||
|
|
||||||
|
// Fan edges
|
||||||
|
for (unsigned jdx=0; jdx< num_fans; jdx++)
|
||||||
|
{
|
||||||
|
unsigned node_offset = jdx*num_nodes_per_fan;
|
||||||
|
unsigned edge_offset = jdx*num_edges_per_fan;
|
||||||
|
|
||||||
|
// Inner edges
|
||||||
|
for(unsigned idx=0; idx<=num_segments; idx++)
|
||||||
|
{
|
||||||
|
edge_ids[edge_offset + idx] = {node_offset, node_offset + idx + 1};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Outer edges
|
||||||
|
for(unsigned idx=0; idx<num_segments; idx++)
|
||||||
|
{
|
||||||
|
edge_ids[edge_offset + num_segments + 1 + idx] = {node_offset + idx + 1, node_offset + idx + 2};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inner rect edges
|
||||||
|
unsigned edge_offset = num_edges_per_fan*num_fans;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<LineMesh> MeshPrimitives::buildRectangleAsLineMesh()
|
std::unique_ptr<LineMesh> MeshPrimitives::buildRectangleAsLineMesh()
|
||||||
{
|
{
|
||||||
VecPoints locations = {
|
VecPoints locations = {
|
||||||
|
|
|
@ -14,4 +14,6 @@ public:
|
||||||
static std::unique_ptr<TriMesh> buildExplodedGridAsTriMesh(unsigned numX, unsigned numY);
|
static std::unique_ptr<TriMesh> buildExplodedGridAsTriMesh(unsigned numX, unsigned numY);
|
||||||
|
|
||||||
static std::unique_ptr<LineMesh> buildExplodedGridAsLineMesh(unsigned numX, unsigned numY);
|
static std::unique_ptr<LineMesh> buildExplodedGridAsLineMesh(unsigned numX, unsigned numY);
|
||||||
|
|
||||||
|
static std::unique_ptr<TriMesh> buildRoundedRectangleAsTriMesh(double radius, double aspect_ratio = 1.0, unsigned num_segments = 4);
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,4 +42,75 @@ std::vector<double> Node::getVectorAttribute(const std::string& tag) const
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Point& Node::getPoint() const
|
||||||
|
{
|
||||||
|
return mPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::scale(double x, double y)
|
||||||
|
{
|
||||||
|
mPoint.scale(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::translate(double x, double y, double z)
|
||||||
|
{
|
||||||
|
mPoint.translate(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Node::isCoincident(Node* node) const
|
||||||
|
{
|
||||||
|
return node->getPoint() == mPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::setState(State state)
|
||||||
|
{
|
||||||
|
mState = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node::State Node::getState() const
|
||||||
|
{
|
||||||
|
return mState;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::clearConnectivity()
|
||||||
|
{
|
||||||
|
mAssociatedEdgeIds.clear();
|
||||||
|
mAssociatedFaceIds.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Node::getNumConnectedEdges() const
|
||||||
|
{
|
||||||
|
return mAssociatedEdgeIds.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Node::getNumConnectedFaces() const
|
||||||
|
{
|
||||||
|
return mAssociatedFaceIds.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::associateEdge(unsigned edgeId)
|
||||||
|
{
|
||||||
|
mAssociatedEdgeIds.push_back(edgeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::associateFace(unsigned faceId)
|
||||||
|
{
|
||||||
|
mAssociatedFaceIds.push_back(faceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Node::getConnectedEdgeId(std::size_t idx) const
|
||||||
|
{
|
||||||
|
return mAssociatedEdgeIds[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Node::getConnectedFaceId(std::size_t idx) const
|
||||||
|
{
|
||||||
|
return mAssociatedFaceIds[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::setIndex(std::size_t idx)
|
||||||
|
{
|
||||||
|
mIndex = idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,41 +6,65 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
class Node
|
class Node
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
enum class State
|
||||||
|
{
|
||||||
|
HEALTHY,
|
||||||
|
DIRTY
|
||||||
|
};
|
||||||
|
|
||||||
Node(const Point& p, unsigned index = 0);
|
Node(const Point& p, unsigned index = 0);
|
||||||
|
|
||||||
static std::unique_ptr<Node> Create(const Point& p, unsigned index = 0);
|
static std::unique_ptr<Node> Create(const Point& p, unsigned index = 0);
|
||||||
|
|
||||||
~Node();
|
~Node();
|
||||||
|
|
||||||
unsigned getIndex() const;
|
void associateEdge(unsigned edgeId);
|
||||||
|
|
||||||
void updateIndex(unsigned index);
|
void associateFace(unsigned faceId);
|
||||||
|
|
||||||
const Point& getPoint() const
|
|
||||||
{
|
|
||||||
return mPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addVectorAttribute(const std::string& tag, const std::vector<double>& values);
|
void addVectorAttribute(const std::string& tag, const std::vector<double>& values);
|
||||||
|
|
||||||
|
void clearConnectivity();
|
||||||
|
|
||||||
|
unsigned getIndex() const;
|
||||||
|
|
||||||
|
unsigned getNumConnectedEdges() const;
|
||||||
|
|
||||||
|
unsigned getNumConnectedFaces() const;
|
||||||
|
|
||||||
|
unsigned getConnectedEdgeId(std::size_t idx) const;
|
||||||
|
|
||||||
|
unsigned getConnectedFaceId(std::size_t idx) const;
|
||||||
|
|
||||||
|
State getState() const;
|
||||||
|
|
||||||
|
const Point& getPoint() const;
|
||||||
|
|
||||||
std::vector<double> getVectorAttribute(const std::string& tag) const;
|
std::vector<double> getVectorAttribute(const std::string& tag) const;
|
||||||
|
|
||||||
void scale(double x, double y)
|
bool isCoincident(Node* node) const;
|
||||||
{
|
|
||||||
mPoint.scale(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
void translate(double x, double y, double z = 0.0)
|
void setState(State state);
|
||||||
{
|
|
||||||
mPoint.translate(x, y, z);
|
void setIndex(std::size_t idx);
|
||||||
}
|
|
||||||
|
void updateIndex(unsigned index);
|
||||||
|
|
||||||
|
void scale(double x, double y);
|
||||||
|
|
||||||
|
void translate(double x, double y, double z = 0.0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::string, std::vector<double> > mVectorAttributes;
|
std::unordered_map<std::string, std::vector<double> > mVectorAttributes;
|
||||||
unsigned mIndex{0};
|
unsigned mIndex{0};
|
||||||
Point mPoint;
|
Point mPoint;
|
||||||
|
|
||||||
|
std::vector<unsigned> mAssociatedEdgeIds;
|
||||||
|
std::vector<unsigned> mAssociatedFaceIds;
|
||||||
|
|
||||||
|
State mState{State::HEALTHY};
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,3 +25,51 @@ std::vector<unsigned> TriFace::getNodeIds() const
|
||||||
{
|
{
|
||||||
return {mEdge0->getNode0Id(), mEdge0->getNode1Id(), mEdge1->getNode1Id()};
|
return {mEdge0->getNode0Id(), mEdge0->getNode1Id(), mEdge1->getNode1Id()};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned TriFace::getNumNodes() const
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TriFace::replaceEdge(Edge* original, Edge* replacement)
|
||||||
|
{
|
||||||
|
if (original == mEdge0)
|
||||||
|
{
|
||||||
|
mEdge0 = replacement;
|
||||||
|
}
|
||||||
|
else if (original == mEdge1)
|
||||||
|
{
|
||||||
|
mEdge1 = replacement;
|
||||||
|
}
|
||||||
|
else if (original == mEdge2)
|
||||||
|
{
|
||||||
|
mEdge2 = replacement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned TriFace::getEdge0Id () const
|
||||||
|
{
|
||||||
|
return mEdge0->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned TriFace::getEdge1Id () const
|
||||||
|
{
|
||||||
|
return mEdge1->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned TriFace::getEdge2Id () const
|
||||||
|
{
|
||||||
|
return mEdge2->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned> TriFace::getEdgeIds() const
|
||||||
|
{
|
||||||
|
return {mEdge0->getId(), mEdge1->getId(), mEdge2->getId()};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TriFace::associateWidthEdges()
|
||||||
|
{
|
||||||
|
mEdge0->associateFace(mId);
|
||||||
|
mEdge1->associateFace(mId);
|
||||||
|
mEdge2->associateFace(mId);
|
||||||
|
}
|
||||||
|
|
|
@ -11,12 +11,22 @@ public:
|
||||||
|
|
||||||
~TriFace();
|
~TriFace();
|
||||||
|
|
||||||
std::vector<unsigned> getNodeIds() const override;
|
|
||||||
|
|
||||||
static std::unique_ptr<TriFace> Create(Edge* edge0, Edge* edge1, Edge* edge2, unsigned id=0);
|
static std::unique_ptr<TriFace> Create(Edge* edge0, Edge* edge1, Edge* edge2, unsigned id=0);
|
||||||
|
|
||||||
private:
|
void associateWidthEdges() override;
|
||||||
|
|
||||||
|
std::vector<unsigned> getNodeIds() const override;
|
||||||
|
|
||||||
|
unsigned getNumNodes() const override;
|
||||||
|
|
||||||
|
void replaceEdge(Edge* original, Edge* replacement);
|
||||||
|
|
||||||
|
unsigned getEdge0Id () const;
|
||||||
|
unsigned getEdge1Id () const;
|
||||||
|
unsigned getEdge2Id () const;
|
||||||
|
std::vector<unsigned> getEdgeIds() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
Edge* mEdge0{nullptr};
|
Edge* mEdge0{nullptr};
|
||||||
Edge* mEdge1{nullptr};
|
Edge* mEdge1{nullptr};
|
||||||
Edge* mEdge2{nullptr};
|
Edge* mEdge2{nullptr};
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include "TriMesh.h"
|
#include "TriMesh.h"
|
||||||
|
|
||||||
#include "Node.h"
|
|
||||||
#include "Edge.h"
|
#include "Edge.h"
|
||||||
#include "TriFace.h"
|
#include "TriFace.h"
|
||||||
|
|
||||||
|
@ -9,43 +8,39 @@ TriMesh::~TriMesh()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriMesh::populate(VecNodes& nodes, VecEdges& edges, VecFaces& faces)
|
AbstractMesh::MeshType TriMesh::getType() const
|
||||||
{
|
{
|
||||||
mNodes = std::move(nodes);
|
return AbstractMesh::MeshType::TRI;
|
||||||
mEdges = std::move(edges);
|
|
||||||
mFaces = std::move(faces);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned> TriMesh::getFaceNodeIds() const
|
std::unique_ptr<AbstractMesh> TriMesh::copy() const
|
||||||
{
|
{
|
||||||
unsigned nodes_per_face = 3;
|
VecNodes nodes(mNodes.size());
|
||||||
std::vector<unsigned> ids(nodes_per_face*mFaces.size());
|
unsigned count = 0;
|
||||||
|
for (auto& node : mNodes)
|
||||||
for(std::size_t idx=0; idx<mFaces.size(); idx++)
|
|
||||||
{
|
{
|
||||||
const auto nodeIds = mFaces[idx]->getNodeIds();
|
nodes[count] = std::make_unique<Node>(node->getPoint());
|
||||||
for(std::size_t jdx=0; jdx<nodes_per_face; jdx++)
|
count++;
|
||||||
{
|
|
||||||
ids[nodes_per_face*idx + jdx] = nodeIds[jdx];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ids;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::vector<double> > TriMesh::getFaceVectorAttributes(const std::string& tag)
|
VecEdges edges(mEdges.size());
|
||||||
|
count = 0;
|
||||||
|
for (auto& edge : mEdges)
|
||||||
{
|
{
|
||||||
std::vector<std::vector<double> > attribs(mFaces.size());
|
edges[count] = std::make_unique<Edge>(nodes[edge->getNode0Id()].get(), nodes[edge->getNode0Id()].get());
|
||||||
for(std::size_t idx=0; idx<mFaces.size(); idx++)
|
count++;
|
||||||
{
|
|
||||||
attribs[idx] = {mFaces[idx]->getVectorAttribute(tag)};
|
|
||||||
}
|
|
||||||
return attribs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriMesh::addConstantFaceVectorAttribute(const std::string& tag, const std::vector<double>& values)
|
VecFaces faces(mFaces.size());
|
||||||
|
count = 0;
|
||||||
|
for (auto& face : mFaces)
|
||||||
{
|
{
|
||||||
for (const auto& face : mFaces)
|
auto ids = face->getEdgeIds();
|
||||||
{
|
faces[count] = std::make_unique<TriFace>(edges[ids[0]].get(), edges[ids[1]].get(), edges[ids[2]].get());
|
||||||
face->addVectorAttribute(tag, values);
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto mesh = std::make_unique<TriMesh>();
|
||||||
|
mesh->populate(nodes, edges, faces);
|
||||||
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,40 +1,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "AbstractMesh.h"
|
#include "FaceMesh.h"
|
||||||
|
|
||||||
#include <string>
|
class TriMesh : public FaceMesh
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
class Edge;
|
|
||||||
class TriFace;
|
|
||||||
|
|
||||||
using EdgePtr = std::unique_ptr<Edge>;
|
|
||||||
using TriFacePtr = std::unique_ptr<TriFace>;
|
|
||||||
|
|
||||||
using VecEdges = std::vector<EdgePtr>;
|
|
||||||
using VecFaces = std::vector<TriFacePtr>;
|
|
||||||
|
|
||||||
class TriMesh : public AbstractMesh
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TriMesh() = default;
|
TriMesh() = default;
|
||||||
|
|
||||||
~TriMesh();
|
~TriMesh();
|
||||||
|
|
||||||
void populate(VecNodes& nodes, VecEdges& edges, VecFaces& faces);
|
std::unique_ptr<AbstractMesh> copy() const override;
|
||||||
|
|
||||||
std::vector<unsigned> getFaceNodeIds() const;
|
MeshType getType() const;
|
||||||
|
|
||||||
void addConstantFaceVectorAttribute(const std::string& tag, const std::vector<double>& values);
|
|
||||||
|
|
||||||
std::vector<std::vector<double> > getFaceVectorAttributes(const std::string& tag);
|
|
||||||
|
|
||||||
MeshType getType() const
|
|
||||||
{
|
|
||||||
return MeshType::TRI;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
VecEdges mEdges;
|
|
||||||
VecFaces mFaces;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,6 +16,7 @@ list(APPEND ui_elements_LIB_INCLUDES
|
||||||
ui_events/ResizeEvent.cpp
|
ui_events/ResizeEvent.cpp
|
||||||
widgets/Widget.cpp
|
widgets/Widget.cpp
|
||||||
widgets/Button.cpp
|
widgets/Button.cpp
|
||||||
|
widgets/ButtonGroup.cpp
|
||||||
widgets/Label.cpp
|
widgets/Label.cpp
|
||||||
widgets/HorizontalSpacer.cpp
|
widgets/HorizontalSpacer.cpp
|
||||||
widgets/VerticalSpacer.cpp
|
widgets/VerticalSpacer.cpp
|
||||||
|
|
0
src/ui_elements/widgets/ButtonGroup.cpp
Normal file
0
src/ui_elements/widgets/ButtonGroup.cpp
Normal file
23
src/ui_elements/widgets/ButtonGroup.h
Normal file
23
src/ui_elements/widgets/ButtonGroup.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Widget.h"
|
||||||
|
|
||||||
|
class ButtonGroup : public Widget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum class Orientation
|
||||||
|
{
|
||||||
|
HORIZONTAL,
|
||||||
|
VERTICAL
|
||||||
|
};
|
||||||
|
|
||||||
|
ButtonGroup();
|
||||||
|
|
||||||
|
~ButtonGroup();
|
||||||
|
|
||||||
|
static std::unique_ptr<ButtonGroup> Create();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool mExclusiveActivation{true};
|
||||||
|
};
|
Loading…
Reference in a new issue