signature:
def create_for_noise ( other_param , threshold = ( - 10 , 10 ) , activated = True ) :
    """Creates a Sigmoid that is adjusted to be used with noise parameters ,
 i . e . with parameters which ' s output values are in the range [ 0.0 , 1.0 ] .
 Parameters
 other _ param : imgaug . parameters . StochasticParameter
 See : func : ` imgaug . parameters . Sigmoid . _ _ init _ _ ` .
 threshold : number or tuple of number or iterable of number or imgaug . parameters . StochasticParameter , optional
 See : func : ` imgaug . parameters . Sigmoid . _ _ init _ _ ` .
 activated : bool or number , optional
 See : func : ` imgaug . parameters . Sigmoid . _ _ init _ _ ` .
 Returns
 Sigmoid
 A sigmoid adjusted to be used with noise ."""

implementation: return Sigmoid ( other_param , threshold , activated , mul = 20 , add = - 10 )


signature:
def area ( self ) :
    """Estimate the area of the polygon .
 Returns
 number
 Area of the polygon ."""

implementation:
if len ( self . exterior ) < 3 :
    raise Exception ( "Cannot compute the polygon's area because it contains less than three points." )
poly = self . to_shapely_polygon ( )
return poly . area


signature:
def project ( self , from_shape , to_shape ) :
    """Project the polygon onto an image with different shape .
 The relative coordinates of all points remain the same .
 E . g . a point at ( x = 20 , y = 20 ) on an image ( width = 100 , height = 200 ) will be
 projected on a new image ( width = 200 , height = 100 ) to ( x = 40 , y = 10 ) .
 This is intended for cases where the original image is resized .
 It cannot be used for more complex changes ( e . g . padding , cropping ) .
 Parameters
 from _ shape : tuple of int
 Shape of the original image . ( Before resize . )
 to _ shape : tuple of int
 Shape of the new image . ( After resize . )
 Returns
 imgaug . Polygon
 Polygon object with new coordinates ."""

implementation:
if from_shape [ 0 : 2 ] == to_shape [ 0 : 2 ] :
    return self . copy ( )
ls_proj = self . to_line_string ( closed = False ) . project ( from_shape , to_shape )
return self . copy ( exterior = ls_proj . coords )


signature:
def find_closest_point_index ( self , x , y , return_distance = False ) :
    """Find the index of the point within the exterior that is closest to the given coordinates .
 " Closeness " is here defined based on euclidean distance .
 This method will raise an AssertionError if the exterior contains no points .
 Parameters
 x : number
 X - coordinate around which to search for close points .
 y : number
 Y - coordinate around which to search for close points .
 return _ distance : bool , optional
 Whether to also return the distance of the closest point .
 Returns
 int
 Index of the closest point .
 number
 Euclidean distance to the closest point .
 This value is only returned if ` return _ distance ` was set to True ."""

implementation:
ia . do_assert ( len ( self . exterior ) > 0 )
distances = [ ]
for x2 , y2 in self . exterior :
    d = ( x2 - x ) ** 2 + ( y2 - y ) ** 2
    distances . append ( d )
distances = np . sqrt ( distances )
closest_idx = np . argmin ( distances )
if return_distance :
    return closest_idx , distances [ closest_idx ]
return closest_idx


signature:
def is_fully_within_image ( self , image ) :
    """Estimate whether the polygon is fully inside the image area .
 Parameters
 image : ( H , W , . . . ) ndarray or tuple of int
 Image dimensions to use .
 If an ndarray , its shape will be used .
 If a tuple , it is assumed to represent the image shape and must contain at least two integers .
 Returns
 bool
 True if the polygon is fully inside the image area .
 False otherwise ."""

implementation: return not self . is_out_of_image ( image , fully = True , partly = True )


signature:
def is_partly_within_image ( self , image ) :
    """Estimate whether the polygon is at least partially inside the image area .
 Parameters
 image : ( H , W , . . . ) ndarray or tuple of int
 Image dimensions to use .
 If an ndarray , its shape will be used .
 If a tuple , it is assumed to represent the image shape and must contain at least two integers .
 Returns
 bool
 True if the polygon is at least partially inside the image area .
 False otherwise ."""

implementation: return not self . is_out_of_image ( image , fully = True , partly = False )


signature:
def is_out_of_image ( self , image , fully = True , partly = False ) :
    """Estimate whether the polygon is partially or fully outside of the image area .
 Parameters
 image : ( H , W , . . . ) ndarray or tuple of int
 Image dimensions to use .
 If an ndarray , its shape will be used .
 If a tuple , it is assumed to represent the image shape and must contain at least two integers .
 fully : bool , optional
 Whether to return True if the polygon is fully outside of the image area .
 partly : bool , optional
 Whether to return True if the polygon is at least partially outside fo the image area .
 Returns
 bool
 True if the polygon is partially / fully outside of the image area , depending
 on defined parameters . False otherwise ."""

implementation:
# TODO this is inconsistent with line strings , which return a default
# value in these cases
if len ( self . exterior ) == 0 :
    raise Exception ( "Cannot determine whether the polygon is inside the image, because it contains no points." )
ls = self . to_line_string ( )
return ls . is_out_of_image ( image , fully = fully , partly = partly )


signature:
def clip_out_of_image ( self , image ) :
    """Cut off all parts of the polygon that are outside of the image .
 This operation may lead to new points being created .
 As a single polygon may be split into multiple new polygons , the result
 is always a list , which may contain more than one output polygon .
 This operation will return an empty list if the polygon is completely
 outside of the image plane .
 Parameters
 image : ( H , W , . . . ) ndarray or tuple of int
 Image dimensions to use for the clipping of the polygon .
 If an ndarray , its shape will be used .
 If a tuple , it is assumed to represent the image shape and must
 contain at least two integers .
 Returns
 list of imgaug . Polygon
 Polygon , clipped to fall within the image dimensions .
 Returned as a list , because the clipping can split the polygon into
 multiple parts . The list may also be empty , if the polygon was
 fully outside of the image plane ."""

implementation:
# load shapely lazily , which makes the dependency more optional
import shapely . geometry
# if fully out of image , clip everything away , nothing remaining
if self . is_out_of_image ( image , fully = True , partly = False ) :
    return [ ]
h , w = image . shape [ 0 : 2 ] if ia . is_np_array ( image ) else image [ 0 : 2 ]
poly_shapely = self . to_shapely_polygon ( )
poly_image = shapely . geometry . Polygon ( [ ( 0 , 0 ) , ( w , 0 ) , ( w , h ) , ( 0 , h ) ] )
multipoly_inter_shapely = poly_shapely . intersection ( poly_image )
if not isinstance ( multipoly_inter_shapely , shapely . geometry . MultiPolygon ) :
    ia . do_assert ( isinstance ( multipoly_inter_shapely , shapely . geometry . Polygon ) )
    multipoly_inter_shapely = shapely . geometry . MultiPolygon ( [ multipoly_inter_shapely ] )
polygons = [ ]
for poly_inter_shapely in multipoly_inter_shapely . geoms :
    polygons . append ( Polygon . from_shapely ( poly_inter_shapely , label = self . label ) )
# shapely changes the order of points , we try here to preserve it as
# much as possible
polygons_reordered = [ ]
for polygon in polygons :
    found = False
    for x , y in self . exterior :
        closest_idx , dist = polygon . find_closest_point_index ( x = x , y = y , return_distance = True )
        if dist < 1e-6 :
            polygon_reordered = polygon . change_first_point_by_index ( closest_idx )
            polygons_reordered . append ( polygon_reordered )
            found = True
            break
    ia . do_assert ( found )
# could only not find closest points if new polys are empty
return polygons_reordered


signature:
def shift ( self , top = None , right = None , bottom = None , left = None ) :
    """Shift the polygon from one or more image sides , i . e . move it on the x / y - axis .
 Parameters
 top : None or int , optional
 Amount of pixels by which to shift the polygon from the top .
 right : None or int , optional
 Amount of pixels by which to shift the polygon from the right .
 bottom : None or int , optional
 Amount of pixels by which to shift the polygon from the bottom .
 left : None or int , optional
 Amount of pixels by which to shift the polygon from the left .
 Returns
 imgaug . Polygon
 Shifted polygon ."""

implementation:
ls_shifted = self . to_line_string ( closed = False ) . shift ( top = top , right = right , bottom = bottom , left = left )
return self . copy ( exterior = ls_shifted . coords )


signature:
def draw_on_image ( self , image , color = ( 0 , 255 , 0 ) , color_face = None , color_lines = None , color_points = None , alpha = 1.0 , alpha_face = None , alpha_lines = None , alpha_points = None , size = 1 , size_lines = None , size_points = None , raise_if_out_of_image = False ) :
    """Draw the polygon on an image .
 Parameters
 image : ( H , W , C ) ndarray
 The image onto which to draw the polygon . Usually expected to be
 of dtype ` ` uint8 ` ` , though other dtypes are also handled .
 color : iterable of int , optional
 The color to use for the whole polygon .
 Must correspond to the channel layout of the image . Usually RGB .
 The values for ` color _ face ` , ` color _ lines ` and ` color _ points `
 will be derived from this color if they are set to ` ` None ` ` .
 This argument has no effect if ` color _ face ` , ` color _ lines `
 and ` color _ points ` are all set anything other than ` ` None ` ` .
 color _ face : None or iterable of int , optional
 The color to use for the inner polygon area ( excluding perimeter ) .
 Must correspond to the channel layout of the image . Usually RGB .
 If this is ` ` None ` ` , it will be derived from ` ` color * 1.0 ` ` .
 color _ lines : None or iterable of int , optional
 The color to use for the line ( aka perimeter / border ) of the polygon .
 Must correspond to the channel layout of the image . Usually RGB .
 If this is ` ` None ` ` , it will be derived from ` ` color * 0.5 ` ` .
 color _ points : None or iterable of int , optional
 The color to use for the corner points of the polygon .
 Must correspond to the channel layout of the image . Usually RGB .
 If this is ` ` None ` ` , it will be derived from ` ` color * 0.5 ` ` .
 alpha : float , optional
 The opacity of the whole polygon , where ` ` 1.0 ` ` denotes a completely
 visible polygon and ` ` 0.0 ` ` an invisible one .
 The values for ` alpha _ face ` , ` alpha _ lines ` and ` alpha _ points `
 will be derived from this alpha value if they are set to ` ` None ` ` .
 This argument has no effect if ` alpha _ face ` , ` alpha _ lines `
 and ` alpha _ points ` are all set anything other than ` ` None ` ` .
 alpha _ face : None or number , optional
 The opacity of the polygon ' s inner area ( excluding the perimeter ) ,
 where ` ` 1.0 ` ` denotes a completely visible inner area and ` ` 0.0 ` `
 an invisible one .
 If this is ` ` None ` ` , it will be derived from ` ` alpha * 0.5 ` ` .
 alpha _ lines : None or number , optional
 The opacity of the polygon ' s line ( aka perimeter / border ) ,
 where ` ` 1.0 ` ` denotes a completely visible line and ` ` 0.0 ` ` an
 invisible one .
 If this is ` ` None ` ` , it will be derived from ` ` alpha * 1.0 ` ` .
 alpha _ points : None or number , optional
 The opacity of the polygon ' s corner points , where ` ` 1.0 ` ` denotes
 completely visible corners and ` ` 0.0 ` ` invisible ones .
 If this is ` ` None ` ` , it will be derived from ` ` alpha * 1.0 ` ` .
 size : int , optional
 Size of the polygon .
 The sizes of the line and points are derived from this value ,
 unless they are set .
 size _ lines : None or int , optional
 Thickness of the polygon ' s line ( aka perimeter / border ) .
 If ` ` None ` ` , this value is derived from ` size ` .
 size _ points : int , optional
 Size of the points in pixels .
 If ` ` None ` ` , this value is derived from ` ` 3 * size ` ` .
 raise _ if _ out _ of _ image : bool , optional
 Whether to raise an error if the polygon is fully
 outside of the image . If set to False , no error will be raised and
 only the parts inside the image will be drawn .
 Returns
 result : ( H , W , C ) ndarray
 Image with polygon drawn on it . Result dtype is the same as the input dtype ."""

implementation:
assert color is not None
assert alpha is not None
assert size is not None
color_face = color_face if color_face is not None else np . array ( color )
color_lines = color_lines if color_lines is not None else np . array ( color ) * 0.5
color_points = color_points if color_points is not None else np . array ( color ) * 0.5
alpha_face = alpha_face if alpha_face is not None else alpha * 0.5
alpha_lines = alpha_lines if alpha_lines is not None else alpha
alpha_points = alpha_points if alpha_points is not None else alpha
size_lines = size_lines if size_lines is not None else size
size_points = size_points if size_points is not None else size * 3
if image . ndim == 2 :
    assert ia . is_single_number ( color_face ) , ( "Got a 2D image. Expected then 'color_face' to be a single " "number, but got %s." % ( str ( color_face ) , ) )
    color_face = [ color_face ]
elif image . ndim == 3 and ia . is_single_number ( color_face ) :
    color_face = [ color_face ] * image . shape [ - 1 ]
if alpha_face < 0.01 :
    alpha_face = 0
elif alpha_face > 0.99 :
    alpha_face = 1
if raise_if_out_of_image and self . is_out_of_image ( image ) :
    raise Exception ( "Cannot draw polygon %s on image with shape %s." % ( str ( self ) , image . shape ) )
# TODO np . clip to image plane if is _ fully _ within _ image ( ) , similar to how it is done for bounding boxes
# TODO improve efficiency by only drawing in rectangle that covers poly instead of drawing in the whole image
# TODO for a rectangular polygon , the face coordinates include the top / left boundary but not the right / bottom
# boundary . This may be unintuitive when not drawing the boundary . Maybe somehow remove the boundary
# coordinates from the face coordinates after generating both ?
input_dtype = image . dtype
result = image . astype ( np . float32 )
rr , cc = skimage . draw . polygon ( self . yy_int , self . xx_int , shape = image . shape )
if len ( rr ) > 0 :
    if alpha_face == 1 :
        result [ rr , cc ] = np . float32 ( color_face )
    elif alpha_face == 0 :
        pass
    else :
        result [ rr , cc ] = ( ( 1 - alpha_face ) * result [ rr , cc , : ] + alpha_face * np . float32 ( color_face ) )
ls_open = self . to_line_string ( closed = False )
ls_closed = self . to_line_string ( closed = True )
result = ls_closed . draw_lines_on_image ( result , color = color_lines , alpha = alpha_lines , size = size_lines , raise_if_out_of_image = raise_if_out_of_image )
result = ls_open . draw_points_on_image ( result , color = color_points , alpha = alpha_points , size = size_points , raise_if_out_of_image = raise_if_out_of_image )
if input_dtype . type == np . uint8 :
    result = np . clip ( np . round ( result ) , 0 , 255 ) . astype ( input_dtype )
    # TODO make clipping more flexible
else :
    result = result . astype ( input_dtype )
return result


signature:
def extract_from_image ( self , image ) :
    """Extract the image pixels within the polygon .
 This function will zero - pad the image if the polygon is partially / fully outside of
 the image .
 Parameters
 image : ( H , W ) ndarray or ( H , W , C ) ndarray
 The image from which to extract the pixels within the polygon .
 Returns
 result : ( H ' , W ' ) ndarray or ( H ' , W ' , C ) ndarray
 Pixels within the polygon . Zero - padded if the polygon is partially / fully
 outside of the image ."""

implementation:
ia . do_assert ( image . ndim in [ 2 , 3 ] )
if len ( self . exterior ) <= 2 :
    raise Exception ( "Polygon must be made up of at least 3 points to extract its area from an image." )
bb = self . to_bounding_box ( )
bb_area = bb . extract_from_image ( image )
if self . is_out_of_image ( image , fully = True , partly = False ) :
    return bb_area
xx = self . xx_int
yy = self . yy_int
xx_mask = xx - np . min ( xx )
yy_mask = yy - np . min ( yy )
height_mask = np . max ( yy_mask )
width_mask = np . max ( xx_mask )
rr_face , cc_face = skimage . draw . polygon ( yy_mask , xx_mask , shape = ( height_mask , width_mask ) )
mask = np . zeros ( ( height_mask , width_mask ) , dtype = np . bool )
mask [ rr_face , cc_face ] = True
if image . ndim == 3 :
    mask = np . tile ( mask [ : , : , np . newaxis ] , ( 1 , 1 , image . shape [ 2 ] ) )
return bb_area * mask


signature:
def change_first_point_by_coords ( self , x , y , max_distance = 1e-4 , raise_if_too_far_away = True ) :
    """Set the first point of the exterior to the given point based on its coordinates .
 If multiple points are found , the closest one will be picked .
 If no matching points are found , an exception is raised .
 Note : This method does * not * work in - place .
 Parameters
 x : number
 X - coordinate of the point .
 y : number
 Y - coordinate of the point .
 max _ distance : None or number , optional
 Maximum distance past which possible matches are ignored .
 If ` ` None ` ` the distance limit is deactivated .
 raise _ if _ too _ far _ away : bool , optional
 Whether to raise an exception if the closest found point is too
 far away ( ` ` True ` ` ) or simply return an unchanged copy if this
 object ( ` ` False ` ` ) .
 Returns
 imgaug . Polygon
 Copy of this polygon with the new point order ."""

implementation:
if len ( self . exterior ) == 0 :
    raise Exception ( "Cannot reorder polygon points, because it contains no points." )
closest_idx , closest_dist = self . find_closest_point_index ( x = x , y = y , return_distance = True )
if max_distance is not None and closest_dist > max_distance :
    if not raise_if_too_far_away :
        return self . deepcopy ( )
    closest_point = self . exterior [ closest_idx , : ]
    raise Exception ( "Closest found point (%.9f, %.9f) exceeds max_distance of %.9f exceeded" % ( closest_point [ 0 ] , closest_point [ 1 ] , closest_dist ) )
return self . change_first_point_by_index ( closest_idx )


signature:
def change_first_point_by_index ( self , point_idx ) :
    """Set the first point of the exterior to the given point based on its index .
 Note : This method does * not * work in - place .
 Parameters
 point _ idx : int
 Index of the desired starting point .
 Returns
 imgaug . Polygon
 Copy of this polygon with the new point order ."""

implementation:
ia . do_assert ( 0 <= point_idx < len ( self . exterior ) )
if point_idx == 0 :
    return self . deepcopy ( )
exterior = np . concatenate ( ( self . exterior [ point_idx : , : ] , self . exterior [ : point_idx , : ] ) , axis = 0 )
return self . deepcopy ( exterior = exterior )


signature:
def to_shapely_polygon ( self ) :
    """Convert this polygon to a Shapely polygon .
 Returns
 shapely . geometry . Polygon
 The Shapely polygon matching this polygon ' s exterior ."""

implementation:
# load shapely lazily , which makes the dependency more optional
import shapely . geometry
return shapely . geometry . Polygon ( [ ( point [ 0 ] , point [ 1 ] ) for point in self . exterior ] )


signature:
def to_shapely_line_string ( self , closed = False , interpolate = 0 ) :
    """Convert this polygon to a Shapely LineString object .
 Parameters
 closed : bool , optional
 Whether to return the line string with the last point being identical to the first point .
 interpolate : int , optional
 Number of points to interpolate between any pair of two consecutive points . These points are added
 to the final line string .
 Returns
 shapely . geometry . LineString
 The Shapely LineString matching the polygon ' s exterior ."""

implementation: return _convert_points_to_shapely_line_string ( self . exterior , closed = closed , interpolate = interpolate )


signature:
def to_bounding_box ( self ) :
    """Convert this polygon to a bounding box tightly containing the whole polygon .
 Returns
 imgaug . BoundingBox
 Tight bounding box around the polygon ."""

implementation:
# TODO get rid of this deferred import
from imgaug . augmentables . bbs import BoundingBox
xx = self . xx
yy = self . yy
return BoundingBox ( x1 = min ( xx ) , x2 = max ( xx ) , y1 = min ( yy ) , y2 = max ( yy ) , label = self . label )


signature:
def to_keypoints ( self ) :
    """Convert this polygon ' s ` exterior ` to ` ` Keypoint ` ` instances .
 Returns
 list of imgaug . Keypoint
 Exterior vertices as ` ` Keypoint ` ` instances ."""

implementation:
# TODO get rid of this deferred import
from imgaug . augmentables . kps import Keypoint
return [ Keypoint ( x = point [ 0 ] , y = point [ 1 ] ) for point in self . exterior ]


signature:
def to_line_string ( self , closed = True ) :
    """Convert this polygon ' s ` exterior ` to a ` ` LineString ` ` instance .
 Parameters
 closed : bool , optional
 Whether to close the line string , i . e . to add the first point of
 the ` exterior ` also as the last point at the end of the line string .
 This has no effect if the polygon has a single point or zero
 points .
 Returns
 imgaug . augmentables . lines . LineString
 Exterior of the polygon as a line string ."""

implementation:
from imgaug . augmentables . lines import LineString
if not closed or len ( self . exterior ) <= 1 :
    return LineString ( self . exterior , label = self . label )
return LineString ( np . concatenate ( [ self . exterior , self . exterior [ 0 : 1 , : ] ] , axis = 0 ) , label = self . label )


signature:
def from_shapely ( polygon_shapely , label = None ) :
    """Create a polygon from a Shapely polygon .
 Note : This will remove any holes in the Shapely polygon .
 Parameters
 polygon _ shapely : shapely . geometry . Polygon
 The shapely polygon .
 label : None or str , optional
 The label of the new polygon .
 Returns
 imgaug . Polygon
 A polygon with the same exterior as the Shapely polygon ."""

implementation:
# load shapely lazily , which makes the dependency more optional
import shapely . geometry
ia . do_assert ( isinstance ( polygon_shapely , shapely . geometry . Polygon ) )
# polygon _ shapely . exterior can be None if the polygon was instantiated without points
if polygon_shapely . exterior is None or len ( polygon_shapely . exterior . coords ) == 0 :
    return Polygon ( [ ] , label = label )
exterior = np . float32 ( [ [ x , y ] for ( x , y ) in polygon_shapely . exterior . coords ] )
return Polygon ( exterior , label = label )


signature:
def exterior_almost_equals ( self , other , max_distance = 1e-6 , points_per_edge = 8 ) :
    """Estimate if this and other polygon ' s exterior are almost identical .
 The two exteriors can have different numbers of points , but any point
 randomly sampled on the exterior of one polygon should be close to the
 closest point on the exterior of the other polygon .
 Note that this method works approximately . One can come up with
 polygons with fairly different shapes that will still be estimated as
 equal by this method . In practice however this should be unlikely to be
 the case . The probability for something like that goes down as the
 interpolation parameter is increased .
 Parameters
 other : imgaug . Polygon or ( N , 2 ) ndarray or list of tuple
 The other polygon with which to compare the exterior .
 If this is an ndarray , it is assumed to represent an exterior .
 It must then have dtype ` ` float32 ` ` and shape ` ` ( N , 2 ) ` ` with the
 second dimension denoting xy - coordinates .
 If this is a list of tuples , it is assumed to represent an exterior .
 Each tuple then must contain exactly two numbers , denoting
 xy - coordinates .
 max _ distance : number , optional
 The maximum euclidean distance between a point on one polygon and
 the closest point on the other polygon . If the distance is exceeded
 for any such pair , the two exteriors are not viewed as equal . The
 points are other the points contained in the polygon ' s exterior
 ndarray or interpolated points between these .
 points _ per _ edge : int , optional
 How many points to interpolate on each edge .
 Returns
 bool
 Whether the two polygon ' s exteriors can be viewed as equal
 ( approximate test ) ."""

implementation:
if isinstance ( other , list ) :
    other = Polygon ( np . float32 ( other ) )
elif ia . is_np_array ( other ) :
    other = Polygon ( other )
else :
    assert isinstance ( other , Polygon )
    other = other
return self . to_line_string ( closed = True ) . coords_almost_equals ( other . to_line_string ( closed = True ) , max_distance = max_distance , points_per_edge = points_per_edge )


signature:
def almost_equals ( self , other , max_distance = 1e-6 , points_per_edge = 8 ) :
    """Estimate if this polygon ' s and another ' s geometry / labels are similar .
 This is the same as : func : ` imgaug . Polygon . exterior _ almost _ equals ` but
 additionally compares the labels .
 Parameters
 other
 The object to compare against . If not a Polygon , then False will
 be returned .
 max _ distance : float , optional
 See : func : ` imgaug . augmentables . polys . Polygon . exterior _ almost _ equals ` .
 points _ per _ edge : int , optional
 See : func : ` imgaug . augmentables . polys . Polygon . exterior _ almost _ equals ` .
 Returns
 bool
 Whether the two polygons can be viewed as equal . In the case of
 the exteriors this is an approximate test ."""

implementation:
if not isinstance ( other , Polygon ) :
    return False
if self . label is not None or other . label is not None :
    if self . label is None :
        return False
    if other . label is None :
        return False
    if self . label != other . label :
        return False
return self . exterior_almost_equals ( other , max_distance = max_distance , points_per_edge = points_per_edge )


signature:
def copy ( self , exterior = None , label = None ) :
    """Create a shallow copy of the Polygon object .
 Parameters
 exterior : list of imgaug . Keypoint or list of tuple or ( N , 2 ) ndarray , optional
 List of points defining the polygon . See : func : ` imgaug . Polygon . _ _ init _ _ ` for details .
 label : None or str , optional
 If not None , then the label of the copied object will be set to this value .
 Returns
 imgaug . Polygon
 Shallow copy ."""

implementation: return self . deepcopy ( exterior = exterior , label = label )


signature:
def deepcopy ( self , exterior = None , label = None ) :
    """Create a deep copy of the Polygon object .
 Parameters
 exterior : list of Keypoint or list of tuple or ( N , 2 ) ndarray , optional
 List of points defining the polygon . See ` imgaug . Polygon . _ _ init _ _ ` for details .
 label : None or str
 If not None , then the label of the copied object will be set to this value .
 Returns
 imgaug . Polygon
 Deep copy ."""

implementation: return Polygon ( exterior = np . copy ( self . exterior ) if exterior is None else exterior , label = self . label if label is None else label )


signature:
def on ( self , image ) :
    """Project polygons from one image to a new one .
 Parameters
 image : ndarray or tuple of int
 New image onto which the polygons are to be projected .
 May also simply be that new image ' s shape tuple .
 Returns
 imgaug . PolygonsOnImage
 Object containing all projected polygons ."""

implementation:
shape = normalize_shape ( image )
if shape [ 0 : 2 ] == self . shape [ 0 : 2 ] :
    return self . deepcopy ( )
polygons = [ poly . project ( self . shape , shape ) for poly in self . polygons ]
# TODO use deepcopy ( ) here
return PolygonsOnImage ( polygons , shape )


signature:
def draw_on_image ( self , image , color = ( 0 , 255 , 0 ) , color_face = None , color_lines = None , color_points = None , alpha = 1.0 , alpha_face = None , alpha_lines = None , alpha_points = None , size = 1 , size_lines = None , size_points = None , raise_if_out_of_image = False ) :
    """Draw all polygons onto a given image .
 Parameters
 image : ( H , W , C ) ndarray
 The image onto which to draw the bounding boxes .
 This image should usually have the same shape as set in
 ` ` PolygonsOnImage . shape ` ` .
 color : iterable of int , optional
 The color to use for the whole polygons .
 Must correspond to the channel layout of the image . Usually RGB .
 The values for ` color _ face ` , ` color _ lines ` and ` color _ points `
 will be derived from this color if they are set to ` ` None ` ` .
 This argument has no effect if ` color _ face ` , ` color _ lines `
 and ` color _ points ` are all set anything other than ` ` None ` ` .
 color _ face : None or iterable of int , optional
 The color to use for the inner polygon areas ( excluding perimeters ) .
 Must correspond to the channel layout of the image . Usually RGB .
 If this is ` ` None ` ` , it will be derived from ` ` color * 1.0 ` ` .
 color _ lines : None or iterable of int , optional
 The color to use for the lines ( aka perimeters / borders ) of the
 polygons . Must correspond to the channel layout of the image .
 Usually RGB . If this is ` ` None ` ` , it will be derived
 from ` ` color * 0.5 ` ` .
 color _ points : None or iterable of int , optional
 The color to use for the corner points of the polygons .
 Must correspond to the channel layout of the image . Usually RGB .
 If this is ` ` None ` ` , it will be derived from ` ` color * 0.5 ` ` .
 alpha : float , optional
 The opacity of the whole polygons , where ` ` 1.0 ` ` denotes
 completely visible polygons and ` ` 0.0 ` ` invisible ones .
 The values for ` alpha _ face ` , ` alpha _ lines ` and ` alpha _ points `
 will be derived from this alpha value if they are set to ` ` None ` ` .
 This argument has no effect if ` alpha _ face ` , ` alpha _ lines `
 and ` alpha _ points ` are all set anything other than ` ` None ` ` .
 alpha _ face : None or number , optional
 The opacity of the polygon ' s inner areas ( excluding the perimeters ) ,
 where ` ` 1.0 ` ` denotes completely visible inner areas and ` ` 0.0 ` `
 invisible ones .
 If this is ` ` None ` ` , it will be derived from ` ` alpha * 0.5 ` ` .
 alpha _ lines : None or number , optional
 The opacity of the polygon ' s lines ( aka perimeters / borders ) ,
 where ` ` 1.0 ` ` denotes completely visible perimeters and ` ` 0.0 ` `
 invisible ones .
 If this is ` ` None ` ` , it will be derived from ` ` alpha * 1.0 ` ` .
 alpha _ points : None or number , optional
 The opacity of the polygon ' s corner points , where ` ` 1.0 ` ` denotes
 completely visible corners and ` ` 0.0 ` ` invisible ones .
 Currently this is an on / off choice , i . e . only ` ` 0.0 ` ` or ` ` 1.0 ` `
 are allowed .
 If this is ` ` None ` ` , it will be derived from ` ` alpha * 1.0 ` ` .
 size : int , optional
 Size of the polygons .
 The sizes of the line and points are derived from this value ,
 unless they are set .
 size _ lines : None or int , optional
 Thickness of the polygon lines ( aka perimeter / border ) .
 If ` ` None ` ` , this value is derived from ` size ` .
 size _ points : int , optional
 The size of all corner points . If set to ` ` C ` ` , each corner point
 will be drawn as a square of size ` ` C x C ` ` .
 raise _ if _ out _ of _ image : bool , optional
 Whether to raise an error if any polygon is fully
 outside of the image . If set to False , no error will be raised and
 only the parts inside the image will be drawn .
 Returns
 image : ( H , W , C ) ndarray
 Image with drawn polygons ."""

implementation:
for poly in self . polygons :
    image = poly . draw_on_image ( image , color = color , color_face = color_face , color_lines = color_lines , color_points = color_points , alpha = alpha , alpha_face = alpha_face , alpha_lines = alpha_lines , alpha_points = alpha_points , size = size , size_lines = size_lines , size_points = size_points , raise_if_out_of_image = raise_if_out_of_image )
return image


signature:
def remove_out_of_image ( self , fully = True , partly = False ) :
    """Remove all polygons that are fully or partially outside of the image .
 Parameters
 fully : bool , optional
 Whether to remove polygons that are fully outside of the image .
 partly : bool , optional
 Whether to remove polygons that are partially outside of the image .
 Returns
 imgaug . PolygonsOnImage
 Reduced set of polygons , with those that were fully / partially
 outside of the image removed ."""

implementation:
polys_clean = [ poly for poly in self . polygons if not poly . is_out_of_image ( self . shape , fully = fully , partly = partly ) ]
# TODO use deepcopy ( ) here
return PolygonsOnImage ( polys_clean , shape = self . shape )


signature:
def clip_out_of_image ( self ) :
    """Clip off all parts from all polygons that are outside of the image .
 NOTE : The result can contain less polygons than the input did . That
 happens when a polygon is fully outside of the image plane .
 NOTE : The result can also contain * more * polygons than the input
 did . That happens when distinct parts of a polygon are only
 connected by areas that are outside of the image plane and hence will
 be clipped off , resulting in two or more unconnected polygon parts that
 are left in the image plane .
 Returns
 imgaug . PolygonsOnImage
 Polygons , clipped to fall within the image dimensions . Count of
 output polygons may differ from the input count ."""

implementation:
polys_cut = [ poly . clip_out_of_image ( self . shape ) for poly in self . polygons if poly . is_partly_within_image ( self . shape ) ]
polys_cut_flat = [ poly for poly_lst in polys_cut for poly in poly_lst ]
# TODO use deepcopy ( ) here
return PolygonsOnImage ( polys_cut_flat , shape = self . shape )


signature:
def shift ( self , top = None , right = None , bottom = None , left = None ) :
    """Shift all polygons from one or more image sides , i . e . move them on the x / y - axis .
 Parameters
 top : None or int , optional
 Amount of pixels by which to shift all polygons from the top .
 right : None or int , optional
 Amount of pixels by which to shift all polygons from the right .
 bottom : None or int , optional
 Amount of pixels by which to shift all polygons from the bottom .
 left : None or int , optional
 Amount of pixels by which to shift all polygons from the left .
 Returns
 imgaug . PolygonsOnImage
 Shifted polygons ."""

implementation:
polys_new = [ poly . shift ( top = top , right = right , bottom = bottom , left = left ) for poly in self . polygons ]
return PolygonsOnImage ( polys_new , shape = self . shape )


signature:
def deepcopy ( self ) :
    """Create a deep copy of the PolygonsOnImage object .
 Returns
 imgaug . PolygonsOnImage
 Deep copy ."""

implementation:
# Manual copy is far faster than deepcopy for PolygonsOnImage ,
# so use manual copy here too
polys = [ poly . deepcopy ( ) for poly in self . polygons ]
return PolygonsOnImage ( polys , tuple ( self . shape ) )


signature:
def from_shapely ( geometry , label = None ) :
    """Create a MultiPolygon from a Shapely MultiPolygon , a Shapely Polygon or a Shapely GeometryCollection .
 This also creates all necessary Polygons contained by this MultiPolygon .
 Parameters
 geometry : shapely . geometry . MultiPolygon or shapely . geometry . Polygon or shapely . geometry . collection . GeometryCollection
 The object to convert to a MultiPolygon .
 label : None or str , optional
 A label assigned to all Polygons within the MultiPolygon .
 Returns
 imgaug . MultiPolygon
 The derived MultiPolygon ."""

implementation:
# load shapely lazily , which makes the dependency more optional
import shapely . geometry
if isinstance ( geometry , shapely . geometry . MultiPolygon ) :
    return MultiPolygon ( [ Polygon . from_shapely ( poly , label = label ) for poly in geometry . geoms ] )
elif isinstance ( geometry , shapely . geometry . Polygon ) :
    return MultiPolygon ( [ Polygon . from_shapely ( geometry , label = label ) ] )
elif isinstance ( geometry , shapely . geometry . collection . GeometryCollection ) :
    ia . do_assert ( all ( [ isinstance ( poly , shapely . geometry . Polygon ) for poly in geometry . geoms ] ) )
    return MultiPolygon ( [ Polygon . from_shapely ( poly , label = label ) for poly in geometry . geoms ] )
else :
    raise Exception ( "Unknown datatype '%s'. Expected shapely.geometry.Polygon or " "shapely.geometry.MultiPolygon or " "shapely.geometry.collections.GeometryCollection." % ( type ( geometry ) , ) )


signature:
def Pad ( px = None , percent = None , pad_mode = "constant" , pad_cval = 0 , keep_size = True , sample_independently = True , name = None , deterministic = False , random_state = None ) :
    """Augmenter that pads images , i . e . adds columns / rows to them .
 dtype support : :
 See ` ` imgaug . augmenters . size . CropAndPad ` ` .
 Parameters
 px : None or int or imgaug . parameters . StochasticParameter or tuple , optional
 The number of pixels to pad on each side of the image .
 Either this or the parameter ` percent ` may be set , not both at the same
 time .
 * If None , then pixel - based padding will not be used .
 * If int , then that exact number of pixels will always be padded .
 * If StochasticParameter , then that parameter will be used for each
 image . Four samples will be drawn per image ( top , right , bottom ,
 left ) .
 * If a tuple of two ints with values a and b , then each side will
 be padded by a random amount in the range ` ` a < = x < = b ` ` .
 ` ` x ` ` is sampled per image side .
 * If a tuple of four entries , then the entries represent top , right ,
 bottom , left . Each entry may be a single integer ( always pad by
 exactly that value ) , a tuple of two ints ` ` a ` ` and ` ` b ` ` ( pad by
 an amount ` ` a < = x < = b ` ` ) , a list of ints ( pad by a random value
 that is contained in the list ) or a StochasticParameter ( sample
 the amount to pad from that parameter ) .
 percent : None or int or float or imgaug . parameters . StochasticParameter or tuple , optional
 The number of pixels to pad on each side of the image given
 * in percent * of the image height / width .
 E . g . if this is set to 0.1 , the augmenter will always add 10 percent
 of the image ' s height to the top , 10 percent of the width to the right ,
 10 percent of the height at the bottom and 10 percent of the width to
 the left . Either this or the parameter ` px ` may be set , not both at the
 same time .
 * If None , then percent - based padding will not be used .
 * If int , then expected to be 0 ( no padding ) .
 * If float , then that percentage will always be padded .
 * If StochasticParameter , then that parameter will be used for each
 image . Four samples will be drawn per image ( top , right , bottom ,
 left ) .
 * If a tuple of two floats with values a and b , then each side will
 be padded by a random percentage in the range ` ` a < = x < = b ` ` .
 ` ` x ` ` is sampled per image side .
 * If a tuple of four entries , then the entries represent top , right ,
 bottom , left . Each entry may be a single float ( always pad by
 exactly that percent value ) , a tuple of two floats ` ` a ` ` and ` ` b ` `
 ( pad by a percentage ` ` a < = x < = b ` ` ) , a list of floats ( pad by a
 random value that is contained in the list ) or a
 StochasticParameter ( sample the percentage to pad from that
 parameter ) .
 pad _ mode : imgaug . ALL or str or list of str or imgaug . parameters . StochasticParameter , optional
 Padding mode to use . The available modes match the numpy padding modes ,
 i . e . ` ` constant ` ` , ` ` edge ` ` , ` ` linear _ ramp ` ` , ` ` maximum ` ` , ` ` median ` ` ,
 ` ` minimum ` ` , ` ` reflect ` ` , ` ` symmetric ` ` , ` ` wrap ` ` . The modes
 ` ` constant ` ` and ` ` linear _ ramp ` ` use extra values , which are provided
 by ` ` pad _ cval ` ` when necessary . See : func : ` imgaug . imgaug . pad ` for
 more details .
 * If ` ` imgaug . ALL ` ` , then a random mode from all available modes
 will be sampled per image .
 * If a string , it will be used as the pad mode for all images .
 * If a list of strings , a random one of these will be sampled per
 image and used as the mode .
 * If StochasticParameter , a random mode will be sampled from this
 parameter per image .
 pad _ cval : number or tuple of number list of number or imgaug . parameters . StochasticParameter , optional
 The constant value to use if the pad mode is ` ` constant ` ` or the end
 value to use if the mode is ` ` linear _ ramp ` ` .
 See : func : ` imgaug . imgaug . pad ` for more details .
 * If number , then that value will be used .
 * If a tuple of two numbers and at least one of them is a float ,
 then a random number will be sampled from the continuous range
 ` ` a < = x < = b ` ` and used as the value . If both numbers are
 integers , the range is discrete .
 * If a list of number , then a random value will be chosen from the
 elements of the list and used as the value .
 * If StochasticParameter , a random value will be sampled from that
 parameter per image .
 keep _ size : bool , optional
 After padding , the result image will usually have a different
 height / width compared to the original input image . If this parameter is
 set to True , then the padded image will be resized to the input image ' s
 size , i . e . the augmenter ' s output shape is always identical to the
 input shape .
 sample _ independently : bool , optional
 If False AND the values for ` px ` / ` percent ` result in exactly one
 probability distribution for the amount to pad , only one single value
 will be sampled from that probability distribution and used for all
 sides . I . e . the pad amount then is the same for all sides .
 name : None or str , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 deterministic : bool , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 random _ state : None or int or numpy . random . RandomState , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 Examples
 > > > aug = iaa . Pad ( px = ( 0 , 10 ) )
 pads each side by a random value from the range 0px to 10px ( the value
 is sampled per side ) . The added rows / columns are filled with black pixels .
 > > > aug = iaa . Pad ( px = ( 0 , 10 ) , sample _ independently = False )
 samples one value v from the discrete range ` ` [ 0 . . 10 ] ` ` and pads all sides
 by ` ` v ` ` pixels .
 > > > aug = iaa . Pad ( px = ( 0 , 10 ) , keep _ size = False )
 pads each side by a random value from the range 0px to 10px ( the value
 is sampled per side ) . After padding , the images are NOT resized to their
 original size ( i . e . the images may end up having different heights / widths ) .
 > > > aug = iaa . Pad ( px = ( ( 0 , 10 ) , ( 0 , 5 ) , ( 0 , 10 ) , ( 0 , 5 ) ) )
 pads the top and bottom by a random value from the range 0px to 10px
 and the left and right by a random value in the range 0px to 5px .
 > > > aug = iaa . Pad ( percent = ( 0 , 0.1 ) )
 pads each side by a random value from the range 0 percent to
 10 percent . ( Percent with respect to the side ' s size , e . g . for the
 top side it uses the image ' s height . )
 > > > aug = iaa . Pad ( percent = ( [ 0.05 , 0.1 ] , [ 0.05 , 0.1 ] , [ 0.05 , 0.1 ] , [ 0.05 , 0.1 ] ) )
 pads each side by either 5 percent or 10 percent .
 > > > aug = iaa . Pad ( px = ( 0 , 10 ) , pad _ mode = " edge " )
 pads each side by a random value from the range 0px to 10px ( the values
 are sampled per side ) . The padding uses the ` ` edge ` ` mode from numpy ' s
 pad function .
 > > > aug = iaa . Pad ( px = ( 0 , 10 ) , pad _ mode = [ " constant " , " edge " ] )
 pads each side by a random value from the range 0px to 10px ( the values
 are sampled per side ) . The padding uses randomly either the ` ` constant ` `
 or ` ` edge ` ` mode from numpy ' s pad function .
 > > > aug = iaa . Pad ( px = ( 0 , 10 ) , pad _ mode = ia . ALL , pad _ cval = ( 0 , 255 ) )
 pads each side by a random value from the range 0px to 10px ( the values
 are sampled per side ) . It uses a random mode for numpy ' s pad function .
 If the mode is ` ` constant ` ` or ` ` linear _ ramp ` ` , it samples a random value
 ` ` v ` ` from the range ` ` [ 0 , 255 ] ` ` and uses that as the constant
 value ( ` ` mode = constant ` ` ) or end value ( ` ` mode = linear _ ramp ` ` ) ."""

implementation:
def recursive_validate ( v ) :
    if v is None :
        return v
    elif ia . is_single_number ( v ) :
        ia . do_assert ( v >= 0 )
        return v
    elif isinstance ( v , iap . StochasticParameter ) :
        return v
    elif isinstance ( v , tuple ) :
        return tuple ( [ recursive_validate ( v_ ) for v_ in v ] )
    elif isinstance ( v , list ) :
        return [ recursive_validate ( v_ ) for v_ in v ]
    else :
        raise Exception ( "Expected None or int or float or StochasticParameter or list or tuple, got %s." % ( type ( v ) , ) )
px = recursive_validate ( px )
percent = recursive_validate ( percent )
if name is None :
    name = "Unnamed%s" % ( ia . caller_name ( ) , )
aug = CropAndPad ( px = px , percent = percent , pad_mode = pad_mode , pad_cval = pad_cval , keep_size = keep_size , sample_independently = sample_independently , name = name , deterministic = deterministic , random_state = random_state )
return aug


signature:
def Crop ( px = None , percent = None , keep_size = True , sample_independently = True , name = None , deterministic = False , random_state = None ) :
    """Augmenter that crops / cuts away pixels at the sides of the image .
 That allows to cut out subimages from given ( full ) input images .
 The number of pixels to cut off may be defined in absolute values or
 percent of the image sizes .
 dtype support : :
 See ` ` imgaug . augmenters . size . CropAndPad ` ` .
 Parameters
 px : None or int or imgaug . parameters . StochasticParameter or tuple , optional
 The number of pixels to crop away ( cut off ) on each side of the image .
 Either this or the parameter ` percent ` may be set , not both at the same
 time .
 * If None , then pixel - based cropping will not be used .
 * If int , then that exact number of pixels will always be cropped .
 * If StochasticParameter , then that parameter will be used for each
 image . Four samples will be drawn per image ( top , right , bottom ,
 left ) .
 * If a tuple of two ints with values ` ` a ` ` and ` ` b ` ` , then each
 side will be cropped by a random amount in the range
 ` ` a < = x < = b ` ` . ` ` x ` ` is sampled per image side .
 * If a tuple of four entries , then the entries represent top , right ,
 bottom , left . Each entry may be a single integer ( always crop by
 exactly that value ) , a tuple of two ints ` ` a ` ` and ` ` b ` ` ( crop by
 an amount ` ` a < = x < = b ` ` ) , a list of ints ( crop by a random
 value that is contained in the list ) or a StochasticParameter
 ( sample the amount to crop from that parameter ) .
 percent : None or int or float or imgaug . parameters . StochasticParameter or tuple , optional
 The number of pixels to crop away ( cut off ) on each side of the image
 given * in percent * of the image height / width .
 E . g . if this is set to 0.1 , the augmenter will always crop away
 10 percent of the image ' s height at the top , 10 percent of the width
 on the right , 10 percent of the height at the bottom and 10 percent
 of the width on the left .
 Either this or the parameter ` px ` may be set , not both at the same time .
 * If None , then percent - based cropping will not be used .
 * If int , then expected to be 0 ( no cropping ) .
 * If float , then that percentage will always be cropped away .
 * If StochasticParameter , then that parameter will be used for each
 image . Four samples will be drawn per image ( top , right , bottom ,
 left ) .
 * If a tuple of two floats with values ` ` a ` ` and ` ` b ` ` , then each
 side will be cropped by a random percentage in the range
 ` ` a < = x < = b ` ` . ` ` x ` ` is sampled per image side .
 * If a tuple of four entries , then the entries represent top , right ,
 bottom , left . Each entry may be a single float ( always crop by
 exactly that percent value ) , a tuple of two floats a and ` ` b ` `
 ( crop by a percentage ` ` a < = x < = b ` ` ) , a list of floats ( crop by
 a random value that is contained in the list ) or a
 StochasticParameter ( sample the percentage to crop from that
 parameter ) .
 keep _ size : bool , optional
 After cropping , the result image has a different height / width than
 the input image . If this parameter is set to True , then the cropped
 image will be resized to the input image ' s size , i . e . the image size
 is then not changed by the augmenter .
 sample _ independently : bool , optional
 If False AND the values for ` px ` / ` percent ` result in exactly one
 probability distribution for the amount to crop , only one
 single value will be sampled from that probability distribution
 and used for all sides . I . e . the crop amount then is the same
 for all sides .
 name : None or str , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 deterministic : bool , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 random _ state : None or int or numpy . random . RandomState , optional
 See : func : ` imgaug . augmenters . meta . Augmenter . _ _ init _ _ ` .
 Examples
 > > > aug = iaa . Crop ( px = ( 0 , 10 ) )
 crops each side by a random value from the range 0px to 10px ( the value
 is sampled per side ) .
 > > > aug = iaa . Crop ( px = ( 0 , 10 ) , sample _ independently = False )
 samples one value ` ` v ` ` from the discrete range ` ` [ 0 . . 10 ] ` ` and crops all
 sides by ` ` v ` ` pixels .
 > > > aug = iaa . Crop ( px = ( 0 , 10 ) , keep _ size = False )
 crops each side by a random value from the range 0px to 10px ( the value
 is sampled per side ) . After cropping , the images are NOT resized to their
 original size ( i . e . the images may end up having different heights / widths ) .
 > > > aug = iaa . Crop ( px = ( ( 0 , 10 ) , ( 0 , 5 ) , ( 0 , 10 ) , ( 0 , 5 ) ) )
 crops the top and bottom by a random value from the range 0px to 10px
 and the left and right by a random value in the range 0px to 5px .
 > > > aug = iaa . Crop ( percent = ( 0 , 0.1 ) )
 crops each side by a random value from the range 0 percent to
 10 percent . ( Percent with respect to the side ' s size , e . g . for the
 top side it uses the image ' s height . )
 > > > aug = iaa . Crop ( percent = ( [ 0.05 , 0.1 ] , [ 0.05 , 0.1 ] , [ 0.05 , 0.1 ] , [ 0.05 , 0.1 ] ) )
 crops each side by either 5 percent or 10 percent ."""

implementation:
def recursive_negate ( v ) :
    if v is None :
        return v
    elif ia . is_single_number ( v ) :
        ia . do_assert ( v >= 0 )
        return - v
    elif isinstance ( v , iap . StochasticParameter ) :
        return iap . Multiply ( v , - 1 )
    elif isinstance ( v , tuple ) :
        return tuple ( [ recursive_negate ( v_ ) for v_ in v ] )
    elif isinstance ( v , list ) :
        return [ recursive_negate ( v_ ) for v_ in v ]
    else :
        raise Exception ( "Expected None or int or float or StochasticParameter or list or tuple, got %s." % ( type ( v ) , ) )
px = recursive_negate ( px )
percent = recursive_negate ( percent )
if name is None :
    name = "Unnamed%s" % ( ia . caller_name ( ) , )
aug = CropAndPad ( px = px , percent = percent , keep_size = keep_size , sample_independently = sample_independently , name = name , deterministic = deterministic , random_state = random_state )
return aug


signature:
def isect_segments__naive ( segments ) :
    """Brute force O ( n2 ) version of ` ` isect _ segments ` ` for test validation ."""

implementation:
isect = [ ]
# order points left - > right
if Real is float :
    segments = [ ( s [ 0 ] , s [ 1 ] ) if s [ 0 ] [ X ] <= s [ 1 ] [ X ] else ( s [ 1 ] , s [ 0 ] ) for s in segments ]
else :
    segments = [ ( ( Real ( s [ 0 ] [ 0 ] ) , Real ( s [ 0 ] [ 1 ] ) ) , ( Real ( s [ 1 ] [ 0 ] ) , Real ( s [ 1 ] [ 1 ] ) ) , ) if ( s [ 0 ] <= s [ 1 ] ) else ( ( Real ( s [ 1 ] [ 0 ] ) , Real ( s [ 1 ] [ 1 ] ) ) , ( Real ( s [ 0 ] [ 0 ] ) , Real ( s [ 0 ] [ 1 ] ) ) , ) for s in segments ]
n = len ( segments )
for i in range ( n ) :
    a0 , a1 = segments [ i ]
    for j in range ( i + 1 , n ) :
        b0 , b1 = segments [ j ]
        if a0 not in ( b0 , b1 ) and a1 not in ( b0 , b1 ) :
            ix = isect_seg_seg_v2_point ( a0 , a1 , b0 , b1 )
            if ix is not None : # USE _ IGNORE _ SEGMENT _ ENDINGS handled already
                isect . append ( ix )
return isect


signature:
def isect_polygon__naive ( points ) :
    """Brute force O ( n2 ) version of ` ` isect _ polygon ` ` for test validation ."""

implementation:
isect = [ ]
n = len ( points )
if Real is float :
    pass
else :
    points = [ ( Real ( p [ 0 ] ) , Real ( p [ 1 ] ) ) for p in points ]
for i in range ( n ) :
    a0 , a1 = points [ i ] , points [ ( i + 1 ) % n ]
    for j in range ( i + 1 , n ) :
        b0 , b1 = points [ j ] , points [ ( j + 1 ) % n ]
        if a0 not in ( b0 , b1 ) and a1 not in ( b0 , b1 ) :
            ix = isect_seg_seg_v2_point ( a0 , a1 , b0 , b1 )
            if ix is not None :
                if USE_IGNORE_SEGMENT_ENDINGS :
                    if ( ( len_squared_v2v2 ( ix , a0 ) < NUM_EPS_SQ or len_squared_v2v2 ( ix , a1 ) < NUM_EPS_SQ ) and ( len_squared_v2v2 ( ix , b0 ) < NUM_EPS_SQ or len_squared_v2v2 ( ix , b1 ) < NUM_EPS_SQ ) ) :
                        continue
                isect . append ( ix )
return isect


signature:
def get_intersections ( self ) :
    """Return a list of unordered intersection points ."""

implementation:
if Real is float :
    return list ( self . intersections . keys ( ) )
else :
    return [ ( float ( p [ 0 ] ) , float ( p [ 1 ] ) ) for p in self . intersections . keys ( ) ]


signature:
def get_intersections_with_segments ( self ) :
    """Return a list of unordered intersection ' ( point , segment ) ' pairs ,
 where segments may contain 2 or more values ."""

implementation:
if Real is float :
    return [ ( p , [ event . segment for event in event_set ] ) for p , event_set in self . intersections . items ( ) ]
else :
    return [ ( ( float ( p [ 0 ] ) , float ( p [ 1 ] ) ) , [ ( ( float ( event . segment [ 0 ] [ 0 ] ) , float ( event . segment [ 0 ] [ 1 ] ) ) , ( float ( event . segment [ 1 ] [ 0 ] ) , float ( event . segment [ 1 ] [ 1 ] ) ) ) for event in event_set ] , ) for p , event_set in self . intersections . items ( ) ]


signature:
def poll ( self ) :
    """Get , and remove , the first ( lowest ) item from this queue .
 : return : the first ( lowest ) item from this queue .
 : rtype : Point , Event pair ."""

implementation:
assert ( len ( self . events_scan ) != 0 )
p , events_current = self . events_scan . pop_min ( )
return p , events_current


signature:
def clear ( self ) :
    """T . clear ( ) - > None . Remove all items from T ."""

implementation:
def _clear ( node ) :
    if node is not None :
        _clear ( node . left )
        _clear ( node . right )
        node . free ( )
_clear ( self . _root )
self . _count = 0
self . _root = None


signature:
def pop_item ( self ) :
    """T . pop _ item ( ) - > ( k , v ) , remove and return some ( key , value ) pair as a
 2 - tuple ; but raise KeyError if T is empty ."""

implementation:
if self . is_empty ( ) :
    raise KeyError ( "pop_item(): tree is empty" )
node = self . _root
while True :
    if node . left is not None :
        node = node . left
    elif node . right is not None :
        node = node . right
    else :
        break
key = node . key
value = node . value
self . remove ( key )
return key , value


signature:
def min_item ( self ) :
    """Get item with min key of tree , raises ValueError if tree is empty ."""

implementation:
if self . is_empty ( ) :
    raise ValueError ( "Tree is empty" )
node = self . _root
while node . left is not None :
    node = node . left
return node . key , node . value


signature:
def max_item ( self ) :
    """Get item with max key of tree , raises ValueError if tree is empty ."""

implementation:
if self . is_empty ( ) :
    raise ValueError ( "Tree is empty" )
node = self . _root
while node . right is not None :
    node = node . right
return node . key , node . value


signature:
def succ_item ( self , key , default = _sentinel ) :
    """Get successor ( k , v ) pair of key , raises KeyError if key is max key
 or key does not exist . optimized for pypy ."""

implementation:
# removed graingets version , because it was little slower on CPython and much slower on pypy
# this version runs about 4x faster with pypy than the Cython version
# Note : Code sharing of succ _ item ( ) and ceiling _ item ( ) is possible , but has always a speed penalty .
node = self . _root
succ_node = None
while node is not None :
    cmp = self . _cmp ( self . _cmp_data , key , node . key )
    if cmp == 0 :
        break
    elif cmp < 0 :
        if ( succ_node is None ) or self . _cmp ( self . _cmp_data , node . key , succ_node . key ) < 0 :
            succ_node = node
        node = node . left
    else :
        node = node . right
if node is None : # stay at dead end
    if default is _sentinel :
        raise KeyError ( str ( key ) )
    return default
# found node of key
if node . right is not None : # find smallest node of right subtree
    node = node . right
    while node . left is not None :
        node = node . left
    if succ_node is None :
        succ_node = node
    elif self . _cmp ( self . _cmp_data , node . key , succ_node . key ) < 0 :
        succ_node = node
elif succ_node is None : # given key is biggest in tree
    if default is _sentinel :
        raise KeyError ( str ( key ) )
    return default
return succ_node . key , succ_node . value


signature:
def prev_item ( self , key , default = _sentinel ) :
    """Get predecessor ( k , v ) pair of key , raises KeyError if key is min key
 or key does not exist . optimized for pypy ."""

implementation:
# removed graingets version , because it was little slower on CPython and much slower on pypy
# this version runs about 4x faster with pypy than the Cython version
# Note : Code sharing of prev _ item ( ) and floor _ item ( ) is possible , but has always a speed penalty .
node = self . _root
prev_node = None
while node is not None :
    cmp = self . _cmp ( self . _cmp_data , key , node . key )
    if cmp == 0 :
        break
    elif cmp < 0 :
        node = node . left
    else :
        if ( prev_node is None ) or self . _cmp ( self . _cmp_data , prev_node . key , node . key ) < 0 :
            prev_node = node
        node = node . right
if node is None : # stay at dead end ( None )
    if default is _sentinel :
        raise KeyError ( str ( key ) )
    return default
# found node of key
if node . left is not None : # find biggest node of left subtree
    node = node . left
    while node . right is not None :
        node = node . right
    if prev_node is None :
        prev_node = node
    elif self . _cmp ( self . _cmp_data , prev_node . key , node . key ) < 0 :
        prev_node = node
elif prev_node is None : # given key is smallest in tree
    if default is _sentinel :
        raise KeyError ( str ( key ) )
    return default
return prev_node . key , prev_node . value


signature:
def set_default ( self , key , default = None ) :
    """T . set _ default ( k [ , d ] ) - > T . get ( k , d ) , also set T [ k ] = d if k not in T"""

implementation:
try :
    return self . get_value ( key )
except KeyError :
    self . insert ( key , default )
    return default


signature:
def pop ( self , key , * args ) :
    """T . pop ( k [ , d ] ) - > v , remove specified key and return the corresponding value .
 If key is not found , d is returned if given , otherwise KeyError is raised"""

implementation:
if len ( args ) > 1 :
    raise TypeError ( "pop expected at most 2 arguments, got %d" % ( 1 + len ( args ) ) )
try :
    value = self . get_value ( key )
    self . remove ( key )
    return value
except KeyError :
    if len ( args ) == 0 :
        raise
    else :
        return args [ 0 ]


signature:
def prev_key ( self , key , default = _sentinel ) :
    """Get predecessor to key , raises KeyError if key is min key
 or key does not exist ."""

implementation:
item = self . prev_item ( key , default )
return default if item is default else item [ 0 ]


signature:
def succ_key ( self , key , default = _sentinel ) :
    """Get successor to key , raises KeyError if key is max key
 or key does not exist ."""

implementation:
item = self . succ_item ( key , default )
return default if item is default else item [ 0 ]


signature:
def key_slice ( self , start_key , end_key , reverse = False ) :
    """T . key _ slice ( start _ key , end _ key ) - > key iterator :
 start _ key < = key < end _ key .
 Yields keys in ascending order if reverse is False else in descending order ."""

implementation: return ( k for k , v in self . iter_items ( start_key , end_key , reverse = reverse ) )


signature:
def iter_items ( self , start_key = None , end_key = None , reverse = False ) :
    """Iterates over the ( key , value ) items of the associated tree ,
 in ascending order if reverse is True , iterate in descending order ,
 reverse defaults to False"""

implementation:
# optimized iterator ( reduced method calls ) - faster on CPython but slower on pypy
if self . is_empty ( ) :
    return [ ]
if reverse :
    return self . _iter_items_backward ( start_key , end_key )
else :
    return self . _iter_items_forward ( start_key , end_key )


signature:
def insert ( self , key , value ) :
    """T . insert ( key , value ) < = = > T [ key ] = value , insert key , value into tree ."""

implementation:
if self . _root is None : # Empty tree case
    self . _root = self . _new_node ( key , value )
    self . _root . red = False
    # make root black
    return
head = Node ( )
# False tree root
grand_parent = None
grand_grand_parent = head
parent = None
# parent
direction = 0
last = 0
# Set up helpers
grand_grand_parent . right = self . _root
node = grand_grand_parent . right
# Search down the tree
while True :
    if node is None : # Insert new node at the bottom
        node = self . _new_node ( key , value )
        parent [ direction ] = node
    elif RBTree . is_red ( node . left ) and RBTree . is_red ( node . right ) : # Color flip
        node . red = True
        node . left . red = False
        node . right . red = False
    # Fix red violation
    if RBTree . is_red ( node ) and RBTree . is_red ( parent ) :
        direction2 = 1 if grand_grand_parent . right is grand_parent else 0
        if node is parent [ last ] :
            grand_grand_parent [ direction2 ] = RBTree . jsw_single ( grand_parent , 1 - last )
        else :
            grand_grand_parent [ direction2 ] = RBTree . jsw_double ( grand_parent , 1 - last )
    # Stop if found
    if self . _cmp ( self . _cmp_data , key , node . key ) == 0 :
        node . value = value
        # set new value for key
        break
    last = direction
    direction = 0 if ( self . _cmp ( self . _cmp_data , key , node . key ) < 0 ) else 1
    # Update helpers
    if grand_parent is not None :
        grand_grand_parent = grand_parent
    grand_parent = parent
    parent = node
    node = node [ direction ]
self . _root = head . right
# Update root
self . _root . red = False


signature:
def remove ( self , key ) :
    """T . remove ( key ) < = = > del T [ key ] , remove item < key > from tree ."""

implementation:
if self . _root is None :
    raise KeyError ( str ( key ) )
head = Node ( )
# False tree root
node = head
node . right = self . _root
parent = None
grand_parent = None
found = None
# Found item
direction = 1
# Search and push a red down
while node [ direction ] is not None :
    last = direction
    # Update helpers
    grand_parent = parent
    parent = node
    node = node [ direction ]
    direction = 1 if ( self . _cmp ( self . _cmp_data , node . key , key ) < 0 ) else 0
    # Save found node
    if self . _cmp ( self . _cmp_data , key , node . key ) == 0 :
        found = node
    # Push the red node down
    if not RBTree . is_red ( node ) and not RBTree . is_red ( node [ direction ] ) :
        if RBTree . is_red ( node [ 1 - direction ] ) :
            parent [ last ] = RBTree . jsw_single ( node , direction )
            parent = parent [ last ]
        elif not RBTree . is_red ( node [ 1 - direction ] ) :
            sibling = parent [ 1 - last ]
            if sibling is not None :
                if ( not RBTree . is_red ( sibling [ 1 - last ] ) ) and ( not RBTree . is_red ( sibling [ last ] ) ) : # Color flip
                    parent . red = False
                    sibling . red = True
                    node . red = True
                else :
                    direction2 = 1 if grand_parent . right is parent else 0
                    if RBTree . is_red ( sibling [ last ] ) :
                        grand_parent [ direction2 ] = RBTree . jsw_double ( parent , last )
                    elif RBTree . is_red ( sibling [ 1 - last ] ) :
                        grand_parent [ direction2 ] = RBTree . jsw_single ( parent , last )
                    # Ensure correct coloring
                    grand_parent [ direction2 ] . red = True
                    node . red = True
                    grand_parent [ direction2 ] . left . red = False
                    grand_parent [ direction2 ] . right . red = False
# Replace and remove if found
if found is not None :
    found . key = node . key
    found . value = node . value
    parent [ int ( parent . right is node ) ] = node [ int ( node . left is None ) ]
    node . free ( )
    self . _count -= 1
# Update root and make it black
self . _root = head . right
if self . _root is not None :
    self . _root . red = False
if not found :
    raise KeyError ( str ( key ) )


signature:
def noise2d ( self , x , y ) :
    """Generate 2D OpenSimplex noise from X , Y coordinates ."""

implementation:
# Place input coordinates onto grid .
stretch_offset = ( x + y ) * STRETCH_CONSTANT_2D
xs = x + stretch_offset
ys = y + stretch_offset
# Floor to get grid coordinates of rhombus ( stretched square ) super - cell origin .
xsb = floor ( xs )
ysb = floor ( ys )
# Skew out to get actual coordinates of rhombus origin . We ' ll need these later .
squish_offset = ( xsb + ysb ) * SQUISH_CONSTANT_2D
xb = xsb + squish_offset
yb = ysb + squish_offset
# Compute grid coordinates relative to rhombus origin .
xins = xs - xsb
yins = ys - ysb
# Sum those together to get a value that determines which region we ' re in .
in_sum = xins + yins
# Positions relative to origin point .
dx0 = x - xb
dy0 = y - yb
value = 0
# Contribution ( 1,0)
dx1 = dx0 - 1 - SQUISH_CONSTANT_2D
dy1 = dy0 - 0 - SQUISH_CONSTANT_2D
attn1 = 2 - dx1 * dx1 - dy1 * dy1
extrapolate = self . _extrapolate2d
if attn1 > 0 :
    attn1 *= attn1
    value += attn1 * attn1 * extrapolate ( xsb + 1 , ysb + 0 , dx1 , dy1 )
# Contribution ( 0,1)
dx2 = dx0 - 0 - SQUISH_CONSTANT_2D
dy2 = dy0 - 1 - SQUISH_CONSTANT_2D
attn2 = 2 - dx2 * dx2 - dy2 * dy2
if attn2 > 0 :
    attn2 *= attn2
    value += attn2 * attn2 * extrapolate ( xsb + 0 , ysb + 1 , dx2 , dy2 )
if in_sum <= 1 : # We ' re inside the triangle ( 2 - Simplex ) at ( 0,0)
    zins = 1 - in_sum
    if zins > xins or zins > yins : # (0,0 ) is one of the closest two triangular vertices
        if xins > yins :
            xsv_ext = xsb + 1
            ysv_ext = ysb - 1
            dx_ext = dx0 - 1
            dy_ext = dy0 + 1
        else :
            xsv_ext = xsb - 1
            ysv_ext = ysb + 1
            dx_ext = dx0 + 1
            dy_ext = dy0 - 1
    else : # (1,0 ) and ( 0,1 ) are the closest two vertices .
        xsv_ext = xsb + 1
        ysv_ext = ysb + 1
        dx_ext = dx0 - 1 - 2 * SQUISH_CONSTANT_2D
        dy_ext = dy0 - 1 - 2 * SQUISH_CONSTANT_2D
else : # We ' re inside the triangle ( 2 - Simplex ) at ( 1,1)
    zins = 2 - in_sum
    if zins < xins or zins < yins : # (0,0 ) is one of the closest two triangular vertices
        if xins > yins :
            xsv_ext = xsb + 2
            ysv_ext = ysb + 0
            dx_ext = dx0 - 2 - 2 * SQUISH_CONSTANT_2D
            dy_ext = dy0 + 0 - 2 * SQUISH_CONSTANT_2D
        else :
            xsv_ext = xsb + 0
            ysv_ext = ysb + 2
            dx_ext = dx0 + 0 - 2 * SQUISH_CONSTANT_2D
            dy_ext = dy0 - 2 - 2 * SQUISH_CONSTANT_2D
    else : # (1,0 ) and ( 0,1 ) are the closest two vertices .
        dx_ext = dx0
        dy_ext = dy0
        xsv_ext = xsb
        ysv_ext = ysb
    xsb += 1
    ysb += 1
    dx0 = dx0 - 1 - 2 * SQUISH_CONSTANT_2D
    dy0 = dy0 - 1 - 2 * SQUISH_CONSTANT_2D
# Contribution ( 0,0 ) or ( 1,1)
attn0 = 2 - dx0 * dx0 - dy0 * dy0
if attn0 > 0 :
    attn0 *= attn0
    value += attn0 * attn0 * extrapolate ( xsb , ysb , dx0 , dy0 )
# Extra Vertex
attn_ext = 2 - dx_ext * dx_ext - dy_ext * dy_ext
if attn_ext > 0 :
    attn_ext *= attn_ext
    value += attn_ext * attn_ext * extrapolate ( xsv_ext , ysv_ext , dx_ext , dy_ext )
return value / NORM_CONSTANT_2D


signature:
def noise3d ( self , x , y , z ) :
    """Generate 3D OpenSimplex noise from X , Y , Z coordinates ."""

implementation:
# Place input coordinates on simplectic honeycomb .
stretch_offset = ( x + y + z ) * STRETCH_CONSTANT_3D
xs = x + stretch_offset
ys = y + stretch_offset
zs = z + stretch_offset
# Floor to get simplectic honeycomb coordinates of rhombohedron ( stretched cube ) super - cell origin .
xsb = floor ( xs )
ysb = floor ( ys )
zsb = floor ( zs )
# Skew out to get actual coordinates of rhombohedron origin . We ' ll need these later .
squish_offset = ( xsb + ysb + zsb ) * SQUISH_CONSTANT_3D
xb = xsb + squish_offset
yb = ysb + squish_offset
zb = zsb + squish_offset
# Compute simplectic honeycomb coordinates relative to rhombohedral origin .
xins = xs - xsb
yins = ys - ysb
zins = zs - zsb
# Sum those together to get a value that determines which region we ' re in .
in_sum = xins + yins + zins
# Positions relative to origin point .
dx0 = x - xb
dy0 = y - yb
dz0 = z - zb
value = 0
extrapolate = self . _extrapolate3d
if in_sum <= 1 : # We ' re inside the tetrahedron ( 3 - Simplex ) at ( 0,0,0)
# Determine which two of ( 0,0,1 ) , ( 0,1,0 ) , ( 1,0,0 ) are closest .
    a_point = 0x01
    a_score = xins
    b_point = 0x02
    b_score = yins
    if a_score >= b_score and zins > b_score :
        b_score = zins
        b_point = 0x04
    elif a_score < b_score and zins > a_score :
        a_score = zins
        a_point = 0x04
    # Now we determine the two lattice points not part of the tetrahedron that may contribute .
    # This depends on the closest two tetrahedral vertices , including ( 0,0,0)
    wins = 1 - in_sum
    if wins > a_score or wins > b_score : # (0,0,0 ) is one of the closest two tetrahedral vertices .
        c = b_point if ( b_score > a_score ) else a_point
        # Our other closest vertex is the closest out of a and b .
        if ( c & 0x01 ) == 0 :
            xsv_ext0 = xsb - 1
            xsv_ext1 = xsb
            dx_ext0 = dx0 + 1
            dx_ext1 = dx0
        else :
            xsv_ext0 = xsv_ext1 = xsb + 1
            dx_ext0 = dx_ext1 = dx0 - 1
        if ( c & 0x02 ) == 0 :
            ysv_ext0 = ysv_ext1 = ysb
            dy_ext0 = dy_ext1 = dy0
            if ( c & 0x01 ) == 0 :
                ysv_ext1 -= 1
                dy_ext1 += 1
            else :
                ysv_ext0 -= 1
                dy_ext0 += 1
        else :
            ysv_ext0 = ysv_ext1 = ysb + 1
            dy_ext0 = dy_ext1 = dy0 - 1
        if ( c & 0x04 ) == 0 :
            zsv_ext0 = zsb
            zsv_ext1 = zsb - 1
            dz_ext0 = dz0
            dz_ext1 = dz0 + 1
        else :
            zsv_ext0 = zsv_ext1 = zsb + 1
            dz_ext0 = dz_ext1 = dz0 - 1
    else : # (0,0,0 ) is not one of the closest two tetrahedral vertices .
        c = ( a_point | b_point )
        # Our two extra vertices are determined by the closest two .
        if ( c & 0x01 ) == 0 :
            xsv_ext0 = xsb
            xsv_ext1 = xsb - 1
            dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_3D
            dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_3D
        else :
            xsv_ext0 = xsv_ext1 = xsb + 1
            dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D
            dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D
        if ( c & 0x02 ) == 0 :
            ysv_ext0 = ysb
            ysv_ext1 = ysb - 1
            dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_3D
            dy_ext1 = dy0 + 1 - SQUISH_CONSTANT_3D
        else :
            ysv_ext0 = ysv_ext1 = ysb + 1
            dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D
            dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D
        if ( c & 0x04 ) == 0 :
            zsv_ext0 = zsb
            zsv_ext1 = zsb - 1
            dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_3D
            dz_ext1 = dz0 + 1 - SQUISH_CONSTANT_3D
        else :
            zsv_ext0 = zsv_ext1 = zsb + 1
            dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D
            dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D
    # Contribution ( 0,0,0)
    attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0
    if attn0 > 0 :
        attn0 *= attn0
        value += attn0 * attn0 * extrapolate ( xsb + 0 , ysb + 0 , zsb + 0 , dx0 , dy0 , dz0 )
    # Contribution ( 1,0,0)
    dx1 = dx0 - 1 - SQUISH_CONSTANT_3D
    dy1 = dy0 - 0 - SQUISH_CONSTANT_3D
    dz1 = dz0 - 0 - SQUISH_CONSTANT_3D
    attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1
    if attn1 > 0 :
        attn1 *= attn1
        value += attn1 * attn1 * extrapolate ( xsb + 1 , ysb + 0 , zsb + 0 , dx1 , dy1 , dz1 )
    # Contribution ( 0,1,0)
    dx2 = dx0 - 0 - SQUISH_CONSTANT_3D
    dy2 = dy0 - 1 - SQUISH_CONSTANT_3D
    dz2 = dz1
    attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2
    if attn2 > 0 :
        attn2 *= attn2
        value += attn2 * attn2 * extrapolate ( xsb + 0 , ysb + 1 , zsb + 0 , dx2 , dy2 , dz2 )
    # Contribution ( 0,0,1)
    dx3 = dx2
    dy3 = dy1
    dz3 = dz0 - 1 - SQUISH_CONSTANT_3D
    attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3
    if attn3 > 0 :
        attn3 *= attn3
        value += attn3 * attn3 * extrapolate ( xsb + 0 , ysb + 0 , zsb + 1 , dx3 , dy3 , dz3 )
elif in_sum >= 2 : # We ' re inside the tetrahedron ( 3 - Simplex ) at ( 1,1,1)
# Determine which two tetrahedral vertices are the closest , out of ( 1,1,0 ) , ( 1,0,1 ) , ( 0,1,1 ) but not ( 1,1,1 ) .
    a_point = 0x06
    a_score = xins
    b_point = 0x05
    b_score = yins
    if a_score <= b_score and zins < b_score :
        b_score = zins
        b_point = 0x03
    elif a_score > b_score and zins < a_score :
        a_score = zins
        a_point = 0x03
    # Now we determine the two lattice points not part of the tetrahedron that may contribute .
    # This depends on the closest two tetrahedral vertices , including ( 1,1,1)
    wins = 3 - in_sum
    if wins < a_score or wins < b_score : # (1,1,1 ) is one of the closest two tetrahedral vertices .
        c = b_point if ( b_score < a_score ) else a_point
        # Our other closest vertex is the closest out of a and b .
        if ( c & 0x01 ) != 0 :
            xsv_ext0 = xsb + 2
            xsv_ext1 = xsb + 1
            dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_3D
            dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D
        else :
            xsv_ext0 = xsv_ext1 = xsb
            dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_3D
        if ( c & 0x02 ) != 0 :
            ysv_ext0 = ysv_ext1 = ysb + 1
            dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D
            if ( c & 0x01 ) != 0 :
                ysv_ext1 += 1
                dy_ext1 -= 1
            else :
                ysv_ext0 += 1
                dy_ext0 -= 1
        else :
            ysv_ext0 = ysv_ext1 = ysb
            dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_3D
        if ( c & 0x04 ) != 0 :
            zsv_ext0 = zsb + 1
            zsv_ext1 = zsb + 2
            dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D
            dz_ext1 = dz0 - 2 - 3 * SQUISH_CONSTANT_3D
        else :
            zsv_ext0 = zsv_ext1 = zsb
            dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_3D
    else : # (1,1,1 ) is not one of the closest two tetrahedral vertices .
        c = ( a_point & b_point )
        # Our two extra vertices are determined by the closest two .
        if ( c & 0x01 ) != 0 :
            xsv_ext0 = xsb + 1
            xsv_ext1 = xsb + 2
            dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D
            dx_ext1 = dx0 - 2 - 2 * SQUISH_CONSTANT_3D
        else :
            xsv_ext0 = xsv_ext1 = xsb
            dx_ext0 = dx0 - SQUISH_CONSTANT_3D
            dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D
        if ( c & 0x02 ) != 0 :
            ysv_ext0 = ysb + 1
            ysv_ext1 = ysb + 2
            dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D
            dy_ext1 = dy0 - 2 - 2 * SQUISH_CONSTANT_3D
        else :
            ysv_ext0 = ysv_ext1 = ysb
            dy_ext0 = dy0 - SQUISH_CONSTANT_3D
            dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D
        if ( c & 0x04 ) != 0 :
            zsv_ext0 = zsb + 1
            zsv_ext1 = zsb + 2
            dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D
            dz_ext1 = dz0 - 2 - 2 * SQUISH_CONSTANT_3D
        else :
            zsv_ext0 = zsv_ext1 = zsb
            dz_ext0 = dz0 - SQUISH_CONSTANT_3D
            dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D
    # Contribution ( 1,1,0)
    dx3 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D
    dy3 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D
    dz3 = dz0 - 0 - 2 * SQUISH_CONSTANT_3D
    attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3
    if attn3 > 0 :
        attn3 *= attn3
        value += attn3 * attn3 * extrapolate ( xsb + 1 , ysb + 1 , zsb + 0 , dx3 , dy3 , dz3 )
    # Contribution ( 1,0,1)
    dx2 = dx3
    dy2 = dy0 - 0 - 2 * SQUISH_CONSTANT_3D
    dz2 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D
    attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2
    if attn2 > 0 :
        attn2 *= attn2
        value += attn2 * attn2 * extrapolate ( xsb + 1 , ysb + 0 , zsb + 1 , dx2 , dy2 , dz2 )
    # Contribution ( 0,1,1)
    dx1 = dx0 - 0 - 2 * SQUISH_CONSTANT_3D
    dy1 = dy3
    dz1 = dz2
    attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1
    if attn1 > 0 :
        attn1 *= attn1
        value += attn1 * attn1 * extrapolate ( xsb + 0 , ysb + 1 , zsb + 1 , dx1 , dy1 , dz1 )
    # Contribution ( 1,1,1)
    dx0 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D
    dy0 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D
    dz0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D
    attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0
    if attn0 > 0 :
        attn0 *= attn0
        value += attn0 * attn0 * extrapolate ( xsb + 1 , ysb + 1 , zsb + 1 , dx0 , dy0 , dz0 )
else : # We ' re inside the octahedron ( Rectified 3 - Simplex ) in between .
# Decide between point ( 0,0,1 ) and ( 1,1,0 ) as closest
    p1 = xins + yins
    if p1 > 1 :
        a_score = p1 - 1
        a_point = 0x03
        a_is_further_side = True
    else :
        a_score = 1 - p1
        a_point = 0x04
        a_is_further_side = False
    # Decide between point ( 0,1,0 ) and ( 1,0,1 ) as closest
    p2 = xins + zins
    if p2 > 1 :
        b_score = p2 - 1
        b_point = 0x05
        b_is_further_side = True
    else :
        b_score = 1 - p2
        b_point = 0x02
        b_is_further_side = False
    # The closest out of the two ( 1,0,0 ) and ( 0,1,1 ) will replace the furthest out of the two decided above , if closer .
    p3 = yins + zins
    if p3 > 1 :
        score = p3 - 1
        if a_score <= b_score and a_score < score :
            a_point = 0x06
            a_is_further_side = True
        elif a_score > b_score and b_score < score :
            b_point = 0x06
            b_is_further_side = True
    else :
        score = 1 - p3
        if a_score <= b_score and a_score < score :
            a_point = 0x01
            a_is_further_side = False
        elif a_score > b_score and b_score < score :
            b_point = 0x01
            b_is_further_side = False
    # Where each of the two closest points are determines how the extra two vertices are calculated .
    if a_is_further_side == b_is_further_side :
        if a_is_further_side : # Both closest points on ( 1,1,1 ) side
        # One of the two extra points is ( 1,1,1)
            dx_ext0 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D
            dy_ext0 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D
            dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D
            xsv_ext0 = xsb + 1
            ysv_ext0 = ysb + 1
            zsv_ext0 = zsb + 1
            # Other extra point is based on the shared axis .
            c = ( a_point & b_point )
            if ( c & 0x01 ) != 0 :
                dx_ext1 = dx0 - 2 - 2 * SQUISH_CONSTANT_3D
                dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D
                dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D
                xsv_ext1 = xsb + 2
                ysv_ext1 = ysb
                zsv_ext1 = zsb
            elif ( c & 0x02 ) != 0 :
                dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D
                dy_ext1 = dy0 - 2 - 2 * SQUISH_CONSTANT_3D
                dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D
                xsv_ext1 = xsb
                ysv_ext1 = ysb + 2
                zsv_ext1 = zsb
            else :
                dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D
                dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D
                dz_ext1 = dz0 - 2 - 2 * SQUISH_CONSTANT_3D
                xsv_ext1 = xsb
                ysv_ext1 = ysb
                zsv_ext1 = zsb + 2
        else : # Both closest points on ( 0,0,0 ) side
        # One of the two extra points is ( 0,0,0)
            dx_ext0 = dx0
            dy_ext0 = dy0
            dz_ext0 = dz0
            xsv_ext0 = xsb
            ysv_ext0 = ysb
            zsv_ext0 = zsb
            # Other extra point is based on the omitted axis .
            c = ( a_point | b_point )
            if ( c & 0x01 ) == 0 :
                dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_3D
                dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D
                dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D
                xsv_ext1 = xsb - 1
                ysv_ext1 = ysb + 1
                zsv_ext1 = zsb + 1
            elif ( c & 0x02 ) == 0 :
                dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D
                dy_ext1 = dy0 + 1 - SQUISH_CONSTANT_3D
                dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D
                xsv_ext1 = xsb + 1
                ysv_ext1 = ysb - 1
                zsv_ext1 = zsb + 1
            else :
                dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D
                dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D
                dz_ext1 = dz0 + 1 - SQUISH_CONSTANT_3D
                xsv_ext1 = xsb + 1
                ysv_ext1 = ysb + 1
                zsv_ext1 = zsb - 1
    else : # One point on ( 0,0,0 ) side , one point on ( 1,1,1 ) side
        if a_is_further_side :
            c1 = a_point
            c2 = b_point
        else :
            c1 = b_point
            c2 = a_point
        # One contribution is a _ permutation of ( 1,1 , - 1)
        if ( c1 & 0x01 ) == 0 :
            dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_3D
            dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D
            dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D
            xsv_ext0 = xsb - 1
            ysv_ext0 = ysb + 1
            zsv_ext0 = zsb + 1
        elif ( c1 & 0x02 ) == 0 :
            dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D
            dy_ext0 = dy0 + 1 - SQUISH_CONSTANT_3D
            dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D
            xsv_ext0 = xsb + 1
            ysv_ext0 = ysb - 1
            zsv_ext0 = zsb + 1
        else :
            dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D
            dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D
            dz_ext0 = dz0 + 1 - SQUISH_CONSTANT_3D
            xsv_ext0 = xsb + 1
            ysv_ext0 = ysb + 1
            zsv_ext0 = zsb - 1
        # One contribution is a _ permutation of ( 0,0,2)
        dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D
        dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D
        dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D
        xsv_ext1 = xsb
        ysv_ext1 = ysb
        zsv_ext1 = zsb
        if ( c2 & 0x01 ) != 0 :
            dx_ext1 -= 2
            xsv_ext1 += 2
        elif ( c2 & 0x02 ) != 0 :
            dy_ext1 -= 2
            ysv_ext1 += 2
        else :
            dz_ext1 -= 2
            zsv_ext1 += 2
    # Contribution ( 1,0,0)
    dx1 = dx0 - 1 - SQUISH_CONSTANT_3D
    dy1 = dy0 - 0 - SQUISH_CONSTANT_3D
    dz1 = dz0 - 0 - SQUISH_CONSTANT_3D
    attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1
    if attn1 > 0 :
        attn1 *= attn1
        value += attn1 * attn1 * extrapolate ( xsb + 1 , ysb + 0 , zsb + 0 , dx1 , dy1 , dz1 )
    # Contribution ( 0,1,0)
    dx2 = dx0 - 0 - SQUISH_CONSTANT_3D
    dy2 = dy0 - 1 - SQUISH_CONSTANT_3D
    dz2 = dz1
    attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2
    if attn2 > 0 :
        attn2 *= attn2
        value += attn2 * attn2 * extrapolate ( xsb + 0 , ysb + 1 , zsb + 0 , dx2 , dy2 , dz2 )
    # Contribution ( 0,0,1)
    dx3 = dx2
    dy3 = dy1
    dz3 = dz0 - 1 - SQUISH_CONSTANT_3D
    attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3
    if attn3 > 0 :
        attn3 *= attn3
        value += attn3 * attn3 * extrapolate ( xsb + 0 , ysb + 0 , zsb + 1 , dx3 , dy3 , dz3 )
    # Contribution ( 1,1,0)
    dx4 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D
    dy4 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D
    dz4 = dz0 - 0 - 2 * SQUISH_CONSTANT_3D
    attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4
    if attn4 > 0 :
        attn4 *= attn4
        value += attn4 * attn4 * extrapolate ( xsb + 1 , ysb + 1 , zsb + 0 , dx4 , dy4 , dz4 )
    # Contribution ( 1,0,1)
    dx5 = dx4
    dy5 = dy0 - 0 - 2 * SQUISH_CONSTANT_3D
    dz5 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D
    attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5
    if attn5 > 0 :
        attn5 *= attn5
        value += attn5 * attn5 * extrapolate ( xsb + 1 , ysb + 0 , zsb + 1 , dx5 , dy5 , dz5 )
    # Contribution ( 0,1,1)
    dx6 = dx0 - 0 - 2 * SQUISH_CONSTANT_3D
    dy6 = dy4
    dz6 = dz5
    attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6
    if attn6 > 0 :
        attn6 *= attn6
        value += attn6 * attn6 * extrapolate ( xsb + 0 , ysb + 1 , zsb + 1 , dx6 , dy6 , dz6 )
# First extra vertex
attn_ext0 = 2 - dx_ext0 * dx_ext0 - dy_ext0 * dy_ext0 - dz_ext0 * dz_ext0
if attn_ext0 > 0 :
    attn_ext0 *= attn_ext0
    value += attn_ext0 * attn_ext0 * extrapolate ( xsv_ext0 , ysv_ext0 , zsv_ext0 , dx_ext0 , dy_ext0 , dz_ext0 )
# Second extra vertex
attn_ext1 = 2 - dx_ext1 * dx_ext1 - dy_ext1 * dy_ext1 - dz_ext1 * dz_ext1
if attn_ext1 > 0 :
    attn_ext1 *= attn_ext1
    value += attn_ext1 * attn_ext1 * extrapolate ( xsv_ext1 , ysv_ext1 , zsv_ext1 , dx_ext1 , dy_ext1 , dz_ext1 )
return value / NORM_CONSTANT_3D