Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hackathon/edge mesh #378

Merged
merged 59 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from 57 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
ba90699
add dummy files
Zhouyuan-Chen Sep 22, 2023
5095f98
fixed problem
Zhouyuan-Chen Sep 22, 2023
f792fb4
added throws for safety
Zhouyuan-Chen Sep 22, 2023
d412649
implemented some EdgeMesh functions
Zhouyuan-Chen Sep 22, 2023
96325c6
add EdgeMeshOperationExecutor and DEBUG_EdgeMesh
Zhouyuan-Chen Sep 26, 2023
b749fac
add EdgeMesh_example and test code
Zhouyuan-Chen Sep 27, 2023
01ba6f1
fix a bug for EdgeMesh::initialize, the loop's condition wrong.
Zhouyuan-Chen Sep 27, 2023
d9e3742
Merge remote-tracking branch 'origin/main' into hackathon/edge_mesh
zlyfunction Sep 27, 2023
37392a7
get the desired frame for edgemesh operation executor
zlyfunction Sep 27, 2023
b551d2d
implement edgemesh split_edge
zlyfunction Sep 27, 2023
913e166
fimish edgemesh split_edge with return tuple
zlyfunction Sep 27, 2023
455c867
correct edgemsh split without aorientation assumptions
zlyfunction Sep 27, 2023
a75edd4
implement edge mesh connectivity
JcDai Sep 27, 2023
b6e2844
take care of the case of self loop
zlyfunction Sep 27, 2023
588530a
a complete draft of edge mesh operations
zlyfunction Sep 27, 2023
2f50e69
Merge branch 'hackathon/edge_mesh' of https://github.com/wildmeshing/…
JcDai Sep 27, 2023
b006e30
implemented edge mesh
JcDai Sep 27, 2023
1a91445
add 1d topology unit test
JcDai Sep 27, 2023
7f9f178
add implementation for operations in edgemesh clas
JcDai Sep 27, 2023
0f1e5c4
fix typo
JcDai Sep 27, 2023
4b549e2
add debug_edgemesh examples
JcDai Sep 27, 2023
d6f79e0
fix bug
JcDai Sep 27, 2023
51e750d
rename tmoe to emoe
zlyfunction Sep 27, 2023
9d210e5
add 1d tuple tests
JcDai Sep 27, 2023
4c1fc6d
Merge branch 'hackathon/edge_mesh' of https://github.com/wildmeshing/…
JcDai Sep 27, 2023
6cd9330
Merge remote-tracking branch 'origin/main' into hackathon/edge_mesh
JcDai Sep 27, 2023
8443678
clean codes
JcDai Sep 27, 2023
93078ed
fix collapse
zlyfunction Sep 28, 2023
0191bc1
add test simplices_to_delete_for_split_1D
zlyfunction Sep 28, 2023
f9339ea
add test simplices_to_delete
zlyfunction Sep 28, 2023
e680734
add split and collapse test, need fix collapse
zlyfunction Sep 28, 2023
36f5b4b
fix ccw, still need fix collapse
zlyfunction Sep 28, 2023
d5ae116
add more 1d topology test
JcDai Sep 28, 2023
8cbc009
Merge branch 'hackathon/edge_mesh' of https://github.com/wildmeshing/…
JcDai Sep 28, 2023
436714d
fix collapse, seems to be correct
zlyfunction Sep 28, 2023
3af5411
Merge branch 'hackathon/edge_mesh' of https://github.com/wildmeshing/…
JcDai Sep 28, 2023
d3fd978
add is_simplex_deleted function in DEBUG_EdgeMesh
zlyfunction Sep 28, 2023
8163b71
fix collapse edge ev update
zlyfunction Sep 28, 2023
36ef0f2
fix bug for self loop otopo init
JcDai Sep 28, 2023
4fff8d8
Merge branch 'main' into hackathon/edge_mesh
Sep 29, 2023
e43b219
collapse test add return_tuple check and delete simplex test
Sep 29, 2023
4f59656
fix bug in update ve in collapse edge
Sep 29, 2023
e20fd21
finish testing collapse edge
Sep 29, 2023
add571d
fix bug in split_edge ev update
Sep 29, 2023
22c615a
finish split test
zlyfunction Sep 29, 2023
3844c20
refactor based on comments
JcDai Oct 3, 2023
57f8aae
Merge remote-tracking branch 'origin/main' into hackathon/edge_mesh
JcDai Oct 3, 2023
cf18878
add throw
JcDai Oct 3, 2023
56e6040
redo changes in TriMesh
JcDai Oct 3, 2023
d3cd444
rollback the redo for Trimesh
JcDai Oct 3, 2023
29a6674
refactor based on comments
zlyfunction Oct 4, 2023
fd11974
reuse hash acc in tests
zlyfunction Oct 4, 2023
88f62a7
fix DEBUG_EdgeMesh::operator==
zlyfunction Oct 4, 2023
0409e9b
Merge branch 'main' into hackathon/edge_mesh
zlyfunction Oct 9, 2023
281e5cc
Merge branch 'main' of https://github.com/wildmeshing/wildmeshing-too…
zlyfunction Oct 9, 2023
6540991
modify to fit the changes happend in main branch
zlyfunction Oct 9, 2023
3ee54bc
typo in comment
zlyfunction Oct 11, 2023
25251ca
fix compile
zlyfunction Oct 11, 2023
e991d24
delete TODO in comments
zlyfunction Oct 11, 2023
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
4 changes: 4 additions & 0 deletions src/wmtk/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ set(SRC_FILES
Mesh.hpp
PointMesh.cpp
PointMesh.hpp
EdgeMesh.hpp
EdgeMesh.cpp
TriMesh.cpp
TriMesh.hpp
TetMesh.cpp
TetMesh.hpp
EdgeMeshOperationExecutor.hpp
EdgeMeshOperationExecutor.cpp
TriMeshOperationExecutor.hpp
TriMeshOperationExecutor.cpp
TetMeshOperationExecutor.hpp
Expand Down
262 changes: 262 additions & 0 deletions src/wmtk/EdgeMesh.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
#include "EdgeMesh.hpp"


#include <wmtk/utils/edgemesh_topology_initialization.h>
#include <wmtk/EdgeMeshOperationExecutor.hpp>
#include <wmtk/SimplicialComplex.hpp>
#include <wmtk/utils/Logger.hpp>
namespace wmtk {
EdgeMesh::EdgeMesh()
: Mesh(1)
, m_ve_handle(register_attribute<long>("m_ve", PrimitiveType::Vertex, 1))
, m_ev_handle(register_attribute<long>("m_ev", PrimitiveType::Edge, 2))
, m_ee_handle(register_attribute<long>("m_ee", PrimitiveType::Edge, 2))
{}
EdgeMesh::EdgeMesh(const EdgeMesh& o) = default;

Check warning on line 15 in src/wmtk/EdgeMesh.cpp

View check run for this annotation

Codecov / codecov/patch

src/wmtk/EdgeMesh.cpp#L15

Added line #L15 was not covered by tests
EdgeMesh::EdgeMesh(EdgeMesh&& o) = default;
EdgeMesh& EdgeMesh::operator=(const EdgeMesh& o) = default;

Check warning on line 17 in src/wmtk/EdgeMesh.cpp

View check run for this annotation

Codecov / codecov/patch

src/wmtk/EdgeMesh.cpp#L17

Added line #L17 was not covered by tests
EdgeMesh& EdgeMesh::operator=(EdgeMesh&& o) = default;

Tuple EdgeMesh::split_edge(const Tuple& t, Accessor<long>& hash_accessor)

Check warning on line 20 in src/wmtk/EdgeMesh.cpp

View check run for this annotation

Codecov / codecov/patch

src/wmtk/EdgeMesh.cpp#L20

Added line #L20 was not covered by tests
{
EdgeMesh::EdgeMeshOperationExecutor executor(*this, t, hash_accessor);
return executor.split_edge();
}

Check warning on line 24 in src/wmtk/EdgeMesh.cpp

View check run for this annotation

Codecov / codecov/patch

src/wmtk/EdgeMesh.cpp#L22-L24

Added lines #L22 - L24 were not covered by tests

Tuple EdgeMesh::collapse_edge(const Tuple& t, Accessor<long>& hash_accessor)

Check warning on line 26 in src/wmtk/EdgeMesh.cpp

View check run for this annotation

Codecov / codecov/patch

src/wmtk/EdgeMesh.cpp#L26

Added line #L26 was not covered by tests
{
EdgeMesh::EdgeMeshOperationExecutor executor(*this, t, hash_accessor);
return executor.collapse_edge();
}

Check warning on line 30 in src/wmtk/EdgeMesh.cpp

View check run for this annotation

Codecov / codecov/patch

src/wmtk/EdgeMesh.cpp#L28-L30

Added lines #L28 - L30 were not covered by tests

long EdgeMesh::id(const Tuple& tuple, PrimitiveType type) const
{
switch (type) {
case PrimitiveType::Vertex: {
ConstAccessor<long> ev_accessor = create_const_accessor<long>(m_ev_handle);
auto ev = ev_accessor.vector_attribute(tuple);
return ev(tuple.m_local_vid);
}
case PrimitiveType::Edge: {
return tuple.m_global_cid;
}
case PrimitiveType::Face:
case PrimitiveType::Tetrahedron:
default: throw std::runtime_error("Tuple id: Invalid primitive type");

Check warning on line 45 in src/wmtk/EdgeMesh.cpp

View check run for this annotation

Codecov / codecov/patch

src/wmtk/EdgeMesh.cpp#L43-L45

Added lines #L43 - L45 were not covered by tests
}
}

bool EdgeMesh::is_boundary(const Tuple& tuple) const
{
return is_boundary_vertex(tuple);
}

bool EdgeMesh::is_boundary_vertex(const Tuple& tuple) const
{
assert(is_valid_slow(tuple));
ConstAccessor<long> ee_accessor = create_const_accessor<long>(m_ee_handle);
return ee_accessor.vector_attribute(tuple)(tuple.m_local_vid) < 0;
}

Tuple EdgeMesh::switch_tuple(const Tuple& tuple, PrimitiveType type) const
{
assert(is_valid_slow(tuple));
bool ccw = is_ccw(tuple);

switch (type) {
case PrimitiveType::Vertex:
return Tuple(
1 - tuple.m_local_vid,
tuple.m_local_eid,
tuple.m_local_fid,
tuple.m_global_cid,
tuple.m_hash);
case PrimitiveType::Edge: {
const long gvid = id(tuple, PrimitiveType::Vertex);

ConstAccessor<long> ee_accessor = create_const_accessor<long>(m_ee_handle);
auto ee = ee_accessor.vector_attribute(tuple);

long gcid_new = ee(tuple.m_local_vid);

// TODO: This is for special case self-loop, just to make sure the local vid of the returned
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this TODO still a TODO?

// tuple is the same as the input. (When doing double-switch this is needed)
if (gcid_new == tuple.m_global_cid) {
return tuple;
}

long lvid_new = -1;

ConstAccessor<long> ev_accessor = create_const_accessor<long>(m_ev_handle);
auto ev = ev_accessor.index_access().vector_attribute(gcid_new);

for (long i = 0; i < 2; ++i) {
if (ev(i) == gvid) {
lvid_new = i;
// break;
}
}
assert(lvid_new != -1);

ConstAccessor<long> hash_accessor = get_const_cell_hash_accessor();

const Tuple res(
lvid_new,
tuple.m_local_eid,
tuple.m_local_fid,
gcid_new,
get_cell_hash(gcid_new, hash_accessor));
assert(is_valid(res, hash_accessor));
return res;
}
case PrimitiveType::Face:
case PrimitiveType::Tetrahedron:
default: throw std::runtime_error("Tuple switch: Invalid primitive type"); break;

Check warning on line 114 in src/wmtk/EdgeMesh.cpp

View check run for this annotation

Codecov / codecov/patch

src/wmtk/EdgeMesh.cpp#L112-L114

Added lines #L112 - L114 were not covered by tests
}
}

bool EdgeMesh::is_ccw(const Tuple& tuple) const
{
assert(is_valid_slow(tuple));
return tuple.m_local_vid == 0;
}

void EdgeMesh::initialize(
Eigen::Ref<const RowVectors2l> EV,
Eigen::Ref<const RowVectors2l> EE,
Eigen::Ref<const VectorXl> VE)
{
// reserve memory for attributes

std::vector<long> cap{static_cast<long>(VE.rows()), static_cast<long>(EE.rows())};

set_capacities(cap);

// get accessors for topology
Accessor<long> ev_accessor = create_accessor<long>(m_ev_handle);
Accessor<long> ee_accessor = create_accessor<long>(m_ee_handle);
Accessor<long> ve_accessor = create_accessor<long>(m_ve_handle);

Accessor<char> v_flag_accessor = get_flag_accessor(PrimitiveType::Vertex);
Accessor<char> e_flag_accessor = get_flag_accessor(PrimitiveType::Edge);

// iterate over the matrices and fill attributes

for (long i = 0; i < capacity(PrimitiveType::Edge); ++i) {
ev_accessor.index_access().vector_attribute(i) = EV.row(i).transpose();
ee_accessor.index_access().vector_attribute(i) = EE.row(i).transpose();

e_flag_accessor.index_access().scalar_attribute(i) |= 0x1;
}
// m_ve
for (long i = 0; i < capacity(PrimitiveType::Vertex); ++i) {
ve_accessor.index_access().scalar_attribute(i) = VE(i);
v_flag_accessor.index_access().scalar_attribute(i) |= 0x1;
}
}

void EdgeMesh::initialize(Eigen::Ref<const RowVectors2l> E)
{
auto [EE, VE] = edgemesh_topology_initialization(E);
initialize(E, EE, VE);
}

long EdgeMesh::_debug_id(const Tuple& tuple, PrimitiveType type) const
{
wmtk::logger().warn("This function must only be used for debugging!!");
return id(tuple, type);
}

Tuple EdgeMesh::tuple_from_id(const PrimitiveType type, const long gid) const
{
switch (type) {
case PrimitiveType::Vertex: {
return vertex_tuple_from_id(gid);
}
case PrimitiveType::Edge: {
return edge_tuple_from_id(gid);
}
case PrimitiveType::Face: {
throw std::runtime_error("no tet tuple supported for edgemesh");
break;

Check warning on line 181 in src/wmtk/EdgeMesh.cpp

View check run for this annotation

Codecov / codecov/patch

src/wmtk/EdgeMesh.cpp#L179-L181

Added lines #L179 - L181 were not covered by tests
}
case PrimitiveType::Tetrahedron: {
throw std::runtime_error("no tet tuple supported for edgemesh");
break;

Check warning on line 185 in src/wmtk/EdgeMesh.cpp

View check run for this annotation

Codecov / codecov/patch

src/wmtk/EdgeMesh.cpp#L183-L185

Added lines #L183 - L185 were not covered by tests
}
default: throw std::runtime_error("Invalid primitive type"); break;

Check warning on line 187 in src/wmtk/EdgeMesh.cpp

View check run for this annotation

Codecov / codecov/patch

src/wmtk/EdgeMesh.cpp#L187

Added line #L187 was not covered by tests
}
}

Tuple EdgeMesh::vertex_tuple_from_id(long id) const
{
ConstAccessor<long> ve_accessor = create_const_accessor<long>(m_ve_handle);
auto e = ve_accessor.index_access().scalar_attribute(id);
ConstAccessor<long> ev_accessor = create_const_accessor<long>(m_ev_handle);
auto ev = ev_accessor.index_access().vector_attribute(e);
for (long i = 0; i < 2; ++i) {
if (ev(i) == id) {
Tuple v_tuple = Tuple(i, -1, -1, e, get_cell_hash_slow(e));
return v_tuple;
}
}
throw std::runtime_error("vertex_tuple_from_id failed");

Check warning on line 203 in src/wmtk/EdgeMesh.cpp

View check run for this annotation

Codecov / codecov/patch

src/wmtk/EdgeMesh.cpp#L203

Added line #L203 was not covered by tests
}

Tuple EdgeMesh::edge_tuple_from_id(long id) const
{
Tuple e_tuple = Tuple(0, -1, -1, id, get_cell_hash_slow(id));

assert(is_valid_slow(e_tuple));
return e_tuple;
}

bool EdgeMesh::is_valid(const Tuple& tuple, ConstAccessor<long>& hash_accessor) const
{
if (tuple.is_null()) return false;

if (tuple.m_local_vid < 0 || tuple.m_global_cid < 0) return false;

return Mesh::is_hash_valid(tuple, hash_accessor);
}

bool EdgeMesh::is_connectivity_valid() const
{
// get accessors for topology
ConstAccessor<long> ev_accessor = create_const_accessor<long>(m_ev_handle);
ConstAccessor<long> ee_accessor = create_const_accessor<long>(m_ee_handle);
ConstAccessor<long> ve_accessor = create_const_accessor<long>(m_ve_handle);
ConstAccessor<char> v_flag_accessor = get_flag_accessor(PrimitiveType::Vertex);
ConstAccessor<char> e_flag_accessor = get_flag_accessor(PrimitiveType::Edge);

// VE and EV
for (long i = 0; i < capacity(PrimitiveType::Vertex); ++i) {
if (v_flag_accessor.index_access().scalar_attribute(i) == 0) {
wmtk::logger().debug("Vertex {} is deleted", i);
continue;
}
int cnt = 0;
for (long j = 0; j < 2; ++j) {
if (ev_accessor.index_access().vector_attribute(
ve_accessor.index_access().scalar_attribute(i))[j] == i) {
cnt++;
}
}
if (cnt == 0) {
return false;

Check warning on line 246 in src/wmtk/EdgeMesh.cpp

View check run for this annotation

Codecov / codecov/patch

src/wmtk/EdgeMesh.cpp#L246

Added line #L246 was not covered by tests
}
}

// EV and EE
for (long i = 0; i < capacity(PrimitiveType::Edge); ++i) {
if (e_flag_accessor.index_access().scalar_attribute(i) == 0) {
wmtk::logger().debug("Edge {} is deleted", i);
continue;
}
// TODO: need to handle cornor case (self-loop)
JcDai marked this conversation as resolved.
Show resolved Hide resolved
}

return true;
}

} // namespace wmtk
82 changes: 82 additions & 0 deletions src/wmtk/EdgeMesh.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#pragma once

#include "Mesh.hpp"
#include "Tuple.hpp"

#include <Eigen/Core>

namespace wmtk {

class EdgeMesh : public Mesh
{
public:
EdgeMesh();
EdgeMesh(const EdgeMesh& o);
EdgeMesh(EdgeMesh&& o);
EdgeMesh& operator=(const EdgeMesh& o);
EdgeMesh& operator=(EdgeMesh&& o);

PrimitiveType top_simplex_type() const override { return PrimitiveType::Edge; }

Check warning on line 19 in src/wmtk/EdgeMesh.hpp

View check run for this annotation

Codecov / codecov/patch

src/wmtk/EdgeMesh.hpp#L19

Added line #L19 was not covered by tests

Tuple split_edge(const Tuple& t, Accessor<long>& hash_accessor);

Tuple collapse_edge(const Tuple& t, Accessor<long>& hash_accessor);

Tuple switch_tuple(const Tuple& tuple, PrimitiveType type) const override;

bool is_ccw(const Tuple& tuple) const override;
bool is_boundary(const Tuple& tuple) const override;
bool is_boundary_vertex(const Tuple& tuple) const override;
bool is_boundary_edge(const Tuple& tuple) const override

Check warning on line 30 in src/wmtk/EdgeMesh.hpp

View check run for this annotation

Codecov / codecov/patch

src/wmtk/EdgeMesh.hpp#L30

Added line #L30 was not covered by tests
{
throw("This function doesn't make sense for EdgeMesh");

Check warning on line 32 in src/wmtk/EdgeMesh.hpp

View check run for this annotation

Codecov / codecov/patch

src/wmtk/EdgeMesh.hpp#L32

Added line #L32 was not covered by tests
}

void initialize(Eigen::Ref<const RowVectors2l> E);

void initialize(
Eigen::Ref<const RowVectors2l> EV,
Eigen::Ref<const RowVectors2l> EE,
Eigen::Ref<const VectorXl> VE);

long _debug_id(const Tuple& tuple, PrimitiveType type) const;
long _debug_id(const Simplex& simplex) const
{
return _debug_id(simplex.tuple(), simplex.primitive_type());
}


bool is_valid(const Tuple& tuple, ConstAccessor<long>& hash_accessor) const override;

bool is_connectivity_valid() const override;

protected:
long id(const Tuple& tuple, PrimitiveType type) const override;
long id(const Simplex& simplex) const { return id(simplex.tuple(), simplex.primitive_type()); }

long id_vertex(const Tuple& tuple) const { return id(tuple, PrimitiveType::Vertex); }
long id_edge(const Tuple& tuple) const { return id(tuple, PrimitiveType::Edge); }

/**
* @brief internal function that returns the tuple of requested type, and has the global index
* cid
*
* @param gid
* @return Tuple
*/
Tuple tuple_from_id(const PrimitiveType type, const long gid) const override;

protected:
attribute::MeshAttributeHandle<long> m_ve_handle;

attribute::MeshAttributeHandle<long> m_ev_handle;
attribute::MeshAttributeHandle<long> m_ee_handle;

Tuple vertex_tuple_from_id(long id) const;
Tuple edge_tuple_from_id(long id) const;

// internal structure that encapsulations the actual execution of split and collapse
class EdgeMeshOperationExecutor;
};

} // namespace wmtk
Loading
Loading