jbuckmccready / cavalier_contours

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

Cut not worked #38

Open happydpc opened 6 months ago

happydpc commented 6 months ago

Here is the test code, I want to cut the polygon to make a rounded corner, although it doesn't fail, but the result is not correct.

(
    pline_closed![(233.5, 0.0, 0.0),
(222.0, 233.5, 0.0),
(-233.5, 233.5, 0.0),
(-233.5, 0.0, 0.0)],
    pline_closed![(222.0, 233.5, 0.0),
(232.934, 11.486, 0.4),
(-0.283, 233.5, 0.0)]
)
=>
[
    (BooleanOp::Or, &[PlineProperties::new(4, -107701.875, 1389.7830190582713, -233.5, 0.0, 233.5, 233.5)], &[]),
    (BooleanOp::And, &[PlineProperties::new(2, 0.0, 444.566, -0.283, 233.5, 222.0, 233.5)], &[]),
    (BooleanOp::Not, &[], &[]),
    (BooleanOp::Xor, &[], &[])
]

The point (222.0, 233.5, 0.0) is intend, it's not that rectangle.

004a5b09ef3fcafba04d0f589ee28ac c58ff5a7a321a3499f8ce9431380e32
jbuckmccready commented 6 months ago

Sorry I have been very busy, I will try to take a look at this in the next few days.

happydpc commented 6 months ago

Updated

I adjust the bulge 0.4 to 0.3998, it's ok now. May be there's some precisions problem when I use the real calculated f64 bulge

image

The real bulge value caculated by these code, the bulge I have to truncate the precision to keep the boolean working.

   let angle = d1.angle_between(d2);
    dbg!(angle.to_degrees());         //angle.to_degrees() = 92.8195695557212
    let bulge = f64_trunc_3(bulge_from_angle(PI as f64 - angle));  //if not truncate, comes the precision bug  
    dbg!(bulge);
jbuckmccready commented 4 months ago

OK the issue is bulge = 0.4 in Polyline 2 nearly causes it to be self intersecting (which doesn't work right for the boolean algorithm), e.g., bulge = 0.401 will return self intersections, bulge = 0.399 will cause boolean algorithm to work, bulge = 0.4 will return no self intersections but also boolean algorithm fails. This is likely due to issues of inconsistency between different types of intersection (line-line and line-arc).

I'll have to look into it more to see if it can be resolved.

Running this:

    let mut intrs = Vec::new();
    pline2.visit_self_intersects(&mut |intr| intrs.push(intr));
    let intrs = pline1.find_intersects(pline2);
    println!("{:?}", intrs);

Get the following:

PlineIntersectsCollection { basic_intersects: [PlineBasicIntersect { start_index1: 1, start_index2: 1, point: Vector2 { x: -0.23185000000003697, y: 233.5 } }], overlapping_intersects: [PlineOverlappingIntersect { start_index1: 1, start_index2: 2, point1: Vector2 { x: -0.283, y: 233.5 }, point2: Vector2 { x: 222.0, y: 233.5 } }] }

Shows the code detects overlapping segment between these segments:

[233.5, 0, 0] -> [222, 233.5, 0] from Polyline 1
[-0.283, 233.5, 0] -> [222, 233.5, 0] from Polyline 2

as PlineOverlappingIntersect { start_index1: 1, start_index2: 2, point1: Vector2 { x: -0.283, y: 233.5 }, point2: Vector2 { x: 222.0, y: 233.5 } }

And a single point intersect between these segments:

[222, 233.5, 0] -> [-233.5, 233.5, 0] from Polyline 1
[232.934, 11.486, 0.4] -> [-0.283, 233.5, 0] from Polyline 2

as PlineBasicIntersect { start_index1: 1, start_index2: 1, point: Vector2 { x: -0.23185000000003697, y: 233.5 } }.