Skip to content

Generic interface for both integer and floating-point triangulation #11

Description

@mikwielgus

It would be nice to not have to decide whether to use floats or integers. Currently, it seems to me that this is impossible -- IntTriangulation works only on i32, whereas Triangulator::triangulate() requires the scalar type to implement FloatNumber, which is currently only implemented for f32 and f64.

It should be possible to use traits to make the current floating-point triangulation interface more generic to also accept integers by implementing the current conversion from and to floats as an identity map for integers.

This would be useful for me because I have a preference for writing code that is generic over both integers and floats to cover more applications. Though in computer graphics, video games, and mechanical CADs floating-point coordinates have been the usual choice for over two decades, fixed-point integer coordinates do not suffer from numerical inrobustness and continue to be widely used in EDA software.

Activity

  1. NailxSharipov commented on May 8, 2026

    @NailxSharipov
    Member

    I'd avoid mixing the float and int APIs.

    For most projects, the float API is the better default because it is simpler and easier to use. For large projects, the choice between float and int is important enough to make a concrete choice.

    Even if the APIs look similar, they have different tradeoffs and behavior. Combining them into one generic interface could make that distinction less clear and make the API harder to reason about.

  2. mikwielgus commented on May 8, 2026

    @mikwielgus
    ContributorAuthor

    From the perspective of a developer of a user-facing project, this makes sense. But I'm developing a library (for any-angle pathfinding), and I don't want to impose my choice on the downstream programmer (especially given that I am going to choose integers). While at the same time I also don't want to have duplicate code to be able to handle both ints and floats.

    I can manage this on my end of course. I will create and implement my own traits that demultiplex to the int and float triangulation. They will look more or less like this:

    pub trait NetTriangulate<K> {
      type Output: NetTriangulation<K>;
    
      fn net_triangulate(&self) -> Self::Output;
    }
    
    pub trait NetTriangulation<K> {
      fn triangle(index: TriangleIndex) -> [[K; 2]; 3];
      fn neighbors(index: TriangleIndex) -> [TriangleIndex; 3];
    }

    However, since this is an adapter that is glued only towards i_triangle and nothing else, it may be useful to have this capability upstreamed in some form.

  3. mikwielgus commented on May 8, 2026

    @mikwielgus
    ContributorAuthor

    While we're at it:

    I'm looking now at i_triangle::float::delaunay::Delaunay and see no way to access adjacency data of triangles (i.e. every triangle's list of neighbors). This makes it impossible for me to run a pathfinding algorithm on the triangulation faces over the floating-point Delaunay triangulation here. I can still do this with ints because i_triangle::advanced::delaunay::IntDelaunay's fields are all public.

  4. NailxSharipov commented on May 8, 2026

    @NailxSharipov
    Member

    Internally, my libraries are based on integer math. The float API is mostly a convenience wrapper around that integer pipeline. So if you are building another library on top of iTriangle and want to support both int and float, I would recommend following the same structure: implement the core logic using int logic, then provide a float wrapper that converts into that representation.

  5. mikwielgus commented on May 8, 2026

    @mikwielgus
    ContributorAuthor

    Internally, my libraries are based on integer math. The float API is mostly a convenience wrapper around that integer pipeline. So if you are building another library on top of iTriangle and want to support both int and float, I would recommend following the same structure: implement the core logic using int logic, then provide a float wrapper that converts into that representation.

    Thank you for the explanation of your decision.

    Then instead of this, I would like to ask for a different, smaller addition: simple single-method interfaces to obtain the adjacency data from Delaunay, IntDelaunay, RawIntTriangulation.

    Adjacency data is useful for performing pathfinding (using e.g. Dijkstra, A* algorithms) over triangulation faces. Right now, it seems to me that it's not possible to obtain this data from the floating-point triangulations and also from RawIntTriangulation.

    I have opened a PR for that: #12

  6. NailxSharipov commented on Jun 1, 2026

    @NailxSharipov
    Member

    In version 0.45.0, I added generic support for integer types.

    It does make the internal math a bit more complex, but from the user’s perspective, I think the result is very convenient.

  7. mikwielgus commented on Jun 1, 2026

    @mikwielgus
    ContributorAuthor

    I appreciate this, but I'm personally interested in having a generic interface that works not just on different types of integers, as you implemented now, but also on floats, because I tend to write code that is generic over scalar types.

    But either way, this is not much of an issue. I can always create my own higher-level interfaces when I need them.

    In case you are interested how this looks like on my end, here's code for a wrapper that I created for my own purposes over your other library, i_overlay, to have my library (still WIP) have a scalar-generic interface for boolean operations on polygons.

  8. mikwielgus commented on Jul 24, 2026

    @mikwielgus
    ContributorAuthor

    I have implemented this today because I need this for myself anyway. I have opened a PR for you to have an opportunity to look at this, in case you would like to see how this would work or reconsider it nevertheless.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions