Skip to content
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

First wave of function bindings update. #7

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

ThomasCartier
Copy link

Tests are still missing.

  • Not ready right now.
    Confirmation needed:
  1. Style ok ?
  2. I need some confirmation for io handling (obj, vtk).
    Do we follow the same strategy as wkb and al ?
  3. Any further objection before I keep going ?

@mthh
Copy link
Owner

mthh commented Nov 1, 2024

Thank you for undertaking this work!

Concerning the style, I usually run rustfmt (with cargo fmt) on the code before pushing any changes (I should include this in the continuous integration pipeline to check that the style is OK at the same time as the tests).

Anything that's OK for rustfmt is OK for me (and it avoids discussing a style guide).
... Except for one or two small details: I've seen you introduce a lot of new empty lines (for example, here - click on 'load diff' to go to the excpected line - between the documentation and the start of the function code or there between [#test] and the test code ; ditto for the line breaks introduced between each line in the code of certain functions where the code itself doesn't change). Is there a reason for this?
It adds a lot of noise to the diff and doesn't seem necessary (Rust's own source code doesn't include such new empty lines between a function's documentation and the function itself, for example: https://doc.rust-lang.org/src/alloc/vec/mod.rs.html#397).

@ThomasCartier
Copy link
Author

You are right for the formatting, it's because I use a different one from the official to ease the coding.
But I always revert my custom rustfmt.toml before sharing.
Apparently, there were some missed bits! Let me correct that.

I will add some tests today.

Side question: did you create the shapes in the test by hand, or is it an export from Blender or else ?

@mthh
Copy link
Owner

mthh commented Nov 1, 2024

I need some confirmation for io handling (obj, vtk).
Do we follow the same strategy as wkb and al ?

I'm not sure what information you want. So far WKB wasn't supported (but it seems like a good idea to support it). The same goes for VTK and OBJ (although it's not necessarily a priority).

I guess VTK / OBJ writer could be defined the same way than the WKT writer, with something like the (totally untested) following:

pub fn geometry_as_vtk(&self) ->  -> Result<String> {
    let mut ptr = MaybeUninit::<*mut c_char>::uninit();
    let mut length: usize = 0;
    unsafe {
        sfcgal_geometry_as_vtk(self.c_geom.as_ref(), ptr.as_mut_ptr(), &mut length);
        Ok(_c_string_with_size(ptr.assume_init(), length))
    }
}

@ThomasCartier
Copy link
Author

Yep, I will implement that today this way

@mthh
Copy link
Owner

mthh commented Nov 1, 2024

Side question: did you create the shapes in the test by hand, or is it an export from Blender or else ?

If I remember correctly, some of them are coming from SFCGAL test suite and other may have been created by hand (or reuse examples seen on the Web such as in the PostGIS examples and stuff like that).

@ThomasCartier
Copy link
Author

Nice, I will dig into it, it will ease my life :)
I will update the corrected work in a few hours!

BTW, I saw they are about to merge 3D alpha shape. This is a killer feature. I will keep you updated when it's there if you wish. I will pre implement it here and leave it commented. This way, minimal work for you :)

@ThomasCartier
Copy link
Author

Last point to discuss: some algorithms need a specific type to work.

I solved this by using this type of matching.

I think I can expand that on most of the functions, because it avoids a ffi roundtrip in case the preconditions don't hold, with a clearer error message.

That's ok for you ?

@mthh
Copy link
Owner

mthh commented Nov 1, 2024

BTW, I saw they are about to merge 3D alpha shape. This is a killer feature. I will keep you updated when it's there if you wish. I will pre implement it here and leave it commented. This way, minimal work for you :)

OK for me, thanks!

Last point to discuss: some algorithms need a specific type to work.

I solved this by using this type of matching.

I think I can expand that on most of the functions, because it avoids a ffi roundtrip in case the preconditions don't hold, with a clearer error message.

That's ok for you ?

Just had a quick look and I guess it's a good idea for functions that we know will fail on the C API side.
There are already probably some functions (at least one) for which the precondition about the geometry type isn't checked and the C function returns an error :

    let res = some_sfcgeometry_of_type_point.line_substring(12., 20.);
    println!("{:?}", res);

returns Err(Obtained null pointer when creating geometry: line_sub_string(): the first argument must be a lineString) .

While others (such as the orientation or the volume methods) have a precondition like "geom is a Polygon" or "geom is a Volume" (cf. https://sfcgal.gitlab.io/SFCGAL/API/sfcgal__c_8h/#function-sfcgal_geometry_orientation) and still return Ok(some_value) (like Ok(Orientation::undetermined) or Ok(0.0)) which might be OK to keep as it.

@ThomasCartier
Copy link
Author

For the latter case, are you against a cfg feature that would enable the users to choose to bail early ? That way, people have the option to choose how "tight" the api is ? I can implement it if you let me.

@mthh
Copy link
Owner

mthh commented Nov 1, 2024

I deduce that you prefer to fail early (avoiding the FFI round trip)?
Honestly, I'm open to discussion and we can also choose to do this way, to avoid writing extra code with cfg feature flag.

I was just thinking of possible use cases (where a user has - really simple example - a Vec of geometries of mixed types, and accumulates their volumes to calculate the sum, knowing that it returns 0.0 for geometries whose volume can't be calculated would avoid having to deal with Err's that would be returned by the method, allowing you to always unwrap...).
Well, it's a bit contrived.

@mthh
Copy link
Owner

mthh commented Nov 1, 2024

Let's do without cfg feature and choose to match the preconditions indicated in the documentation on the Rust side, without doing the FFI round trip, even for the few functions (like “orientation” or “volume”) that don't return an error on the C API side even when the precondition doesn't hold.

This will probably lead to a clearer API / better user experience.

@ThomasCartier
Copy link
Author

Ok!

Ghost added 4 commits November 1, 2024 14:50
Cleaned the formatting issues.
Added some utils functions.
useless FFI roundtrips.
Each precondition is set in a macros_rule.
@mthh
Copy link
Owner

mthh commented Nov 1, 2024

Sorry I slightly modified the src/geometry.rs file to make clippy happy after slightly improving the CI workflows, so you'll need to merge the latest master version into your PR branch.

@ThomasCartier
Copy link
Author

Hi,
Using the fork, I find some things to change for dev experience:

  1. many functions starting with geometry_XXX could be renamed to XXX directly. For example my_sfgeometry.translate3d(...) instead of my_sfgeometry.geometry_translate3d(...)
  2. I went too far with tesselate. it returns early when it shouldn't. Surely tired, I didn't spot it. Must correct that tomorrow.

What's your opinion on 1) ?

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.

2 participants