Menu

#160 Z not set to 0 when new intersection point calculated, and missed SetZ() in newer code

*
closed
nobody
None
1
2019-06-11
2016-12-19
No

There's a place in ProcessEdgesAtTopOfScanbeamf() where a new intersection is sometimes calculated, but it erroneously inherits any previously set Z value on the edge->Curr point.

When this comes out as an intersection, and not an end point, the Z value should be set to 0.

Proposed fix around line 3038 in r498:

else
  {
    e->Curr.X = TopX( *e, topY );
    e->Curr.Y = topY;
#ifdef use_xyz
    e->Curr.Z = topY == e->Top.Y ? e->Top.Z : (topY == e->Bot.Y ? e->Bot.Z : 0);
#endif
  }

Whether you can do a proper SetZ() at this point, with the proper edges, I'm not sure.
But in the case I was looking at, a new SetZ() needed to be added in some fairly new code,
in ProcessHorizontal(), around line 2716:

    if (horzEdge->OutIdx >= 0 && !IsOpen)  //note: may be done multiple times
        {
#ifdef use_xyz
            if (dir == dLeftToRight) SetZ(e->Curr, *horzEdge, *e);
            else SetZ(e->Curr, *e, *horzEdge);
#endif
            op1 = AddOutPt(horzEdge, e->Curr);
            TEdge* eNextHorz = m_SortedEdges;

Although IntersectEdges() will be called several lines later on essentially the same point (in my test case), the SetZ() that happens inside IntersectEdges() won't affect the point just added here with AddOutPt().

The if/else here for the edge param order just mimics what you do several lines later.
Hopefully that's right, but I'm just guessing.

This second fix is dependant upon the first, since SetZ() won't set Z if it's already set to the wrong thing.

But the first fix also corrects other wrong Z values at intersections that don't depend on the second fix.

My test polygons for this are:
p1 = [
[10, 0, 1],
[10, 10, 2],
[ 0, 10, 3],
[ 0, 0, 4],
]

p2 = [
[ 5, 5, 5],
[15, 5, 6],
[15, 15, 7],
[ 5, 15, 8],
]

Execute options are UNION with both squares in subjects and fill type NONZERO.

When zfill callback is not set, I get this:

[10, 5, 0] <-- correct, z==0 at intersection
[15, 5, 7] <-- wrong at a preserved input point, z should be 6
[15, 15, 7]
[5, 15, 8]
[5, 10, 8] <-- wrong at intersection, z should be 0
[0, 10, 3]
[0, 0, 4]
[10, 0, 2] <-- wrong at a preserved input point, z should be 1

The first fix fixes those three problems, when no zfill callback is set.

With that first fix in place we can see the remaining problem without the second fix.
When the zfill callback is essentially: intersectionPoint.Z = 23, the result is

[10, 5, 23] <-- correct again at intersection
[15, 5, 6] <-- correct because of first fix
[15, 15, 7]
[5, 15, 8]
[5, 10, 0] <-- wrong at intersection, should be 23
[0, 10, 3]
[0, 0, 4]
[10, 0, 1] <-- correct because of first fix

The second fix corrects that.

Thanks for you time Angus.

Related

Discussion: SetZ - being lost in the returned list?

Discussion

  • Anonymous

    Anonymous - 2016-12-20

    Seems to address the problem for me. Nicely done, Mike!

     
  • Angus Johnson

    Angus Johnson - 2017-02-26

    Thanks Mike. I'm about to add this fix to version 6.4.2

     
  • Angus Johnson

    Angus Johnson - 2017-02-26
    • status: open --> closed
     
  • David Orejuela Esteban

    It was finally added to version 6.4.2? I'm getting all z values set to 0 with #define use_xyz

     
  • David Orejuela Esteban

    Sorry I didn't realize this is about Clipper class and I was using ClipperOffset, which is not in Clipper's class hierarchy.

    It's using a Clipper object as a local variable in ClipperOffset::Execute, I'd suggest to promote that local variable to a member variable and give public access to it, so a user can set its ZFillFunction as well it can be done with Clipper

     

Anonymous
Anonymous

Add attachments
Cancel





MongoDB Logo MongoDB