⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ezpolyclip.pas

📁 很管用的GIS控件
💻 PAS
📖 第 1 页 / 共 5 页
字号:
                edge.bundle[BELOW, SUBJ] );
            End;
        End;

        (* Update parity *)
        parity[CLIP] := parity[CLIP] Xor edge.bundle[ABOVE, CLIP];
        parity[SUBJ] := parity[SUBJ] Xor edge.bundle[ABOVE, SUBJ];

        (* Update horizontal state *)
        If boolean( exists[CLIP] ) Then
          horiz[CLIP] := next_hstate[ord( horiz[CLIP] ), ( ( exists[CLIP] - 1 ) Shl 1 ) + parity[CLIP]];
        If boolean( exists[SUBJ] ) Then
          horiz[SUBJ] :=
            next_hstate[ord( horiz[SUBJ] ),
            ( ( exists[SUBJ] - 1 ) Shl 1 ) + parity[SUBJ]];

        vclass := tr + ( tl Shl 1 ) + ( br Shl 2 ) + ( bl Shl 3 );

        If contributing Then
        Begin
          xb := edge.xb;

          Case TVertexType( vclass ) Of
            vtEMN, vtIMN:
              Begin
                add_local_min( out_poly, edge, xb, yb );
                px := xb;
                cf := edge.outp[ABOVE];
              End;
            vtERI:
              Begin
                If xb <> px Then
                Begin
                  add_right( cf, xb, yb );
                  px := xb;
                End;
                edge.outp[ABOVE] := cf;
                cf := Nil;
              End;
            vtELI:
              Begin
                add_left( edge.outp[BELOW], xb, yb );
                px := xb;
                cf := edge.outp[BELOW];
              End;
            vtEMX:
              Begin
                If xb <> px Then
                Begin
                  add_left( cf, xb, yb );
                  px := xb;
                End;
                merge_right( cf, edge.outp[BELOW], out_poly );
                cf := Nil;
              End;
            vtILI:
              Begin
                If xb <> px Then
                Begin
                  add_left( cf, xb, yb );
                  px := xb;
                End;
                edge.outp[ABOVE] := cf;
                cf := Nil;
              End;
            vtIRI:
              Begin
                add_right( edge.outp[BELOW], xb, yb );
                px := xb;
                cf := edge.outp[BELOW];
                edge.outp[BELOW] := Nil;
              End;
            vtIMX:
              Begin
                If xb <> px Then
                Begin
                  add_right( cf, xb, yb );
                  px := xb;
                End;
                merge_left( cf, edge.outp[BELOW], out_poly );
                cf := Nil;
                edge.outp[BELOW] := Nil;
              End;
            vtIMM:
              Begin
                If xb <> px Then
                Begin
                  add_right( cf, xb, yb );
                  px := xb;
                End;
                merge_left( cf, edge.outp[BELOW], out_poly );
                edge.outp[BELOW] := Nil;
                add_local_min( out_poly, edge, xb, yb );
                cf := edge.outp[ABOVE];
              End;
            vtEMM:
              Begin
                If xb <> px Then
                Begin
                  add_left( cf, xb, yb );
                  px := xb;
                End;
                merge_right( cf, edge.outp[BELOW], out_poly );
                edge.outp[BELOW] := Nil;
                add_local_min( out_poly, edge, xb, yb );
                cf := edge.outp[ABOVE];
              End;
            vtLED:
              Begin
                If edge.bot.y = yb Then
                  add_left( edge.outp[BELOW], xb, yb );
                edge.outp[ABOVE] := edge.outp[BELOW];
                px := xb;
              End;
            vtRED:
              Begin
                If edge.bot.y = yb Then
                  add_right( edge.outp[BELOW], xb, yb );
                edge.outp[ABOVE] := edge.outp[BELOW];
                px := xb;
              End;
          End; (* End of switch *)
        End; (* End of contributing conditional *)
      End; (* End of edge exists conditional *)

      edge := edge.next;
    End; (* End of AET loop *)

    (* Delete terminating edges from the AET, otherwise compute xt *)
    edge := aet;
    While edge <> Nil Do
    Begin
      If edge.top.y = yb Then
      Begin
        prev_edge := edge.prev;
        next_edge := edge.next;
        If prev_edge <> Nil Then
          prev_edge.next := next_edge
        Else
          aet := next_edge;
        If next_edge <> Nil Then
          next_edge.prev := prev_edge;

        (* Copy bundle head state to the adjacent tail edge if required *)
        If ( ( edge.bstate[BELOW] = bsBUNDLE_HEAD ) And ( prev_edge <> Nil ) ) And
          ( prev_edge.bstate[BELOW] = bsBUNDLE_TAIL ) Then
        Begin
          prev_edge.outp[BELOW] := edge.outp[BELOW];
          prev_edge.bstate[BELOW] := bsUNBUNDLED;
          If ( prev_edge.prev <> Nil ) And
            ( prev_edge.prev.bstate[BELOW] = bsBUNDLE_TAIL ) Then
            prev_edge.bstate[BELOW] := bsBUNDLE_HEAD;
        End;
      End
      Else
      Begin
        If edge.top.y = yt Then
          edge.xt := edge.top.x
        Else
          edge.xt := edge.bot.x + edge.dx * ( yt - edge.bot.y );
      End;

      edge := edge.next;
    End;

    If scanbeam < sbt_entries Then
    Begin
      (* === SCANBEAM INTERIOR PROCESSING ============================== *)

      build_intersection_table( it, aet, dy );

      (* Process each node in the intersection table *)
      intersect := it;
      While intersect <> Nil Do
      Begin
        e0 := intersect.ie[0];
        e1 := intersect.ie[1];

        (* Only generate output for contributing intersections *)
        If ( boolean( e0.bundle[ABOVE, CLIP] ) Or boolean( e0.bundle[ABOVE, SUBJ] ) ) And
          ( boolean( e1.bundle[ABOVE, CLIP] ) Or boolean( e1.bundle[ABOVE, SUBJ] ) ) Then
        Begin
          p := e0.outp[ABOVE];
          q := e1.outp[ABOVE];
          ix := intersect.point.x;
          iy := intersect.point.y + yb;

          ain[CLIP] := integer( ( boolean( e0.bundle[ABOVE, CLIP] ) And Not
            boolean( e0.bside[CLIP] ) )
            Or ( boolean( e1.bundle[ABOVE, CLIP] ) And boolean( e1.bside[CLIP] ) )
            Or ( Not boolean( e0.bundle[ABOVE, CLIP] ) And Not
            boolean( e1.bundle[ABOVE, CLIP] )
            And boolean( e0.bside[CLIP] ) And boolean( e1.bside[CLIP] ) ) );
          ain[SUBJ] := integer( ( boolean( e0.bundle[ABOVE, SUBJ] ) And Not
            boolean( e0.bside[SUBJ] ) )
            Or ( boolean( e1.bundle[ABOVE, SUBJ] ) And boolean( e1.bside[SUBJ] ) )
            Or ( Not boolean( e0.bundle[ABOVE, SUBJ] ) And Not
            boolean( e1.bundle[ABOVE, SUBJ] )
            And boolean( e0.bside[SUBJ] ) And boolean( e1.bside[SUBJ] ) ) );
          (* Determine quadrant occupancies *)
          bl := 0;
          br := 0;
          tl := 0;
          tr := 0;
          Case op Of
            pcDIFF, pcINT:
              Begin
                tr := ( ain[CLIP] ) And ( ain[SUBJ] );
                tl := ( ain[CLIP] Xor e1.bundle[ABOVE, CLIP] )
                  And ( ain[SUBJ] Xor e1.bundle[ABOVE, SUBJ] );
                br := ( ain[CLIP] Xor e0.bundle[ABOVE, CLIP] )
                  And ( ain[SUBJ] Xor e0.bundle[ABOVE, SUBJ] );
                bl := ( ain[CLIP] Xor e1.bundle[ABOVE, CLIP] Xor e0.bundle[ABOVE,
                  CLIP] )
                  And ( ain[SUBJ] Xor e1.bundle[ABOVE, SUBJ] Xor e0.bundle[ABOVE,
                  SUBJ] );
              End;
            pcXOR:
              Begin
                tr := ( ain[CLIP] ) Xor ( ain[SUBJ] );
                tl := ( ain[CLIP] Xor e1.bundle[ABOVE, CLIP] )
                  Xor ( ain[SUBJ] Xor e1.bundle[ABOVE, SUBJ] );
                br := ( ain[CLIP] Xor e0.bundle[ABOVE, CLIP] )
                  Xor ( ain[SUBJ] Xor e0.bundle[ABOVE, SUBJ] );
                bl := ( ain[CLIP] Xor e1.bundle[ABOVE, CLIP] Xor e0.bundle[ABOVE,
                  CLIP] )
                  Xor ( ain[SUBJ] Xor e1.bundle[ABOVE, SUBJ] Xor e0.bundle[ABOVE,
                  SUBJ] );
              End;
            pcUNION:
              Begin
                tr := ( ain[CLIP] ) Or ( ain[SUBJ] );
                tl := ( ain[CLIP] Xor e1.bundle[ABOVE, CLIP] )
                  Or ( ain[SUBJ] Xor e1.bundle[ABOVE, SUBJ] );
                br := ( ain[CLIP] Xor e0.bundle[ABOVE, CLIP] )
                  Or ( ain[SUBJ] Xor e0.bundle[ABOVE, SUBJ] );
                bl := ( ain[CLIP] Xor e1.bundle[ABOVE, CLIP] Xor e0.bundle[ABOVE,
                  CLIP] )
                  Or ( ain[SUBJ] Xor e1.bundle[ABOVE, SUBJ] Xor e0.bundle[ABOVE,
                  SUBJ] );
              End;
          End;

          vclass := tr + ( tl Shl 1 ) + ( br Shl 2 ) + ( bl Shl 3 );

          Case TVertexType( vclass ) Of
            vtEMN:
              Begin
                add_local_min( out_poly, e0, ix, iy );
                e1.outp[ABOVE] := e0.outp[ABOVE];
              End;
            vtERI:
              If p <> Nil Then
              Begin
                add_right( p, ix, iy );
                e1.outp[ABOVE] := p;
                e0.outp[ABOVE] := Nil;
              End;
            vtELI:
              If q <> Nil Then
              Begin
                add_left( q, ix, iy );
                e0.outp[ABOVE] := q;
                e1.outp[ABOVE] := Nil;
              End;
            vtEMX:
              If ( p <> Nil ) And ( q <> Nil ) Then
              Begin
                add_left( p, ix, iy );
                merge_right( p, q, out_poly );
                e0.outp[ABOVE] := Nil;
                e1.outp[ABOVE] := Nil;
              End;
            vtIMN:
              Begin
                add_local_min( out_poly, e0, ix, iy );
                e1.outp[ABOVE] := e0.outp[ABOVE];
              End;
            vtILI:
              If p <> Nil Then
              Begin
                add_left( p, ix, iy );
                e1.outp[ABOVE] := p;
                e0.outp[ABOVE] := Nil;
              End;
            vtIRI:
              If q <> Nil Then
              Begin
                add_right( q, ix, iy );
                e0.outp[ABOVE] := q;
                e1.outp[ABOVE] := Nil;
              End;
            vtIMX:
              If ( p <> Nil ) And ( q <> Nil ) Then
              Begin
                add_right( p, ix, iy );
                merge_left( p, q, out_poly );
                e0.outp[ABOVE] := Nil;
                e1.outp[ABOVE] := Nil;
              End;
            vtIMM:
              If ( p <> Nil ) And ( q <> Nil ) Then
              Begin
                add_right( p, ix, iy );
                merge_left( p, q, out_poly );
                add_local_min( out_poly, e0, ix, iy );
                e1.outp[ABOVE] := e0.outp[ABOVE];
              End;
            vtEMM:
              If ( p <> Nil ) And ( q <> Nil ) Then
              Begin
                add_left( p, ix, iy );
                merge_right( p, q, out_poly );
                add_local_min( out_poly, e0, ix, iy );
                e1.outp[ABOVE] := e0.outp[ABOVE];
              End;
          End; (* End of switch *)

        End; (* End of contributing intersection conditional *)

        (* Swap bundle sides in response to edge crossing *)
        If boolean( e0.bundle[ABOVE, CLIP] ) Then
          e1.bside[CLIP] := ( 1 - e1.bside[CLIP] );
        If boolean( e1.bundle[ABOVE, CLIP] ) Then
          e0.bside[CLIP] := ( 1 - e0.bside[CLIP] );
        If boolean( e0.bundle[ABOVE, SUBJ] ) Then
          e1.bside[SUBJ] := ( 1 - e1.bside[SUBJ] );
        If boolean( e1.bundle[ABOVE, SUBJ] ) Then
          e0.bside[SUBJ] := ( 1 - e0.bside[SUBJ] );

        (* Swap e0 and e1 bundles in the AET *)
        prev_edge := e0.prev;
        next_edge := e1.next;
        If next_edge <> Nil Then
          next_edge.prev := e0;

        If e0.bstate[ABOVE] = bsBUNDLE_HEAD Then
        Begin
          search := TRUE;
          While ( search ) Do
          Begin
            prev_edge := prev_edge.prev;
            If prev_edge <> Nil Then
            Begin
              If prev_edge.bstate[ABOVE] <> bsBUNDLE_TAIL Then
                search := FALSE;
            End
            Else
              search := FALSE;
          End;
        End;
        If prev_edge = Nil Then
        Begin
          aet.prev := e1;
          e1.next := aet;
          aet := e0.next;
        End
        Else
        Begin
          prev_edge.next.prev := e1;
          e1.next := prev_edge.next;
          prev_edge.next := e0.next;
        End;
        e0.next.prev := prev_edge;
        e1.next.prev := e1;
        e0.next := next_edge;

        intersect := intersect.next;
      End; (* End of IT loop*)

      (* Prepare for next scanbeam *)
      edge := aet;
      While edge <> Nil Do
      Begin
        next_edge := edge.next;
        succ_edge := edge.succ;

        If ( edge.top.y = yt ) And ( succ_edge <> Nil ) Then
        Begin
          (* Replace AET edge by its successor *)
          succ_edge.outp[BELOW] := edge.outp[ABOVE];
          succ_edge.bstate[BELOW] := edge.bstate[ABOVE];
          succ_edge.bundle[BELOW, CLIP] := edge.bundle[ABOVE, CLIP];
          succ_edge.bundle[BELOW, SUBJ] := edge.bundle[ABOVE, SUBJ];
          prev_edge := edge.prev;
          If prev_edge <> Nil Then
            prev_edge.next := succ_edge
          Else
            aet := succ_edge;
          If next_edge <> Nil Then
            next_edge.prev := succ_edge;
          succ_edge.prev := prev_edge;
          succ_edge.next := next_edge;
        End
        Else
        Begin
          (* Update this edge *)
          edge.outp[BELOW] := edge.outp[ABOVE];
          edge.bstate[BELOW] := edge.bstate[ABOVE];
          edge.bundle[BELOW, CLIP] := edge.bundle[ABOVE, CLIP];
          edge.bundle[BELOW, SUBJ] := edge.bundle[ABOVE, SUBJ];
          edge.xb := edge.xt;
        End;
        edge.outp[ABOVE] := Nil;

        edge := next_edge
      End;
    End;
  End; (* === END OF SCANBEAM PROCESSING ================================== *)

  (* Generate result polygon from out_poly *)
  result.clear;
  result.hole.clear;
  tmpcontours := count_contours( out_poly );
  If tmpcontours > 0 Then
  Begin

    c := 0;
    poly := out_poly;
    While poly <> Nil Do
    Begin
      npoly := poly.next;
      If poly.active <> 0 Then
      Begin

        contour.NumVertices := poly.active;
        GetMem( contour.vertex, contour.NumVertices * sizeof( TEzPoint ) );
        fillchar( contour.vertex^, contour.NumVertices * sizeof( TEzPoint ), 0 );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -