voronoi.patch

Patch against master but applies cleanly to 2.8.1 - Andrew Bevitt, 2015-07-15 04:47 PM

Download (8.31 KB)

View differences:

python/plugins/fTools/tools/doGeometry.py Thu Jul 16 09:31:20 2015
36 36
import voronoi
37 37
from sets import Set
38 38

  
39
# For comparing equality in lat/long - 10^6 meters are < 1 degree
40
# so this gives mm resolution at lat=0. For finer resolution tasks
41
# a localised projection will likely be used, so this should be OK.
42
FLT_EPSILON = 10**-9
43

  
39 44
class GeometryDialog( QDialog, Ui_Dialog ):
40 45
  def __init__( self, iface, function ):
41 46
    QDialog.__init__( self, iface.mainWindow() )
......
729 734
    """ Clip voronoi function based on code written for Inkscape
730 735
        Copyright (C) 2010 Alvin Penner, [email protected]
731 736
    """
737
    def float_eq( a, b ):
738
      # the initial == test is for efficiency
739
      return a == b or abs( a - b ) <= FLT_EPSILON
740
    
732 741
    def clip_line( x1, y1, x2, y2, w, h, x, y ):
742
      # where both x's are left of the clipping region no line needed
733 743
      if x1 < 0 - x and x2 < 0 - x:
734 744
        return [ 0, 0, 0, 0 ]
745
      # where both x's are right of the clipping region no line needed
735 746
      if x1 > w + x and x2 > w + x:
736 747
        return [ 0, 0, 0, 0 ]
737
      if x1 < 0 - x:
738
        y1 = ( y1 * x2 - y2 * x1 ) / ( x2 - x1 )
739
        x1 = 0 - x
740
      if x2 < 0 - x:
741
        y2 = ( y1 * x2 - y2 * x1 ) / ( x2 - x1 )
742
        x2 = 0 - x
743
      if x1 > w + x:
744
        y1 = y1 + ( w + x - x1 ) * ( y2 - y1 ) / ( x2 - x1 )
745
        x1 = w + x
746
      if x2 > w + x:
747
        y2 = y1 + ( w + x - x1 ) *( y2 - y1 ) / ( x2 - x1 )
748
        x2 = w + x
748
      # where both y's are below the clipping region no line needed
749 749
      if y1 < 0 - y and y2 < 0 - y:
750 750
        return [ 0, 0, 0, 0 ]
751
      # where both y's are above the clipping region no line needed
751 752
      if y1 > h + y and y2 > h + y:
752 753
        return [ 0, 0, 0, 0 ]
753
      if x1 == x2 and y1 == y2:
754
      # where end points are too close to tell apart no line needed
755
      if float_eq( x1, x2 ) and float_eq( y1, y2 ):
754 756
        return [ 0, 0, 0, 0 ]
755
      if y1 < 0 - y:
756
        x1 = ( x1 * y2 - x2 * y1 ) / ( y2 - y1 )
757
      # y = mx + b: calculate gradient but make sure is not a vertical line
758
      if not float_eq( x1, x2 ):
759
        m = (y2 - y1) / (x2 - x1)
760
      else:
761
        m = float("+inf") # vertical lines have infinite gradient
762
      # y = mx + b: calculate intercept, if horizontal m==0 so use first Y value
763
      if ( not float_eq( y1, y2 ) and not float_eq( x1, x2 ) ) or float_eq( y1, y2):
764
        b = y1 - m*x1 # b = y1 when y1 == y2
765
      else: # y1 != y2 and x1 == x2
766
        b = float("nan") # vertical lines have no intercept
767
      # for simplicity later define if the line is vertical
768
      is_vertical = ( m == float("+inf") and b == float("nan") )
769
      # where either of the x1,y1 or x2,y2 points are outside of the clipping region
770
      # need to move them to be on the border of the region; this is done by recalculating
771
      # the x or y value based on the equation of the line holding the other axis as the
772
      # value of the clipping rectangle border that is violated.
773
      if x1 < 0 - x: # first point is left of region
774
        # impossible to have vertical line here, could be horizontal
775
        # but that doesn't matter as m = 0, b = y1 in that case
776
        x1 = 0 - x
777
        y1 = m*x1 + b
778
      if x2 < 0 - x: # second point is left of region
779
        # impossible to have vertical line here, could be horizontal
780
        # but that doesn't matter as m = 0, b = y1 in that case
781
        x2 = 0 - x
782
        y2 = m*x2 + b
783
      if x1 > w + x: # first point is right of region
784
        # impossible to have vertical line here, could be horizontal
785
        # but that doesn't matter as m = 0, b = y1 in that case
786
        x1 = w + x
787
        y1 = m*x1 + b
788
      if x2 > w + x: # second point is right of region
789
        # impossible to have vertical line here, could be horizontal
790
        # but that doesn't matter as m = 0, b = y1 in that case
791
        x2 = w + x
792
        y2 = m*x2 + b
793
      if y1 < 0 - y: # first point is below the region
794
        # impossible to have horizontal line here, could be vertical though
795
        # if is vertical then x value does not need to change
757 796
        y1 = 0 - y
758
      if y2 < 0 - y:
759
        x2 = ( x1 * y2 - x2 * y1 ) / ( y2 - y1 )
797
        if not is_vertical: # if veritical then X doesn't need to change
798
          x1 = (y1 - b) / m
799
      if y2 < 0 - y: # second point is below the region
800
        # impossible to have horizontal line here, could be vertical though
801
        # if is vertical then x value does not need to change
760 802
        y2 = 0 - y
761
      if y1 > h + y:
762
        x1 = x1 + ( h + y - y1 ) * ( x2 - x1 ) / ( y2 - y1 )
803
        if not is_vertical: # if vertical then X doesn't need to change
804
          x2 = (y2 - b) / m
805
      if y1 > h + y: # first point is above the region
806
        # impossible to have horizontal line here, could be vertical though
807
        # if is vertical then x value does not need to change
763 808
        y1 = h + y
764
      if y2 > h + y:
765
        x2 = x1 + ( h + y - y1) * ( x2 - x1 ) / ( y2 - y1 )
809
        if not is_vertical: # if vertical then X doesn't need to change
810
          x1 = (y1 - b) / m
811
      if y2 > h + y: # second point is above the region
812
        # impossible to have horizontal line here, could be vertical though
813
        # if is vertical then x value does not need to change
766 814
        y2 = h + y
815
        if not is_vertical: # if vertical then X doesn't need to change
816
          x2 = (y2 - b) / m
817
      # recheck point approximate equivalance because both points may have been
818
      # outside the region and thus were both clipped to a point on the boundary
819
      if float_eq( x1, x2 ) and float_eq( y1, y2 ):
820
        return [ 0, 0, 0, 0 ]
821
      # return the clipped region
767 822
      return [ x1, y1, x2, y2 ]
768 823
    lines = []
769 824
    hasXMin = False
......
772 827
    hasYMax = False
773 828
    for edge in edges:
774 829
      if edge[ 1 ] >= 0 and edge[ 2 ] >= 0:       # two vertices
775
          [ x1, y1, x2, y2 ] = clip_line( c.vertices[ edge[ 1 ] ][ 0 ], c.vertices[ edge[ 1 ] ][ 1 ], c.vertices[ edge[ 2 ] ][ 0 ], c.vertices[ edge[ 2 ] ][ 1 ], width, height, exX, exY )
830
        [ x1, y1, x2, y2 ] = clip_line( c.vertices[ edge[ 1 ] ][ 0 ], c.vertices[ edge[ 1 ] ][ 1 ], c.vertices[ edge[ 2 ] ][ 0 ], c.vertices[ edge[ 2 ] ][ 1 ], width, height, exX, exY )
776 831
      elif edge[ 1 ] >= 0:                      # only one vertex
777 832
        if c.lines[ edge[ 0 ] ][ 1 ] == 0:      # vertical line
778
          xtemp = c.lines[ edge[ 0 ] ][ 2 ] / c.lines[ edge[ 0 ] ][ 0 ]
833
          xtemp = c.vertices[ edge[ 1 ] ][ 0 ]
779 834
          if c.vertices[ edge[ 1 ] ][ 1 ] > ( height + exY ) / 2:
780 835
            ytemp = height + exY
781 836
          else:
782
            ytemp = 0 - exX
837
            ytemp = 0.0 - exY
783 838
        else:
784 839
          xtemp = width + exX
785
          ytemp = ( c.lines[ edge[ 0 ] ][ 2 ] - ( width + exX ) * c.lines[ edge[ 0 ] ][ 0 ] ) / c.lines[ edge[ 0 ] ][ 1 ]
840
          ytemp = ( c.lines[ edge[ 0 ] ][ 2 ] - xtemp * c.lines[ edge[ 0 ] ][ 0 ] ) / c.lines[ edge[ 0 ] ][ 1 ]
786 841
        [ x1, y1, x2, y2 ] = clip_line( c.vertices[ edge[ 1 ] ][ 0 ], c.vertices[ edge[ 1 ] ][ 1 ], xtemp, ytemp, width, height, exX, exY )
787 842
      elif edge[ 2 ] >= 0:                       # only one vertex
788 843
        if c.lines[ edge[ 0 ] ][ 1 ] == 0:       # vertical line
789
          xtemp = c.lines[ edge[ 0 ] ][ 2 ] / c.lines[ edge[ 0 ] ][ 0 ]
844
          xtemp = c.vertices[ edge[ 2 ] ][ 0 ]
790 845
          if c.vertices[ edge[ 2 ] ][ 1 ] > ( height + exY ) / 2:
791 846
            ytemp = height + exY
792 847
          else:
793 848
            ytemp = 0.0 - exY
794 849
        else:
795 850
          xtemp = 0.0 - exX
796
          ytemp = c.lines[ edge[ 0 ] ][ 2 ] / c.lines[ edge[ 0 ] ][ 1 ]
851
          ytemp = ( c.lines[ edge[ 0 ] ][ 2 ] - xtemp * c.lines[ edge[ 0 ] ][ 0 ] ) / c.lines[ edge[ 0 ] ][ 1 ]
797 852
        [ x1, y1, x2, y2 ] = clip_line( xtemp, ytemp, c.vertices[ edge[ 2 ] ][ 0 ], c.vertices[ edge[ 2 ] ][ 1 ], width, height, exX, exY )
798 853
      if x1 or x2 or y1 or y2:
799 854
        lines.append( QgsPoint( x1 + extent.xMinimum(), y1 + extent.yMinimum() ) )
800 855
        lines.append( QgsPoint( x2 + extent.xMinimum(), y2 + extent.yMinimum() ) )
801
        if 0 - exX in ( x1, x2 ):
856
        if 0.0 - exX in ( x1, x2 ):
802 857
          hasXMin = True
803
        if 0 - exY in ( y1, y2 ):
858
        if 0.0 - exY in ( y1, y2 ):
804 859
          hasYMin = True
805 860
        if height + exY in ( y1, y2 ):
806 861
          hasYMax = True