How did you get around the fact that you can't return float_t[3] from the value method?

I didn't. I assumed we're using Vector template structs. For size_t[3] i added a simple wrapper struct Triangle.
I could live with the restriction to have to package static arrays in structs before i can use them with OMD.

That Domain template is a nice idea. So are the different accessors.

Quote:

Changed "indeces" to the proper spelling

oops

Quote:

One reason for the "Domain!()" thing is that I wanted to be able to add an "edge" domain since that can be useful for something like silhouette processing (tag each edge as silouhette or not). But I think there are some thorny issues there. "edge" has tight coupling with "halfedge" that's difficult to express using this totally generic approach. Resizing edges needs to be in sync with the resizing of halfedges, and you might want to add pointers between edges and their associated halfedges. I guess what needs to happen is that the core halfedgemesh sees the domain name "edge" then it will do the right thing.

I don't think this coupling is different from the couplings halfedge, vertex and face already have. The mesh is inconsistent if there are floating halfedges without vertices or faces.

Quote:

I guess that's not so bad. The thing called Mesh in the currently code is more like OM's BaseKernel, ArrayKernel and AttribKernel rolled together. The "what's 'edge' mean?" level of stuff comes from PolyConnectivity. And that's also where we implement whether it's a simple tri-list mesh or a halfedge mesh or whatever.

Yeah, normally one wouldn't use resize directly. Instead add_{vertex|halfedge|face} would be used. Those functions require appropriate additional parameters to ensure a consistent add operation. We could think about making resize (and similar operations that can affect consistency) private.
Most of what is now in ArrayKernel could be in BaseKernel, i guess. The storage container dependent part is pleasantly small.

Most of what is now in ArrayKernel could be in BaseKernel, i guess. The storage container dependent part is pleasantly small.

Is there much need for BaseKernel? I'm not sure how you'd build a non-array kernel off of this very array-oriented property stuff. But I haven't given much thought to what would be required to have non-array kernels. I think CGAL has a non-array kernel, but I don't know anything about it. The other kind of Kernel I could imagine being useful is a more node-oriented one, where each vertex carries a little struct with all properties for that vertex. And where the handles were actually pointers to nodes rather than indices. I just finished implementing a recursive divide-and-conquer type algorithm and some things would have been a lot easier with vertex handles that could remain valid after splitting a mesh in two.

Is there much need for BaseKernel? I'm not sure how you'd build a non-array kernel off of this very array-oriented property stuff. But I haven't given much thought to what would be required to have non-array kernels. I think CGAL has a non-array kernel, but I don't know anything about it.

With compile-time properties only, it's straight forward to build non-random access kernels. We simply declare one node structure per domain, containing single instances of it's properties, and build for example a linked list with them.

To support runtime properties in non-random access kernels, we either have to use per-property handles (as opposed to the per-domain handles we use now) only or simply make runtime property support optional.

I'd claim that having runtime dynamic properties is actually very obscure. OM has them only because it can't have compile-time dynamic properties in C++.

Quote:

The other kind of Kernel I could imagine being useful is a more node-oriented one, where each vertex carries a little struct with all properties for that vertex. And where the handles were actually pointers to nodes rather than indices. I just finished implementing a recursive divide-and-conquer type algorithm and some things would have been a lot easier with vertex handles that could remain valid after splitting a mesh in two.

It might be possible to keep handles valid by using change/add instead of remove/add/add for a 1-2 split for example. For topology changes that could mean to allow operations that leave the mesh in an inconsistent state, though. Just a premature thought...

Is there much need for BaseKernel? I'm not sure how you'd build a non-array kernel off of this very array-oriented property stuff. But I haven't given much thought to what would be required to have non-array kernels. I think CGAL has a non-array kernel, but I don't know anything about it.

With compile-time properties only, it's straight forward to build non-random access kernels. We simply declare one node structure per domain, containing single instances of it's properties, and build for example a linked list with them.

But that's going to require rewriting most of the prototype class. So my point was there's not much that can be usefully separated out into a BaseKernel in this design. Not that there needs to be, just saying that I think BaseKernel can go away. The only thing it has in the current version is the (very much array-centric) default properties.

I'm also not really anxious to go and create a non-array kernel, I'd just rather not design things in a way that would hinder it happening later.

jascha wrote:

To support runtime properties in non-random access kernels, we either have to use per-property handles (as opposed to the per-domain handles we use now) only or simply make runtime property support optional.

Per property handles would make sense in that case. And maybe per-domain handles could still work for CT properties.

jascha wrote:

I'd claim that having runtime dynamic properties is actually very obscure. OM has them only because it can't have compile-time dynamic properties in C++.

I don't think that's the only reason OM has them. It may have been the original reason for making it work, but it's an obviously useful thing to have. And the current code relies on it for some things like the delete/collect_garbage functionality. Those require the "status" properties to record extra info about vertics, but for memory's sake status properties are not present by default.

But that's going to require rewriting most of the prototype class. So my point was there's not much that can be usefully separated out into a BaseKernel in this design. Not that there needs to be, just saying that I think BaseKernel can go away. The only thing it has in the current version is the (very much array-centric) default properties.

Actually it appeared to me as if the changes for a linked-list kernel wouldn't be that big. It's mostly the PropertyContainer that needs to change. Since the .domains member can still be an array (it would be esoteric to force the kernel's container type here, too), the whole domains business can remain the way it is and go to the BaseKernel.
The AddProps business can stay the same, too. All we need to complement it is a Tuple with offsets into the node structure. Instead of using the index of a PropHandleCT as an index into the properties_ member of the PropContainer, we get the offset from the Tuple with that index and use it on a node.
Therefore, all the large templates can be put into the BaseKernel. Some of the functions that access a property's .data member directly could call an abstract function in the Property class instead, making them potential BaseKernel members, too.

I'll try to back up these claims with an implementation some time. But since it's not very important and doesn't require any design change, it doesn't need to be done right away.
OTOH, it might help to decide about the need for per property handles. We should be able to add them later, as well, though.

Quote:

I don't think that's the only reason OM has them. It may have been the original reason for making it work, but it's an obviously useful thing to have. And the current code relies on it for some things like the delete/collect_garbage functionality. Those require the "status" properties to record extra info about vertics, but for memory's sake status properties are not present by default.

Yes, but i question the benefit of that. Are there algorithms that may delete elements from domains, but do so only in a sufficiently small fraction of runs?
I can think of a couple of ways to allow for runtime properties in node-based kernels, but they all have linear memory overhead for additional references.
In the current design, we could make runtime properties an optional feature and still implement the delete/garbage functionality, because the code may check for either a runtime or compile-time status property. For node-based kernels that would mean that the functionality is not available if the status property hasn't been added at compile-time.

Actually it appeared to me as if the changes for a linked-list kernel wouldn't be that big. It's mostly the PropertyContainer that needs to change. Since the .domains member can still be an array (it would be esoteric to force the kernel's container type here, too), the whole domains business can remain the way it is and go to the BaseKernel.

So then the PropertyContainer type would become a template parameter to BaseKernel? Like this?

Code:

class ArrayKernel : BaseKernel!(ArrayPropertyContainer)

jascha wrote:

The AddProps business can stay the same, too. All we need to complement it is a Tuple with offsets into the node structure. Instead of using the index of a PropHandleCT as an index into the properties_ member of the PropContainer, we get the offset from the Tuple with that index and use it on a node.
Therefore, all the large templates can be put into the BaseKernel. Some of the functions that access a property's .data member directly could call an abstract function in the Property class instead, making them potential BaseKernel members, too.

Looking at how CGAL does things, it seems they always organize data per node rather than per property. They have two kernels, a vector kernel and a list kernel, but it seems that it's basically either vector<VertexData> or list<VertexData> rather than separate arrays per-property. So a VertexHandle always returns a handle to the whole clump of vertex data. They also have operator-> overloaded on the handles to access particular vertex properties.

Anyway, if you can get the linked list version working, a node-oriented array version should be possible as well. I assume there are times when node oriented data is more efficient to access than property-oriented data.

jascha wrote:

I'll try to back up these claims with an implementation some time. But since it's not very important and doesn't require any design change, it doesn't need to be done right away.
OTOH, it might help to decide about the need for per property handles. We should be able to add them later, as well, though.

Doesn't seem necessary. The VertexHandle gives you the pointer to the node, and like you said the metadata for the property you're trying to access should be enough to get the offset into that node.