jbuckmccready / cavalier_contours

2D polyline/shape library for offsetting, combining, etc.
Apache License 2.0
151 stars 13 forks source link

Incorrect combining result (using C) #23

Closed tredecimguttatus closed 2 years ago

tredecimguttatus commented 2 years ago

Hello! Ive created this test vector:

"Vector, nodes 4, closed=1"
"    Node 0 : X=155.575   Y=113.665   B=0"
"    Node 1 : X=161.29   Y=113.665   B=1"
"    Node 2 : X=161.29   Y=114.935   B=0"
"    Node 3 : X=155.575   Y=114.935   B=1"
"Vector, nodes 4, closed=1"
"    Node 0 : X=161.29   Y=113.665   B=0"
"    Node 1 : X=167.64   Y=113.665   B=1"
"    Node 2 : X=167.64   Y=114.935   B=0"
"    Node 3 : X=161.29   Y=114.935   B=1"

Basically it is 2 horisontal lines: second one starts at same point, where first ends (X=161.290 Y=114.300)

I use this C function:

cavc_pline_boolean(scene[countur_in_scene_num], countur2, cavc_booleanOp_And, combine_options, &pos_list, &neg_list);

Could you please take a look on it?

tredecimguttatus commented 2 years ago

Some additional info: Im using AND operation to check if 2 counturs overlaping and can be merged. If pos_list not empty - it means that counturs can be merged. it is not good way, but i did not find how could i do it on C better. Problem exist if result - closed vector with 2 nodes. изображение изображение Magenta line - i the result. Central shape not combined, because AND operation gives zero vector and program assumes that there is no intersections here.

Final goal - i have a list of positive (painted) and negative (islands) counturs (without intersections) and need to add new "painted" countur. Raw algorithm i see like this:

  1. create list of all already existing positive counturs that connected to new countur.
  2. combine all of them into one positive countur using OR operation, and collect all negative counturs.
  3. use NOT operation with all existing negative counturs, collect results.
jbuckmccready commented 2 years ago

Alright this issue should be fixed with commit: https://github.com/jbuckmccready/cavalier_contours/commit/9fb706efadc757e8274b672660422f8955d89c31

The issue was caused by numerical instability due to the implementation of line_circle_intr. I changed the implementation to something more stable and added test cases to cover the case you reported.

Please pull the latest to test and confirm it fixes the issue.

tredecimguttatus commented 2 years ago

Hello! Exactly this case resolved: изображение

But i extended my C test, and see some troubles, related to this topic. I need some time to extract values for you, but today it should be ready.

tredecimguttatus commented 2 years ago

If i did everything correctly, "And" operation shall give same result as test before:

        overlapping_pill_shaped_ends_new {
            (
                pline_closed![(152.8756878376510, 123.9826833364100, 0.0000000000000), (160.7920178376510, 113.9073533364100, 1.0000000000000), (161.7906421623490, 114.6919866635900, 0.0000000000000), (153.8743121623490, 124.7673166635900, 1.0000000000000)],
                pline_closed![(160.7920178773358, 113.9073532859021, 0.0000000000000), (166.8456878773358, 106.2026832859021, 1.0000000000000), (167.8443121226642, 106.9873167140979, 0.0000000000000), (161.7906421226642, 114.6919867140979, 1.0000000000000)]
            )
            =>
            [
                (BooleanOp::And, &[PlineProperties::new(2, 1.2667686977437822, 3.989822670059025, 120.655, 113.665, 161.92499999999998, 114.935)], &[]),
            ]
        }

May be i have problem with precision here (circle may be moved little bit, precision about 0.001), but my C test say:

const cavc_vertex pline_a[4] = {
    /*0*/ {152.8746878376510, 123.9836833364100, 0.0000000000000},
    /*1*/ {160.7910178376510, 113.9083533364100, 1.0000000000000},
    /*2*/ {161.7896421623490, 114.6929866635900, 0.0000000000000},
    /*3*/ {153.8733121623490, 124.7683166635900, 1.0000000000000},
};
const cavc_vertex pline_b[4] = {
    /*0*/ {160.7910178773358, 113.9083532859021, 0.0000000000000},
    /*1*/ {166.8446878773358, 106.2036832859021, 1.0000000000000},
    /*2*/ {167.8433121226642, 106.9883167140979, 0.0000000000000},
    /*3*/ {161.7896421226642, 114.6929867140979, 1.0000000000000},
}
Operation result:
    pos list size: 1
    neg list size: 0
const cavc_vertex positive[4] = {
    /*0*/ {160.7910178773358, 113.9083532859021, 1.0000000000000},
    /*1*/ {161.7896421623490, 114.6929866635900, 0.0000000000000},
    /*2*/ {153.8733121623490, 124.7683166635900, 1.0000000000000},
    /*3*/ {152.8746878376510, 123.9836833364100, 0.0000000000000},
}

Or graphically: изображение Resulting vector same as one of inputs (blue+red), just starting point changed.

OR operation also gives incorrect result, i guess by the same root cause.

jbuckmccready commented 2 years ago

I'll look into it more today. A few things come to mind:

  1. I wonder if I need to explicitly check the line segment end points distance from arc center to determine if end points intersect. The segment end points are somewhat unique/important to the algorithm and it seems finding tangent intersects between lines and circles is hard to make reliable with fuzzy floating point epsilon handling. I will try to research it some more.
  2. Probably can add tests with the overlapping arc ends at several different angles (e.g., like the new case that fails) to capture a broader range of the same problem.
  3. Also probably need to add tests where the pill shapes move closer and further away by very small increments.
jbuckmccready commented 2 years ago

These are great bug cases, helping me correct the fuzzy float epsilon propagation and improve numeric stability!

This latest case hit code paths where epsilon values for fuzzy comparing were not being used correctly (inconsistent between functions), I have it fixed and will commit the changes today.

jbuckmccready commented 2 years ago

Alright new commit with more improvements/fixes around epsilon values used for fuzzy comparing: https://github.com/jbuckmccready/cavalier_contours/commit/3bf2b379158c4139b5a91144568b33a3cd91e7a3

It fixes the second case you found and I added the second case as a test as well. It should also improve/reduce numeric error/inconsistencies propagated by fuzzy comparing in general.

Please pull the latest to test and confirm it fixes the issue.

tredecimguttatus commented 2 years ago

Hello! I plan to check it carefully, but unfortunately today i will be able to implement just several smoke tests. And i will be afk from tomorrow until tuesday.

UPD. For now i just can say that my big test vector, that i used for testing fully passed! Below you can see small part of it. It is beautiful! изображение

tredecimguttatus commented 2 years ago

Checked another test vector, got this:

const cavc_vertex source_a[4] = {
    /*0*/ {113.1450199999994, 99.0409009830200, 0.0000000000000},
    /*1*/ {113.1449999999994, 114.3000009830200, 1.0000000000000},
    /*2*/ {111.6450000000006, 114.2999990169800, 0.0000000000000},
    /*3*/ {111.6450200000006, 99.0408990169800, 1.0000000000000},
};
const cavc_vertex source_b[4] = {
    /*0*/ {113.1450000000000, 114.3000000000000, 0.0000000000000},
    /*1*/ {113.1450000000000, 117.4750000000000, 1.0000000000000},
    /*2*/ {111.6450000000000, 117.4750000000000, 0.0000000000000},
    /*3*/ {111.6450000000000, 114.3000000000000, 1.0000000000000},
};

Looks like OR operation returns one of them. About result of AND - not sure.

изображение

I really have no more time today, sorry for few details (

jbuckmccready commented 2 years ago

Fixed that case now as well, commit: https://github.com/jbuckmccready/cavalier_contours/commit/fa30fdd15f93417a0d31a004045638939188bf86

Issue was again in the line_circle_intr function, this time caused by squared values being fuzzy compared which are not to scale with the epsilon value, e.g., length * length < eps when it should be length < eps.

Your testing and cases reported has been really helpful, thanks! Pull the latest to test and let me know how it goes.

tredecimguttatus commented 2 years ago

Thank you to! Really, great library. I will continue on tuesday, or little later. Next steps will be:

PS: checked update - i can confirm that case abowe was fixed.

tredecimguttatus commented 2 years ago

Hello! Sorry for long delay - i found issue of incorrect usage of epsilon, created big description, and after that i found this in my source code: cavc_pline_remove_redundant((cavc_pline *)combined, 0.2); LOL But during all this stuff i fully ruined my implementation. So i had to complete update of my sw to continue. Unfortunately after all my updates combining result looks not so good as previously, it is confusing - there is a chance that i introduced some errors.

So, i have several new cases. And they related to epsilon too.

First one

related to epsilon values, so i am not 100% sure about finding validity.

const cavc_vertex source_a[4] = {
    /*0*/ {/*X*/152.2788842579442, /*Y*/58.5145144677570, 0.0000000000000},
    /*1*/ {/*X*/151.6438842579442, /*Y*/53.4345144677570, 1.0000000000000},
    /*2*/ {/*X*/153.1561157420558, /*Y*/53.2454855322430, 0.0000000000000},
    /*3*/ {/*X*/153.7911157420558, /*Y*/58.3254855322430, 1.0000000000000},
};
const cavc_vertex source_b[4] = {
    /*0*/ {/*X*/153.1620000000000, /*Y*/52.7050000000000, 0.0000000000000},
    /*1*/ {/*X*/153.1620000000000, /*Y*/53.3400000000000, 1.0000000000000},
    /*2*/ {/*X*/151.6380000000000, /*Y*/53.3400000000000, 0.0000000000000},
    /*3*/ {/*X*/151.6380000000000, /*Y*/52.7050000000000, 1.0000000000000},
};

Operation OR with this options:

            cavc_pline_boolean_o combine_options;
            cavc_pline_boolean_o_init(&combine_options);
            combine_options.pos_equal_eps = 0.05;
            combine_options.slice_join_eps = 0.05;

Gives incorrect result (i think so);

Second one:

const cavc_vertex source_a[4] = {
    /*0*/ {/*X*/10.2548112191951, /*Y*/4.4473618027979, 0.0000000000000},
    /*1*/ {/*X*/5.8085712191951, /*Y*/8.0043518027979, 1.0000000000000},
    /*2*/ {/*X*/5.0152087808049, /*Y*/7.0126481972021, 0.0000000000000},
    /*3*/ {/*X*/9.4614487808049, /*Y*/3.4556581972021, 1.0000000000000},
};
const cavc_vertex source_b[4] = {
    /*0*/ {/*X*/5.8089199887361, /*Y*/8.0040725860499, -0.2276528214202},
    /*1*/ {/*X*/5.0950100000000, /*Y*/9.4907900625929, 1.0000000000000},
    /*2*/ {/*X*/3.8250100000000, /*Y*/9.4907899374071, 0.2276528214202},
    /*3*/ {/*X*/5.0148600112639, /*Y*/7.0129274139501, 1.0000000000000},
};

Operation OR in my code gives this:

const cavc_vertex result_0[5] = {
    /*0*/ {/*X*/5.0152087808049, /*Y*/7.0126481972021, 0.0000000000000},
    /*1*/ {/*X*/9.4614487808049, /*Y*/3.4556581972021, 1.0000000000000},
    /*2*/ {/*X*/10.2548112191951, /*Y*/4.4473618027979, 0.0000000000000},
    /*3*/ {/*X*/5.8085712191951, /*Y*/8.0043518027979, 0.9996482755531},
    /*4*/ {/*X*/5.0148600112639, /*Y*/7.0129274139501, 0.0001758931564},
};

Or graphically: изображение (red - source, green - result)

This happens with default epsilon. If i change combine_options.pos_equal_eps = 0.0005; this part is passed. Increasing this value gives more mistakes. Too small value gives more mistakes too.

But with value 0.0005 failed this combination (value 0.005 gives good result):

const cavc_vertex source_a[4] = {
    /*0*/ {/*X*/34.5520701659868, /*Y*/13.5800000000000, -0.3443278085713},
    /*1*/ {/*X*/39.2580061973296, /*Y*/9.9033180119262, 1.0000000000000},
    /*2*/ {/*X*/42.1688938026704, /*Y*/10.6290819880738, 0.3443278085713},
    /*3*/ {/*X*/34.5520698340132, /*Y*/16.5800000000000, 1.0000000000000},
};
const cavc_vertex source_b[4] = {
    /*0*/ {/*X*/43.5052137502180, /*Y*/5.2838034375545, 0.0000000000000},
    /*1*/ {/*X*/42.1686637502180, /*Y*/10.6300034375545, 1.0000000000000},
    /*2*/ {/*X*/39.2582362497820, /*Y*/9.9023965624455, 0.0000000000000},
    /*3*/ {/*X*/40.5947862497820, /*Y*/4.5561965624455, 1.0000000000000},
};

изображение

Also i have this:

const cavc_vertex source_a[4] = {
    /*0*/ {/*X*/24.2719330436524, /*Y*/4.8163319805663, 0.0000000000000},
    /*1*/ {/*X*/16.1052530436524, /*Y*/14.7344219805663, 1.0000000000000},
    /*2*/ {/*X*/15.3209269563476, /*Y*/14.0885980194337, 0.0000000000000},
    /*3*/ {/*X*/23.4876069563476, /*Y*/4.1705080194337, 1.0000000000000},
};
const cavc_vertex source_b[4] = {
    /*0*/ {/*X*/11.7209392690379, /*Y*/15.8420000000005, -0.2299490931599},
    /*1*/ {/*X*/15.3138743717012, /*Y*/14.0973589501497, 1.0000000000000},
    /*2*/ {/*X*/16.1123056282988, /*Y*/14.7256610498503, 0.2299490931599},
    /*3*/ {/*X*/11.7209407309621, /*Y*/16.8579999999995, 1.0000000000000},
};

изображение

I have more results, but they look contradictory for me - depend on epsilon. Some vectors pass with high value, some - with low value, Some pass if vector moved.

Could you please teake a look on overall situation, and give me advice what kind if related information is mostly usable for you, and how should i deal with combine options to provide good data for you.

PS. if library has function to check if two vectors intersecting, could you add it to ffi? - it will improve my code. PPS. I can provide vectors in more convinient way for you, if you'll show me how it should look.

jbuckmccready commented 2 years ago

I found using 1e-5 for position equal epsilon and 1e-4 for slice join epsilon to yield good results when using doubles (this is the default used in the library). Small enough to not clobber inputs but large enough to avoid inconsistencies across math operations. These are the epsilon values I am using to reproduce and fix the issues you are reporting.

I will look into the cases you posted today.

Adding polyline intersect functions to c ffi shouldn't be too hard, just takes some time/attention... Can you give it a shot and make a pull request? These are the functions that would be wrapped: self interects and intersects between two polylines. So basically just need to define the c structures to return the result and make a c ffi wrapper function, you can see examples of this in the current c ffi code: https://github.com/jbuckmccready/cavalier_contours/blob/master/cavalier_contours_ffi/src/lib.rs

Most convenient form to post example cases is in the json form that matches the interactive web demo here: https://jbuckmccready.github.io/cavalier_contours_web_demo_page/ So the input looks like the following json:

{
  "isClosed": true, 
  "vertexes": [
    [100, 100, -0.5], 
    [80, 90, 0.374794619217547], 
    [210, 0, 0], 
    [230, 0, 1], 
    [320, 0, -0.5], 
    [280, 0, 0.5], 
    [390, 210, 0], 
    [280, 120, 0.5]
  ]
}
tredecimguttatus commented 2 years ago

Hello! So, i propose stop playing with epsilon values and simply use default. We can return to epsilons later. I removed all epsilon modifications from my code and extracted several cases. May be it will be easier to start from them:

1.

{
  "isClosed": true,
  "vertexes": [
    [9.205577051997063, 7.029369955609887, 0.000000000000000],
    [18.231617051997059, 2.014909955609888, 1.000000000000000],
    [18.848382948002939, 3.125090044390112, 0.000000000000000],
    [9.822342948002939, 8.139550044390113, 1.000000000000000]
  ]
}
{
  "isClosed": true,
  "vertexes": [
    [9.822782733308527, 8.139305491458524, -0.207545228447529],
    [7.056947779266055, 11.750330431457192, 1.000000000000000],
    [5.824672220733945, 11.443089568542808, 0.207545228447529],
    [9.205137266691475, 7.029614508541476, 1.000000000000000]
  ]
}

изображение

2.

{
  "isClosed": true,
  "vertexes": [
    [6.012782733308527, 6.869305491458524, -0.207545228447529],
    [3.246947779266055, 10.480330431457192, 1.000000000000000],
    [2.014672220733944, 10.173089568542808, 0.207545228447529],
    [5.395137266691473, 5.759614508541476, 1.000000000000000]
  ]
}
{
  "isClosed": true,
  "vertexes": [
    [1.413958758496091, 12.575992893779793, 0.000000000000000],
    [2.014768758496091, 10.172702893779793, 1.000000000000000],
    [3.246851241503909, 10.480717106220208, 0.000000000000000],
    [2.646041241503909, 12.884007106220208, 1.000000000000000]
  ]
}

изображение

3.

{
  "isClosed": true,
  "vertexes": [
    [13.015577051997061, 9.569369955609886, 0.000000000000000],
    [22.041617051997061, 4.554909955609888, 1.000000000000000],
    [22.658382948002942, 5.665090044390113, 0.000000000000000],
    [13.632342948002938, 10.679550044390112, 1.000000000000000]
  ]
}
{
  "isClosed": true,
  "vertexes": [
    [13.632782733308526, 10.679305491458523, -0.207545228447530],
    [10.866947779266056, 14.290330431457191, 1.000000000000000],
    [9.634672220733943, 13.983089568542811, 0.207545228447530],
    [13.015137266691474, 9.569614508541475, 1.000000000000000]
  ]
}

изображение

4.

{
  "isClosed": true,
  "vertexes": [
    [9.033958758496091, 16.385992893779790, 0.000000000000000],
    [9.634768758496090, 13.982702893779793, 1.000000000000000],
    [10.866851241503909, 14.290717106220209, 0.000000000000000],
    [10.266041241503910, 16.694007106220209, 1.000000000000000]
  ]
}
{
  "isClosed": true,
  "vertexes": [
    [13.632782733308526, 10.679305491458523, -0.207545228447530],
    [10.866947779266056, 14.290330431457191, 1.000000000000000],
    [9.634672220733943, 13.983089568542811, 0.207545228447530],
    [13.015137266691474, 9.569614508541475, 1.000000000000000]
  ]
}

изображение

5.

{
  "isClosed": true,
  "vertexes": [
    [25.604811219195092, 15.257361802797867, 0.000000000000000],
    [21.158571219195093, 18.814351802797869, 1.000000000000000],
    [20.365208780804910, 17.822648197202131, 0.000000000000000],
    [24.811448780804909, 14.265658197202132, 1.000000000000000]
  ]
}
{
  "isClosed": true,
  "vertexes": [
    [21.158919988736113, 18.814072586049921, -0.227652821420176],
    [20.445009999999996, 20.300790062592878, 1.000000000000000],
    [19.175010000000000, 20.300789937407121, 0.227652821420176],
    [20.364860011263890, 17.822927413950080, 1.000000000000000]
  ]
}

изображение

6.

{
  "isClosed": true,
  "vertexes": [
    [31.425213750217996, 14.363803437554500, 0.000000000000000],
    [30.088663750217997, 19.710003437554498, 1.000000000000000],
    [27.178236249782003, 18.982396562445501, 0.000000000000000],
    [28.514786249782002, 13.636196562445500, 1.000000000000000]
  ]
}
{
  "isClosed": true,
  "vertexes": [
    [22.472070165986750, 22.660000000000011, -0.344327808571312],
    [27.178006197329630, 18.983318011926176, 1.000000000000000],
    [30.088893802670370, 19.709081988073823, 0.344327808571312],
    [22.472069834013247, 25.659999999999989, 1.000000000000000]
  ]
}

изображение

Case 3 and 4 use same vector b. All this cases has common part - not ortogonal line + tangent arc, so i have a feeling all this cases has same root cause. Regarding pull request - please give me some time - im not so good in all this stuff.

jbuckmccready commented 2 years ago

Thanks, I'm working on it now. I fixed the issue in the first cases you posted (have not committed it yet, still testing), I think it is the same issue as the rest (as you mentioned). I'm working through all the new cases you just posted and adding them as test cases. It's helpful having them posted in the json format.

jbuckmccready commented 2 years ago

Well I've been trying to trap things, but it's been difficult. I have things sort of "fixed" but the tests still failing because of differing number of vertexes in the result when one of the polylines directions is inverted (which the tests automatically check). Visually the results essentially look the same but there is +/- 1 vertex that is very close (but not touching according to epsilon values) another vertex, or an additional very small loop/area polyline.

The problem arises dues to differing results between arc-arc intersect finding and line-arc intersect finding (and the sub questions for the type of intersect, e.g. overlapping or tangent).

I'm still thinking about how to improve/change the algorithmic approach to avoid the issues.

tredecimguttatus commented 2 years ago

I know several guys, who really good in math algorithms. If you describe this part of algorithm and whats going wrong, we can think about it tohether.

jbuckmccready commented 2 years ago

Alright, fixed with commit: https://github.com/jbuckmccready/cavalier_contours/commit/7faddb185ab09c44723beb754bc7e37180404d3e

I added automated tests for all cases reported so far. Keep testing and let me know how it goes.

tredecimguttatus commented 2 years ago

For all available cases it works good! No issues for now.

The only one thing i can add, that in OR operation tests some nodes duplicated: изображение

But cavc_pline_remove_redundant((cavc_pline *)combined, 0.001); function fix it without problems: изображение

I will continue testing with more cases.

jbuckmccready commented 2 years ago

Share the cases with vertexes very close together in the end result and I can look into it. It may be something simple to fix.

tredecimguttatus commented 2 years ago

It happens in all vectors from 30 Aug post. For example this:

{
  "isClosed": true,
  "vertexes": [
    [6.012782733308527, 6.869305491458524, -0.207545228447529],
    [3.246947779266055, 10.480330431457192, 1.000000000000000],
    [2.014672220733944, 10.173089568542808, 0.207545228447529],
    [5.395137266691473, 5.759614508541476, 1.000000000000000]
  ]
}
{
  "isClosed": true,
  "vertexes": [
    [1.413958758496091, 12.575992893779793, 0.000000000000000],
    [2.014768758496091, 10.172702893779793, 1.000000000000000],
    [3.246851241503909, 10.480717106220208, 0.000000000000000],
    [2.646041241503909, 12.884007106220208, 1.000000000000000]
  ]
}

OR combination gives this result:

{
  "isClosed": true,
  "vertexes": [
    [2.014768758496091, 10.172702893779793, 0.207530349794348],
    [5.395137266691473, 5.759614508541476, 1.000000000000000],
    [6.012782733308527, 6.869305491458524, -0.207545228447529],
    [3.246947779266055, 10.480330431457192, 0.000156906888925],
    [3.246851241503909, 10.480717106220208, 0.000000000000000],
    [2.646041241503909, 12.884007106220208, 1.000000000000000],
    [1.413958758496091, 12.575992893779793, 0.000000000000000]
  ]
}

Point 3.246947779266055, 10.480330431457192 looks dulicated. изображение

But distance between [3.246947779266055, 10.480330431457192, 0.000156906888925], [3.246851241503909, 10.480717106220208, 0.000000000000000], looks >epsilon, so i dont think that it is an issue, it is just look like an issue. So i propose to take a short look on it, and leave it as is. I have additional cases for you, but collecting data in progress, it will be ready in several hours.

tredecimguttatus commented 2 years ago

Hi I have something like intermediate result. Investigation is ongoing. Rust code report error in some combination of data. But same input vectors in web demo give good result. I claimed on my code (it was really dirty) and re-implemented it from scratch and fully checked it using drMemory (and thats why i was silent for all this time)

So, on this input data we have panic:

{
  "isClosed": true,
  "Area": 14.2499,
  "vertexes": [
    [11.664990000000303, 18.442909378846142, 0.000000000000000],
    [11.665000000000305, 8.219999378846142, 1.000000000000000],
    [12.934999999999697, 8.220000621153860, 0.000000000000000],
    [12.934989999999695, 18.442910621153860, 1.000000000000000]
  ]
}
{
  "isClosed": true,
  "Area": 4.72737,
  "vertexes": [
    [13.062000000000001, 8.220000000000001, 0.000000000000000],
    [13.062000000000001, 10.125000000000000, 1.000000000000000],
    [11.538000000000000, 10.125000000000000, 0.000000000000000],
    [11.538000000000000, 8.220000000000001, 1.000000000000000]
  ]
}

Operation AND (used to check for intersections) give this output:

thread '<unnamed>' panicked at 'point does not lie on the line defined by p0 to p1', C:\cavalier_contours-master\cavalier_contours\src\core\math\base_math.rs:278:9
stack backtrace:
   0: std::panicking::begin_panic<str>
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3\library\std\src\panicking.rs:616
   1: cavalier_contours::core::math::base_math::parametric_from_point<f64>
             at C:\cavalier_contours-master\cavalier_contours\src\core\math\base_math.rs:278
   2: cavalier_contours::core::math::line_circle_intersect::line_circle_intr<f64>
             at C:\cavalier_contours-master\cavalier_contours\src\core\math\line_circle_intersect.rs:156
   3: cavalier_contours::polyline::pline_seg_intersect::pline_seg_intr::closure$0<f64>
             at C:\cavalier_contours-master\cavalier_contours\src\polyline\pline_seg_intersect.rs:147
   4: cavalier_contours::polyline::pline_seg_intersect::pline_seg_intr<f64>
             at C:\cavalier_contours-master\cavalier_contours\src\polyline\pline_seg_intersect.rs:236
   5: cavalier_contours::polyline::internal::pline_intersects::find_intersects::closure$0<cavalier_contours::polyline::pline::Polyline<f64>,cavalier_contours::polyline::pline::Polyline<f64>,f64>
             at C:\cavalier_contours-master\cavalier_contours\src\polyline\internal\pline_intersects.rs:355
   6: static_aabb2d_index::core::impl$15::visit<f64,tuple$<>,cavalier_contours::polyline::internal::pline_intersects::find_intersects::closure_env$0<cavalier_contours::polyline::pline::Polyline<f64>,cavalier_contours::polyline::pline::Polyline<f64>,f64> >
             at C:\Users\KarakurT\.cargo\registry\src\github.com-1ecc6299db9ec823\static_aabb2d_index-0.6.0\src\core.rs:215
   7: static_aabb2d_index::static_aabb2d_index::StaticAABB2DIndex<f64>::visit_query_with_stack<f64,cavalier_contours::polyline::internal::pline_intersects::find_intersects::closure_env$0<cavalier_contours::polyline::pline::Polyline<f64>,cavalier_contours::polyl
             at C:\Users\KarakurT\.cargo\registry\src\github.com-1ecc6299db9ec823\static_aabb2d_index-0.6.0\src\static_aabb2d_index.rs:1016
   8: cavalier_contours::polyline::internal::pline_intersects::find_intersects<cavalier_contours::polyline::pline::Polyline<f64>,cavalier_contours::polyline::pline::Polyline<f64>,f64>
             at C:\cavalier_contours-master\cavalier_contours\src\polyline\internal\pline_intersects.rs:399
   9: cavalier_contours::polyline::internal::pline_boolean::process_for_boolean<cavalier_contours::polyline::pline::Polyline<f64>,cavalier_contours::polyline::pline::Polyline<f64>,f64>
             at C:\cavalier_contours-master\cavalier_contours\src\polyline\internal\pline_boolean.rs:55
  10: cavalier_contours::polyline::internal::pline_boolean::polyline_boolean<cavalier_contours::polyline::pline::Polyline<f64>,cavalier_contours::polyline::pline::Polyline<f64>,cavalier_contours::polyline::pline::Polyline<f64>,f64>
             at C:\cavalier_contours-master\cavalier_contours\src\polyline\internal\pline_boolean.rs:744
  11: cavalier_contours::polyline::traits::PlineSource::boolean_opt<cavalier_contours::polyline::pline::Polyline<f64>,cavalier_contours::polyline::pline::Polyline<f64> >
             at C:\cavalier_contours-master\cavalier_contours\src\polyline\traits.rs:1459
  12: cavalier_contours_ffi::cavc_pline_boolean::closure$0
             at C:\cavalier_contours-master\cavalier_contours_ffi\src\lib.rs:965
  13: std::panicking::try::do_call<cavalier_contours_ffi::cavc_pline_boolean::closure_env$0,i32>
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3\library\std\src\panicking.rs:492
  14: std::panicking::begin_panic::impl$1::take_box<str>
  15: std::panicking::try<i32,cavalier_contours_ffi::cavc_pline_boolean::closure_env$0>
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3\library\std\src\panicking.rs:456
  16: std::panic::catch_unwind<cavalier_contours_ffi::cavc_pline_boolean::closure_env$0,i32>
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3\library\std\src\panic.rs:137
  17: cavalier_contours_ffi::cavc_pline_boolean
             at C:\cavalier_contours-master\cavalier_contours_ffi\src\lib.rs:949
  18: addCounturToLayerVector
             at D:\repository\andreyrodi_elwand\DESCTOP_APPS\LIBRARIES\Utils_test\Utils\utils.cpp:167
  19: main
             at D:\repository\andreyrodi_elwand\DESCTOP_APPS\LIBRARIES\Utils_test\main.cpp:61
  20: invoke_main
             at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
  21: __scrt_common_main_seh
             at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
  22: __scrt_common_main
             at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:330
  23: mainCRTStartup
             at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp:16
  24: BaseThreadInitThunk
  25: RtlUserThreadStart
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

I also tried to update math.rs:278 - removed assert and compared value with zero to get more information. But this update fixed issue somehow.

I will continue investigation, moreover input vector is not real input - it was calculated using some functions from library and i could corrupt something on this step. Im stiil thinking that problem in my code, but i would be gratefull for any ideas.

Best regards, Andrei

jbuckmccready commented 2 years ago

I will take a look at it in next few days. There are some debug asserts which are maybe triggering due to fuzzy comparison stuff.

jbuckmccready commented 2 years ago

Fixed with commit: https://github.com/jbuckmccready/cavalier_contours/commit/7cce6cd13ba48d825ad9184a6efdaa427c3bc3d3

I improved the way the debug assert is done and also improved the calculation to use the larger denominator to avoid error in case of very small component difference.

tredecimguttatus commented 2 years ago

Hello! Checked - issue was resolved.

jbuckmccready commented 2 years ago

Closing this issue, open new issues if you find more problems.