# Can I put non-primitive geometries into a GeometrySet?

**URL:** <https://discourse.julialang.org/t/can-i-put-non-primitive-geometries-into-a-geometryset/121102>\
**Category:** General Usage\
**Tags:** meshes\
**Created:** [October 9, 2024, 10:07am UTC](https://discourse.julialang.org/t/can-i-put-non-primitive-geometries-into-a-geometryset/121102 "2024-10-09T10:07:58Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jfschue](https://avatars.discourse-cdn.com/v4/letter/j/5f9b8f/32.png) [@Jfschue](https://discourse.julialang.org/u/Jfschue)\
**Post date:** [October 9, 2024, 10:07am UTC](https://discourse.julialang.org/t/can-i-put-non-primitive-geometries-into-a-geometryset/121102/1 "2024-10-09T10:07:58Z")

</div>

If I put a SimpleMesh geometry into a GeometrySet, I get a StackOverflowError:

```julia
using Meshes

# test using primitive geometries
s1 = Meshes.Sphere((0, 0, 0), 1)
s2 = Meshes.Sphere((1, 1, 1), 1)
gs1 = GeometrySet([s1, s2]) # works fine

# test using Meshes
s3 = discretize(s1, RegularDiscretization(10, 10))
s4 = discretize(s2, RegularDiscretization(10, 10))
gs2 = GeometrySet([s3, s4]) # throws StackOverflowError

StackOverflowError:

Stacktrace:
  [1] _stable_typeof
    @ ./operators.jl:910 [inlined]
  [2] Base.Fix2(f::typeof(isequal), x::Type)
    @ Base ./operators.jl:1121
  [3] isequal
    @ ./operators.jl:1136 [inlined]
  [4] allequal
    @ ./set.jl:533 [inlined]
  [5] GeometrySet(geoms::Vector{SimpleMesh{𝔼{3}, Cartesian3D{NoDatum, Quantity{Float64, 𝐋, Unitful.FreeUnits{(m,), 𝐋, nothing}}}, Vector{Meshes.Point{𝔼{3}, Cartesian3D{NoDatum, Quantity{Float64, 𝐋, Unitful.FreeUnits{(m,), 𝐋, nothing}}}}}, SimpleTopology{Connectivity}}})
    @ Meshes ~/.julia/packages/Meshes/fFipW/src/domains/sets.jl:29
  [6] GeometrySet(geoms::Vector{SimpleMesh{𝔼{3}, Cartesian3D{NoDatum, Quantity{Float64, 𝐋, Unitful.FreeUnits{(m,), 𝐋, nothing}}}, Vector{Meshes.Point{𝔼{3}, Cartesian3D{NoDatum, Quantity{Float64, 𝐋, Unitful.FreeUnits{(m,), 𝐋, nothing}}}}}, SimpleTopology{Connectivity}}}) (repeats 74533 times)
    @ Meshes ~/.julia/packages/Meshes/fFipW/src/domains/sets.jl:35
  [7] eval
    @ ./boot.jl:370 [inlined]
  [8] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
    @ Base ./loading.jl:1903
...

```

Thoughts, suggestions? I’m new to Meshes.jl, so very possibly doing something stupid. I am headed in this direction (meshes in GeometrySets) because ultimately I want to save multiple geometries into an OBJ or PLY file and it seems like using a geotable and GeoIO would be a convenient way to do that.

Many thanks!

I’m using Julia 1.9.2 and Meshes.jl 0.51.19

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [October 9, 2024, 11:09am UTC](https://discourse.julialang.org/t/can-i-put-non-primitive-geometries-into-a-geometryset/121102/2 "2024-10-09T11:09:48Z")

</div>

In Meshes.jl we differentiate between `Geometry` and `Domain`. The `Domain` is a collection of geometries. The `GeometrySet` is a `Domain` where the geometries know nothing about each other.

> [Can I put non-primitive geometries into a GeometrySet?](https://discourse.julialang.org/t/can-i-put-non-primitive-geometries-into-a-geometryset/121102)

You can store any `Geometry` in a `GeometrySet`, including `Primitive` and `Polytope` geometries.

Did you have a chance to read the GDSJL book?

[https://juliaearth.github.io/geospatial-data-science-with-julia](https://juliaearth.github.io/geospatial-data-science-with-julia)

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [October 9, 2024, 11:22am UTC](https://discourse.julialang.org/t/can-i-put-non-primitive-geometries-into-a-geometryset/121102/3 "2024-10-09T11:22:16Z")

</div>

> [@Jfschue](#):
>
> I want to save multiple geometries into an OBJ or PLY file and it seems like using a geotable and GeoIO would be a convenient way to do that.

The GeoTable stores a single `Domain` in the `:geometry` column. GeoIO.jl can only load/save one GeoTable at a time. If you need to save two meshes that are the result of discretization of geometries, you can try to merge them into a single mesh.

Based on your example:

```julia
mesh1 = discretize(s1, RegularDiscretization(10, 10))
mesh2 = discretize(s2, RegularDiscretization(10, 10))

mesh = merge(mesh1, mesh2)

geotable = georef(nothing, mesh) # without attributes

GeoIO.save("file.ply", geotable)

```

---

<div class="post-metadata">

**Author:** ![Jfschue](https://avatars.discourse-cdn.com/v4/letter/j/5f9b8f/32.png) [@Jfschue](https://discourse.julialang.org/u/Jfschue)\
**Post date:** [October 9, 2024, 5:53pm UTC](https://discourse.julialang.org/t/can-i-put-non-primitive-geometries-into-a-geometryset/121102/4 "2024-10-09T17:53:19Z")

</div>

Thank you very much, Julio. Very helpful and timely replies. I was indeed being stupid and was loose in my understanding of `Domain` (even though I had read GDSJL… too quickly).

I am unfortunately having some trouble with the practicalities of merging. If I create meshes from a box and a sphere and merge them, the new mesh seems to have all the vertices of the combination, but only the connectivity from the box. Here’s an example:

```julia
box1_mesh = discretize(Meshes.Box((1, 1, 1), (2, 2, 2)), RegularDiscretization(1, 1))
sphere1_mesh = discretize(Meshes.Sphere((2, 2, 2), 0.5), RegularDiscretization(4, 4))
# one box and one sphere do not merge as expected (by me)
oneeach = merge(box1_mesh, sphere1_mesh)
1 SimpleMesh
  30 vertices
  ├─ Point(x: 1.0 m, y: 1.0 m, z: 1.0 m)
  ├─ Point(x: 2.0 m, y: 1.0 m, z: 1.0 m)
  ├─ Point(x: 1.0 m, y: 2.0 m, z: 1.0 m)
  ├─ Point(x: 2.0 m, y: 2.0 m, z: 1.0 m)
  ├─ Point(x: 1.0 m, y: 1.0 m, z: 2.0 m)
  ⋮
  ├─ Point(x: 2.0 m, y: 1.5 m, z: 2.0 m)
  ├─ Point(x: 2.0 m, y: 1.5669872981077806 m, z: 1.75 m)
  ├─ Point(x: 2.0 m, y: 1.75 m, z: 1.5669872981077806 m)
  ├─ Point(x: 2.0 m, y: 2.0 m, z: 2.5 m)
  └─ Point(x: 2.0 m, y: 2.0 m, z: 1.5 m)
  1 elements
  └─ Hexahedron(1, 2, 4, 3, 5, 6, 8, 7)

```

Merging two box meshes or two sphere meshes works as I expected. What am I missing this time? 😄 Thanks for your time!

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [October 9, 2024, 6:17pm UTC](https://discourse.julialang.org/t/can-i-put-non-primitive-geometries-into-a-geometryset/121102/5 "2024-10-09T18:17:34Z")

</div>

Hi @Jfschue , that was a tricky one. Notice that the first mesh is made of 3D geometries and the second is made of 2D geometries. When you merge the two, the `SimpleMesh` constructor will take all these connectivities into account, but will only interpret the geometries with highest dimension as the _elements_.

You can see that all connectivities are stored in the underlying topology:

```julia
topology(oneeach)

SimpleTopology{Connectivity}(Connectivity[Hexahedron(1, 2, 4, 3, 5, 6, 8, 7), Quadrangle(9, 10, 15, 14), Quadrangle(10, 11, 16, 15), Quadrangle(11, 12, 17, 16), Quadrangle(12, 13, 18, 17), Quadrangle(14, 15, 20, 19), Quadrangle(15, 16, 21, 20), Quadrangle(16, 17, 22, 21), Quadrangle(17, 18, 23, 22), Quadrangle(19, 20, 25, 24) … Quadrangle(26, 27, 12, 11), Quadrangle(27, 28, 13, 12), Triangle(29, 9, 14), Triangle(29, 14, 19), Triangle(29, 19, 24), Triangle(29, 24, 9), Triangle(30, 18, 13), Triangle(30, 23, 18), Triangle(30, 28, 23), Triangle(30, 13, 28)], [3, 2, 2, 2, 2, 2, 2, 2, 2, 2 … 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [1])

```

It is saying that you have 1 `Hexahedron` (the single element) and a couple of `Quadrangle` and `Triangle` of lower parametric dimension.

The GeoIO.jl module currently loads/saves element and vertex data. It ignores geometries with intermediate dimension.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [October 9, 2024, 7:57pm UTC](https://discourse.julialang.org/t/can-i-put-non-primitive-geometries-into-a-geometryset/121102/6 "2024-10-09T19:57:09Z")

</div>

> [@Jfschue](#):
>
> If I put a SimpleMesh geometry into a GeometrySet, I get a StackOverflowError

> [@Jfschue](#):
>
> I’m new to [Meshes.jl](https://juliahub.com/ui/Packages/General/Meshes), so very possibly doing something stupid.

Unbounded recursion is a bug, independently of what specifically caused it. Ideally the constructor would be coded in such a manner to make infinite recursion impossible (by throwing explicitly or, better, relying on dispatch to throw a `MethodError`). So, in principle, this is a package bug, to be pedantic.

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [October 9, 2024, 7:59pm UTC](https://discourse.julialang.org/t/can-i-put-non-primitive-geometries-into-a-geometryset/121102/7 "2024-10-09T19:59:58Z")

</div>

And we can find many other bugs that way when a constructor is called with unexpected arguments. PRs are welcome to try to improve the error message and avoid the stack overflow. Not in our priority list to fix bugs caused by incorrect usage.

---

<div class="post-metadata">

**Author:** ![Jfschue](https://avatars.discourse-cdn.com/v4/letter/j/5f9b8f/32.png) [@Jfschue](https://discourse.julialang.org/u/Jfschue)\
**Post date:** [October 10, 2024, 12:42am UTC](https://discourse.julialang.org/t/can-i-put-non-primitive-geometries-into-a-geometryset/121102/8 "2024-10-10T00:42:31Z")

</div>

Thanks for the explanation. Good to know what’s going on. This detail is not a limitation for my actual use case, but I’m glad it came up here. I learned something new.

---

<div class="post-metadata">

**Author:** ![Jfschue](https://avatars.discourse-cdn.com/v4/letter/j/5f9b8f/32.png) [@Jfschue](https://discourse.julialang.org/u/Jfschue)\
**Post date:** [October 10, 2024, 12:46am UTC](https://discourse.julialang.org/t/can-i-put-non-primitive-geometries-into-a-geometryset/121102/9 "2024-10-10T00:46:25Z")

</div>

You make an excellent point @nsajko. There are always opportunities to inform [new] users when things go unexpectedly. I read the following somewhere…

> Geometric processing doesn’t need to be complicated. It should be fun and read like math. If it feels “computer sciency”, that is a limitation of the software and programming language.

Thanks for the contribution!
