Skip to content

CellNetwork.cell_neighbors() modification #1449

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

Open
wants to merge 19 commits into
base: main
Choose a base branch
from

Conversation

2twenity
Copy link

What type of change is this?

  • Bug fix in a backwards-compatible manner.
  • New feature in a backwards-compatible manner.

Checklist

Put an x in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code.

  • I added a line to the CHANGELOG.md file in the Unreleased section under the most fitting heading (e.g. Added, Changed, Removed).
  • I ran all tests on my computer and it's all green (i.e. invoke test).
  • I ran lint on my computer and there are no errors (i.e. invoke lint).
  • I added new functions/classes and made them available on a second-level import, e.g. compas.datastructures.Mesh.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have added necessary documentation (if appropriate)

Some description.

CellNetwork.cell_neighbors

I've been trying to analyze connections between building elements using CellNetwork.cell_neighbors method and found out that simple common faces search could not work, because faces can point at the vertices with same coordinates, but which have different indexes, because there's no duplicate vertex check in CellNetwork.add_vertex method. Therefore I've modified the comparison logic to simple common vertices search. If 2 cells have more than 2 vertices in common, they might be adjacent. (Maybe a condition that points don't lie on the same line should be considered as well). This method performed quite well in a graph construction process of an HVAC received from Speckle.

Screenshot 2025-03-23 at 16 08 30

I've added this particular CellNetwork to tests/compas/datastructures/fixtures folder.

CellNetwork.add_mesh

Also I've implemeted add_mesh method to CellNetwork which simple decomposes mesh to vertices and faces, checks if it's manifold and adds as a Cell to CellNetwork

@tomvanmele
Copy link
Member

hi,

thanks for this.
would you mind fixing the lint in the code so the workflows can run properly?

we will automate this in the future, but for now this needs to be done locally...

thanks!

Copy link
Member

@tomvanmele tomvanmele left a comment

Choose a reason for hiding this comment

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

i (think i) understand what you're trying to do, but (if i understood correctly) i think we should do it differently.

with what you propose, the cell network will not care about the welding of vertices in some cases while it does care in others. this will lead to very confusing results.

we should perhaps rather change the behaviour wrt welding, and/or include a setting wrt this behaviour on a global level...

def add_mesh(self, input_mesh: Mesh):
if input_mesh.is_manifold():
# mesh.unify_cycles()
unpacked_mesh = input_mesh.to_vertices_and_faces()
Copy link
Member

Choose a reason for hiding this comment

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

vertices, faces = ...

Comment on lines 737 to 740
if self._max_vertex == -1:
vertex_diff = 0
else:
vertex_diff = self._max_vertex + 1
Copy link
Member

Choose a reason for hiding this comment

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

this can be simplified to

vertex_offset = self._max_vertex + 1

vertex_diff = self._max_vertex + 1

for vertex in unpacked_mesh[0]:
self.add_vertex(attr_dict = {"x": vertex[0], "y": vertex[1], "z":vertex[2]})
Copy link
Member

Choose a reason for hiding this comment

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

self.add_vertex(x=vertex[0], y=vertex[1], z=vertex[2])

@@ -728,6 +728,32 @@ def add_cell(self, faces, ckey=None, attr_dict=None, **kwattr):

return ckey


def add_mesh(self, input_mesh: Mesh):
Copy link
Member

Choose a reason for hiding this comment

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

i have the felling this already exists but under a different name, no @romanarust ?

Copy link
Member

Choose a reason for hiding this comment

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

no, this does not yet exist

@@ -4033,7 +4059,7 @@ def cell_face_neighbors(self, cell, face):
return nbrs

def cell_neighbors(self, cell):
"""Find the neighbors of a given cell.
"""Find the neighbors of a given cell based on common vertices.
Copy link
Member

Choose a reason for hiding this comment

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

i think this should be a different function because it does something else than what was intended by the original one...

Copy link
Author

Choose a reason for hiding this comment

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

Actually I was even thinking about proposing one more datastructure like Mesh Network. Something more practice oriented, because that's not common to have a building represented as masses or adjacent rooms only. Moreover some parts in a model can have clashes, or be adjacent on a face to face level only, or can have common vertices.
So briefly the initial functionality:

  • analyzing meshes adjacency (including collision etc)
  • storing some metadata on a mesh level (attr dict but for meshes)
  • mesh network to graph conversion (each node is a mesh centroid, edge could have some metadata about type of adjacency like collision or face adjacency)
  • graph algorithms
  • integration with compas viewer

Basically all of these could be added to CellNetwork as well, if it has no clashes with initial idea of a CellNetwork

Copy link
Member

Choose a reason for hiding this comment

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

what you describe is already under development here
https://github.com/BlockResearchGroup/compas_model

Copy link
Member

Choose a reason for hiding this comment

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

i think this should be a different function because it does something else than what was intended by the original one...

Agree. Additionally, heavy processing tasks like clash detection shouldn't be tied to the CellNetwork, as they fall under mesh processing. Identifying nearby meshes for clash detection (which I assume is the goal of this function) would be better handled with something like KDtree for spatial awareness.

Copy link
Author

Choose a reason for hiding this comment

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

The goal of this function is to convert meshes to a topologic spatial graph. Clashes were just a thing to consider, the general assumption is that the model is relatively clean with required openings etc. But now I see that maybe CellNetwork should remain more lightweight, especially considering the compas_model developments. I'll have a look at compas_model and investigate how it could be used for this task


for face in unpacked_mesh[1]:
new_face = [vertex + vertex_diff for vertex in face]
self.add_face(new_face)
Copy link
Member

Choose a reason for hiding this comment

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

fkey = self.add_face(new_face)

for face in unpacked_mesh[1]:
new_face = [vertex + vertex_diff for vertex in face]
self.add_face(new_face)
faces_lst.append(self._max_face)
Copy link
Member

Choose a reason for hiding this comment

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

faces_lst.append(fkey)

@romanarust
Copy link
Member

Hi @2twenity! Thank you for the PR!

Copy link
Author

@2twenity 2twenity left a comment

Choose a reason for hiding this comment

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

Thanks for the review! I've modified add_mesh function and reverted back cell_neighbors method, because I find it more appropriate for compas_model. Method itself should be further developed as well. Also I've added add_mesh test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants