I'm converting a Monte Carlo simulation of certain random geometries from Python to Rust. The freedom I had in Python allowed me to be somewhat sloppy about storing references to other objects all throughout my code, but this seems to be trickier to implement in Rust.
In my current Python implementation, the main object is a Geometry. It contains a dictionary of Vertexes with a unique ID (the ID is also its lookup key in the dictionary) and a dictionary of Triangles (same scenario as for Vertex). Every Triangle contains a list of three Vertexes (no dictionary this time, here it's an ordered list), and every Vertex contains a dictionary of all the Triangles that it appears in (again indexed by the Triangle's unique ID).
This leads to a whole lot of cross-references, but it does make it very easy to find things. For example, it is straightforward to find all the neighbouring Vertexes of a specific Vertex by simply looping through all the Triangles it appears in and collecting all the Vertexes that are contained in these Triangles.
For convenience, here is a summary of the data structures:
class Geometry(object):
def __init__(self):
self.vertices = {}
self.triangles = {}
class Vertex(object):
counter = 0
def __init__(self):
self.index = Vertex.counter
Vertex.counter += 1
self.triangles = {}
class Triangle(object):
counter = 0
def __init__(self, vertices):
self.index = Triangle.counter
Triangle.counter += 1
self.vertices = vertices # list of length 3
In Rust, this will not work because of the ownership model. The most straightforward alternative I could come up with would be to give the Geometry object a member HashMap of Vertexes and Triangles, just like in my Python code (again indexed by ID). The Vertex and Triangle objects would then contain a vector/array of the IDs of their 'members'. This ID can then be used to find the appropriate object in the HashMap.
For example, if a certain Triangle contains the Vertexes with IDs 1, 2, and 3, I could set the variable 'vertices' in the Triangle object to the array [1,2,3]. However, in order to actually work with the Vertex objects afterwards, I'd have to subsequently look up the object in the HashMap. This would lead to a lot of repetition all throughout the code. Furthermore, since the Triangle and Vertex structs are not aware of the struct Geometry, it will be impossible to add a method to either Triangle or Vertex that will encapsulate this process - after all, they cannot access the appropriate HashMap.
I've been thinking about a way of making this work with borrows, so that the Triangle and Vertex objects can in fact store a reference to one another. However, my experience with Rust is severely lacking, so I'm not getting very far. Some initial naive approaches always ran into problems with lifetimes and I'm even starting to doubt whether my current setup is workable at all in the Rust paradigm.
All feedback on any part of my question would be very welcome. Ideally I'm looking for a concrete suggestion on how to implement something along my line of thinking, but if you get the idea that I should rethink my entire approach, then I'd also be very happy to hear that.