Exemplo n.º 1
0
def as_box(quadrant):
    """"Convert a quadrant of the form: ((x_min,y_min),width) to a box: ((x_min,y_min),(x_max,y_max))."""
    width = quadrant[1]
    minp = quadrant[0]
    maxp = tuple(xy + width for xy in minp)
    assert (x(minp) <= x(maxp) and y(minp) <= y(maxp))
    return (minp, maxp)
Exemplo n.º 2
0
def as_box( quadrant ):
    """"Convert a quadrant of the form: ((x_min,y_min),width) to a box: ((x_min,y_min),(x_max,y_max))."""
    width = quadrant[1]
    minp = quadrant[0]
    maxp = tuple(xy+width for xy in minp)
    assert( x(minp) <= x(maxp) and y(minp) <= y(maxp) )
    return (minp,maxp)
Exemplo n.º 3
0
def bounds(vertices):
    """Return the iso-axis rectangle enclosing the given points"""
    # find vertices set bounds
    xmin = x(vertices[0])
    ymin = y(vertices[0])
    xmax = xmin
    ymax = ymin

    # we do not use min(vertices,key=x) because it would iterate 4 times over the list, instead of just one
    for v in vertices:
        xmin = min(x(v), xmin)
        xmax = max(x(v), xmax)
        ymin = min(y(v), ymin)
        ymax = max(y(v), ymax)
    return (xmin, ymin), (xmax, ymax)
Exemplo n.º 4
0
def bounds( vertices ):
    """Return the iso-axis rectangle enclosing the given points"""
    # find vertices set bounds
    xmin = x(vertices[0])
    ymin = y(vertices[0])
    xmax = xmin
    ymax = ymin

    # we do not use min(vertices,key=x) because it would iterate 4 times over the list, instead of just one
    for v in vertices:
        xmin = min(x(v),xmin)
        xmax = max(x(v),xmax)
        ymin = min(y(v),ymin)
        ymax = max(y(v),ymax)
    return (xmin,ymin),(xmax,ymax)
Exemplo n.º 5
0
    def init(self, quadrant=None, box=None, points=None):
        """Initialize the root quadrant with the given quadrant, the given box or the given set of points."""

        if len([k for k in (box, points, quadrant) if k]) > 1:
            raise BaseException(
                "ERROR: you should specify a box, a quadrant or points")

        # Initialize the root quadrant as the given box
        if box:
            minp, maxp = box
            width = max(x(maxp) - x(minp), y(maxp) - y(minp))

        # Initialize the root quadrant as the box around the points
        elif points:
            minp, maxp = geometry.box(points)
            width = max(x(maxp) - x(minp), y(maxp) - y(minp))

        # Initialize the root quadrant as the given origin point and width
        elif quadrant:
            minp = quadrant[0]
            width = quadrant[1]

        assert (x(minp) <= x(minp) + width and y(minp) <= y(minp) + width)

        # There is always the root quadrant in the list of available ones.
        root = (minp, width)
        quadrants = [root]

        return root, quadrants
Exemplo n.º 6
0
    def init( self, quadrant = None, box = None, points = None ):
        """Initialize the root quadrant with the given quadrant, the given box or the given set of points."""

        if len([k for k in (box,points,quadrant) if k]) > 1:
            raise BaseException("ERROR: you should specify a box, a quadrant or points")

        # Initialize the root quadrant as the given box
        if box:
            minp,maxp = box
            width = max( x(maxp)-x(minp), y(maxp)-y(minp) )

        # Initialize the root quadrant as the box around the points
        elif points:
            minp,maxp = geometry.box( points )
            width = max( x(maxp)-x(minp), y(maxp)-y(minp) )

        # Initialize the root quadrant as the given origin point and width
        elif quadrant:
            minp = quadrant[0]
            width = quadrant[1]

        assert( x(minp) <= x(minp)+width and y(minp) <= y(minp)+width )

        # There is always the root quadrant in the list of available ones.
        root = (minp,width)
        quadrants = [ root ]

        return root,quadrants
Exemplo n.º 7
0
def in_circle(p, center, radius, epsilon=sys.float_info.epsilon):
    """Return True if the given point p is in the given circle"""

    assert (len(p) == 2)
    cx, cy = center

    dxp = x(p) - cx
    dyp = y(p) - cy
    dr = math.sqrt(dxp**2 + dyp**2)

    if (dr - radius) <= epsilon:
        return True
    else:
        return False
Exemplo n.º 8
0
def in_circle( p, center, radius, epsilon  = sys.float_info.epsilon ):
    """Return True if the given point p is in the given circle"""

    assert( len(p) == 2 )
    cx,cy = center

    dxp = x(p) - cx
    dyp = y(p) - cy
    dr = math.sqrt(dxp**2 + dyp**2)

    if (dr - radius) <= epsilon:
        return True
    else:
        return False
Exemplo n.º 9
0
def circumcircle(triangle, epsilon=sys.float_info.epsilon):
    """Compute the circumscribed circle of a triangle and 
    Return a 2-tuple: ( (center_x, center_y), radius )"""

    assert (len(triangle) == 3)
    p0, p1, p2 = triangle
    assert (len(p0) == 2)
    assert (len(p1) == 2)
    assert (len(p2) == 2)

    dy01 = abs(y(p0) - y(p1))
    dy12 = abs(y(p1) - y(p2))

    if dy01 < epsilon and dy12 < epsilon:
        # coincident points
        raise CoincidentPointsError

    elif dy01 < epsilon:
        m12 = mtan(p2, p1)
        mx12, my12 = middle(p1, p2)
        cx = mid(x, p1, p0)
        cy = m12 * (cx - mx12) + my12

    elif dy12 < epsilon:
        m01 = mtan(p1, p0)
        mx01, my01 = middle(p0, p1)
        cx = mid(x, p2, p1)
        cy = m01 * (cx - mx01) + my01

    else:
        m01 = mtan(p1, p0)
        m12 = mtan(p2, p1)
        mx01, my01 = middle(p0, p1)
        mx12, my12 = middle(p1, p2)
        cx = (m01 * mx01 - m12 * mx12 + my12 - my01) / (m01 - m12)
        if dy01 > dy12:
            cy = m01 * (cx - mx01) + my01
        else:
            cy = m12 * (cx - mx12) + my12

    dx1 = x(p1) - cx
    dy1 = y(p1) - cy
    r = math.sqrt(dx1**2 + dy1**2)

    return (cx, cy), r
Exemplo n.º 10
0
def circumcircle( triangle, epsilon = sys.float_info.epsilon ):
    """Compute the circumscribed circle of a triangle and 
    Return a 2-tuple: ( (center_x, center_y), radius )"""

    assert( len(triangle) == 3 )
    p0,p1,p2 = triangle
    assert( len(p0) == 2 )
    assert( len(p1) == 2 )
    assert( len(p2) == 2 )

    dy01 = abs( y(p0) - y(p1) )
    dy12 = abs( y(p1) - y(p2) )

    if dy01 < epsilon and dy12 < epsilon:
        # coincident points
        raise CoincidentPointsError

    elif dy01 < epsilon:
        m12 = mtan( p2,p1 )
        mx12,my12 = middle( p1, p2 )
        cx = mid( x, p1, p0 )
        cy = m12 * (cx - mx12) + my12

    elif dy12 < epsilon:
        m01 = mtan( p1, p0 )
        mx01,my01 = middle( p0, p1 )
        cx = mid( x, p2, p1 )
        cy = m01 * ( cx - mx01 ) + my01

    else:
        m01 =  mtan( p1, p0 )
        m12 =  mtan( p2, p1 )
        mx01,my01 = middle( p0, p1 )
        mx12,my12 = middle( p1, p2 )
        cx = ( m01 * mx01 - m12 * mx12 + my12 - my01 ) / ( m01 - m12 )
        if dy01 > dy12:
            cy = m01 * ( cx - mx01 ) + my01
        else:
            cy = m12 * ( cx - mx12 ) + my12

    dx1 = x(p1) - cx
    dy1 = y(p1) - cy
    r = math.sqrt(dx1**2 + dy1**2)

    return (cx,cy),r
Exemplo n.º 11
0
def write( graph, stream ):
    for k in graph:
        stream.write( "%f,%f:" % (x(k),y(k)) )
        for p in graph[k]:
            stream.write( "%f,%f " % (x(p),y(p)) )
        stream.write("\n")
Exemplo n.º 12
0
def write_points( points, stream ):
    for p in points:
        stream.write( "%f,%f\n" % ( x(p),y(p) ) )
Exemplo n.º 13
0
def write_segments( segments, stream ):
    for seg in segments:
        for p in seg:
            stream.write( "%f,%f " % ( x(p),y(p) ) )
        stream.write( "\n" )
Exemplo n.º 14
0
def turn(p, q, r):
    """Returns -1, 0, 1 if the sequence of points (p,q,r) forms a right, straight, or left turn."""
    qr = (x(q) - x(p)) * (y(r) - y(p))
    rq = (x(r) - x(p)) * (y(q) - y(p))
    # cmp(x,y) returns -1 if x<y, 0 if x==y, +1 if x>y
    return cmp(qr - rq, 0)
Exemplo n.º 15
0
def write_points(points, stream):
    for p in points:
        stream.write("%f,%f\n" % (x(p), y(p)))
Exemplo n.º 16
0
def mtan( pa, pb ):
    return -1 * ( x(pa) - x(pb) ) / ( y(pa) - y(pb) )
Exemplo n.º 17
0
def delaunay_bowyer_watson(points,
                           supertri=None,
                           superdelta=0.1,
                           epsilon=sys.float_info.epsilon,
                           do_plot=None,
                           plot_filename="Bowyer-Watson_%i.png"):
    """Return the Delaunay triangulation of the given points

    epsilon: used for floating point comparisons, two points are considered equals if their distance is < epsilon.
    do_plot: if not None, plot intermediate steps on this matplotlib object and save them as images named: plot_filename % i
    """

    if do_plot and len(points) > 10:
        print "WARNING it is a bad idea to plot each steps of a triangulation of many points"

    # Sort points first on the x-axis, then on the y-axis.
    vertices = sorted(points)

    # LOGN( "super-triangle",supertri )
    if not supertri:
        supertri = supertriangle(vertices, superdelta)

    # It is the first triangle of the list.
    triangles = [supertri]

    completed = {supertri: False}

    # The predicate returns true if at least one of the vertices
    # is also found in the supertriangle.
    def match_supertriangle(tri):
        if tri[0] in supertri or \
           tri[1] in supertri or \
           tri[2] in supertri:
            return True

    # Returns the base of each plots, with points, current triangulation, super-triangle and bounding box.
    def plot_base(ax, vi=len(vertices), vertex=None):
        ax.set_aspect('equal')
        # regular points
        scatter_x = [p[0] for p in vertices[:vi]]
        scatter_y = [p[1] for p in vertices[:vi]]
        ax.scatter(scatter_x, scatter_y, s=30, marker='o', facecolor="black")
        # super-triangle vertices
        scatter_x = [p[0] for p in list(supertri)]
        scatter_y = [p[1] for p in list(supertri)]
        ax.scatter(scatter_x,
                   scatter_y,
                   s=30,
                   marker='o',
                   facecolor="lightgrey",
                   edgecolor="lightgrey")
        # current vertex
        if vertex:
            ax.scatter(vertex[0],
                       vertex[1],
                       s=30,
                       marker='o',
                       facecolor="red",
                       edgecolor="red")
        # current triangulation
        uberplot.plot_segments(ax,
                               edges_of(triangles),
                               edgecolor="blue",
                               alpha=0.5,
                               linestyle='solid')
        # bounding box
        (xmin, ymin), (xmax, ymax) = bounds(vertices)
        uberplot.plot_segments(ax,
                               tour([(xmin, ymin), (xmin, ymax), (xmax, ymax),
                                     (xmax, ymin)]),
                               edgecolor="magenta",
                               alpha=0.2,
                               linestyle='dotted')

    # Insert vertices one by one.
    LOG("Insert vertices: ")
    if do_plot:
        it = 0
    for vi, vertex in enumerate(vertices):
        # LOGN( "\tvertex",vertex )
        assert (len(vertex) == 2)

        if do_plot:
            ax = do_plot.add_subplot(111)
            plot_base(ax, vi, vertex)

        # All the triangles whose circumcircle encloses the point to be added are identified,
        # the outside edges of those triangles form an enclosing polygon.

        # Forget previous candidate polygon's edges.
        enclosing = []

        removed = []
        for triangle in triangles:
            # LOGN( "\t\ttriangle",triangle )
            assert (len(triangle) == 3)

            # Do not consider triangles already tested.
            # If completed has a key, test it, else return False.
            if completed.get(triangle, False):
                # LOGN( "\t\t\tAlready completed" )
                # if do_plot:
                # uberplot.plot_segments( ax, tour(list(triangle)), edgecolor = "magenta", alpha=1, lw=1, linestyle='dotted' )
                continue

            # LOGN( "\t\t\tCircumcircle" )
            assert (triangle[0] != triangle[1] and triangle[1] != triangle[2]
                    and triangle[2] != triangle[0])
            center, radius = circumcircle(triangle, epsilon)

            # If it match Delaunay's conditions.
            if x(center) < x(vertex) and math.sqrt(
                (x(vertex) - x(center))**2) > radius:
                # LOGN( "\t\t\tMatch Delaunay, mark as completed" )
                completed[triangle] = True

            # If the current vertex is inside the circumscribe circle of the current triangle,
            # add the current triangle's edges to the candidate polygon.
            if in_circle(vertex, center, radius, epsilon):
                # LOGN( "\t\t\tIn circumcircle, add to enclosing polygon",triangle )
                if do_plot:
                    circ = plot.Circle(center,
                                       radius,
                                       facecolor='yellow',
                                       edgecolor="orange",
                                       alpha=0.2,
                                       clip_on=False)
                    ax.add_patch(circ)

                for p0, p1 in tour(list(triangle)):
                    # Then add this edge to the polygon enclosing the vertex,
                    enclosing.append((p0, p1))
                # and remove the corresponding triangle from the current triangulation.
                removed.append(triangle)
                completed.pop(triangle, None)

            elif do_plot:
                circ = plot.Circle(center,
                                   radius,
                                   facecolor='lightgrey',
                                   edgecolor="grey",
                                   alpha=0.2,
                                   clip_on=False)
                ax.add_patch(circ)

        # end for triangle in triangles

        # The triangles in the enclosing polygon are deleted and
        # new triangles are formed between the point to be added and
        # each outside edge of the enclosing polygon.

        # Actually remove triangles.
        for triangle in removed:
            triangles.remove(triangle)

        # Remove duplicated edges.
        # This leaves the edges of the enclosing polygon only,
        # because enclosing edges are only in a single triangle,
        # but edges inside the polygon are at least in two triangles.
        hull = []
        for i, (p0, p1) in enumerate(enclosing):
            # Clockwise edges can only be in the remaining part of the list.
            # Search for counter-clockwise edges as well.
            if (p0, p1) not in enclosing[i + 1:] and (p1, p0) not in enclosing:
                hull.append((p0, p1))
            elif do_plot:
                uberplot.plot_segments(ax, [(p0, p1)],
                                       edgecolor="white",
                                       alpha=1,
                                       lw=1,
                                       linestyle='dotted')

        if do_plot:
            uberplot.plot_segments(ax,
                                   hull,
                                   edgecolor="red",
                                   alpha=1,
                                   lw=1,
                                   linestyle='solid')

        # Create new triangles using the current vertex and the enclosing hull.
        # LOGN( "\t\tCreate new triangles" )
        for p0, p1 in hull:
            assert (p0 != p1)
            triangle = tuple([p0, p1, vertex])
            # LOGN("\t\t\tNew triangle",triangle)
            triangles.append(triangle)
            completed[triangle] = False

            if do_plot:
                uberplot.plot_segments(ax, [(p0, vertex), (p1, vertex)],
                                       edgecolor="green",
                                       alpha=1,
                                       linestyle='solid')

        if do_plot:
            plot.savefig(plot_filename % it, dpi=150)
            plot.clf()

            it += 1
        LOG(".")

    # end for vertex in vertices
    LOGN(" done")

    # Remove triangles that have at least one of the supertriangle vertices.
    # LOGN( "\tRemove super-triangles" )

    # Filter out elements for which the predicate is False,
    # here: *keep* elements that *do not* have a common vertex.
    # The filter is a generator, so we must make a list with it to actually get the data.
    triangulation = list(filter_if_not(match_supertriangle, triangles))

    if do_plot:
        ax = do_plot.add_subplot(111)
        plot_base(ax)
        uberplot.plot_segments(ax,
                               edges_of(triangles),
                               edgecolor="red",
                               alpha=0.5,
                               linestyle='solid')
        uberplot.plot_segments(ax,
                               edges_of(triangulation),
                               edgecolor="blue",
                               alpha=1,
                               linestyle='solid')
        plot.savefig(plot_filename % it, dpi=150)
        plot.clf()

    return triangulation
Exemplo n.º 18
0
def mtan(pa, pb):
    return -1 * (x(pa) - x(pb)) / (y(pa) - y(pb))
Exemplo n.º 19
0
def delaunay_bowyer_watson( points, supertri = None, superdelta = 0.1, epsilon = sys.float_info.epsilon,
        do_plot = None, plot_filename = "Bowyer-Watson_%i.png" ):
    """Return the Delaunay triangulation of the given points

    epsilon: used for floating point comparisons, two points are considered equals if their distance is < epsilon.
    do_plot: if not None, plot intermediate steps on this matplotlib object and save them as images named: plot_filename % i
    """

    if do_plot and len(points) > 10:
        print "WARNING it is a bad idea to plot each steps of a triangulation of many points"

    # Sort points first on the x-axis, then on the y-axis.
    vertices = sorted( points )

    # LOGN( "super-triangle",supertri )
    if not supertri:
        supertri = supertriangle( vertices, superdelta )

    # It is the first triangle of the list.
    triangles = [ supertri ]

    completed = { supertri: False }

    # The predicate returns true if at least one of the vertices
    # is also found in the supertriangle.
    def match_supertriangle( tri ):
        if tri[0] in supertri or \
           tri[1] in supertri or \
           tri[2] in supertri:
            return True

    # Returns the base of each plots, with points, current triangulation, super-triangle and bounding box.
    def plot_base(ax,vi = len(vertices), vertex = None):
        ax.set_aspect('equal')
        # regular points
        scatter_x = [ p[0] for p in vertices[:vi]]
        scatter_y = [ p[1] for p in vertices[:vi]]
        ax.scatter( scatter_x,scatter_y, s=30, marker='o', facecolor="black")
        # super-triangle vertices
        scatter_x = [ p[0] for p in list(supertri)]
        scatter_y = [ p[1] for p in list(supertri)]
        ax.scatter( scatter_x,scatter_y, s=30, marker='o', facecolor="lightgrey", edgecolor="lightgrey")
        # current vertex
        if vertex:
            ax.scatter( vertex[0],vertex[1], s=30, marker='o', facecolor="red", edgecolor="red")
        # current triangulation
        uberplot.plot_segments( ax, edges_of(triangles), edgecolor = "blue", alpha=0.5, linestyle='solid' )
        # bounding box
        (xmin,ymin),(xmax,ymax) = bounds(vertices)
        uberplot.plot_segments( ax, tour([(xmin,ymin),(xmin,ymax),(xmax,ymax),(xmax,ymin)]), edgecolor = "magenta", alpha=0.2, linestyle='dotted' )


    # Insert vertices one by one.
    LOG("Insert vertices: ")
    if do_plot:
        it=0
    for vi,vertex in enumerate(vertices):
        # LOGN( "\tvertex",vertex )
        assert( len(vertex) == 2 )

        if do_plot:
            ax = do_plot.add_subplot(111)
            plot_base(ax,vi,vertex)

        # All the triangles whose circumcircle encloses the point to be added are identified,
        # the outside edges of those triangles form an enclosing polygon.

        # Forget previous candidate polygon's edges.
        enclosing = []

        removed = []
        for triangle in triangles:
            # LOGN( "\t\ttriangle",triangle )
            assert( len(triangle) == 3 )

            # Do not consider triangles already tested.
            # If completed has a key, test it, else return False.
            if completed.get( triangle, False ):
                # LOGN( "\t\t\tAlready completed" )
                # if do_plot:
                    # uberplot.plot_segments( ax, tour(list(triangle)), edgecolor = "magenta", alpha=1, lw=1, linestyle='dotted' )
                continue

            # LOGN( "\t\t\tCircumcircle" ) 
            assert( triangle[0] != triangle[1] and triangle[1] != triangle [2] and triangle[2] != triangle[0] )
            center,radius = circumcircle( triangle, epsilon )

            # If it match Delaunay's conditions.
            if x(center) < x(vertex) and math.sqrt((x(vertex)-x(center))**2) > radius:
                # LOGN( "\t\t\tMatch Delaunay, mark as completed" ) 
                completed[triangle] = True

            # If the current vertex is inside the circumscribe circle of the current triangle,
            # add the current triangle's edges to the candidate polygon.
            if in_circle( vertex, center, radius, epsilon ):
                # LOGN( "\t\t\tIn circumcircle, add to enclosing polygon",triangle )
                if do_plot:
                    circ = plot.Circle(center, radius, facecolor='yellow', edgecolor="orange", alpha=0.2, clip_on=False)
                    ax.add_patch(circ)

                for p0,p1 in tour(list(triangle)):
                    # Then add this edge to the polygon enclosing the vertex,
                    enclosing.append( (p0,p1) )
                # and remove the corresponding triangle from the current triangulation.
                removed.append( triangle )
                completed.pop(triangle,None)

            elif do_plot:
                circ = plot.Circle(center, radius, facecolor='lightgrey', edgecolor="grey", alpha=0.2, clip_on=False)
                ax.add_patch(circ)

        # end for triangle in triangles

        # The triangles in the enclosing polygon are deleted and
        # new triangles are formed between the point to be added and
        # each outside edge of the enclosing polygon. 

        # Actually remove triangles.
        for triangle in removed:
            triangles.remove(triangle)


        # Remove duplicated edges.
        # This leaves the edges of the enclosing polygon only,
        # because enclosing edges are only in a single triangle,
        # but edges inside the polygon are at least in two triangles.
        hull = []
        for i,(p0,p1) in enumerate(enclosing):
            # Clockwise edges can only be in the remaining part of the list.
            # Search for counter-clockwise edges as well.
            if (p0,p1) not in enclosing[i+1:] and (p1,p0) not in enclosing:
                hull.append((p0,p1))
            elif do_plot:
                uberplot.plot_segments( ax, [(p0,p1)], edgecolor = "white", alpha=1, lw=1, linestyle='dotted' )



        if do_plot:
            uberplot.plot_segments( ax, hull, edgecolor = "red", alpha=1, lw=1, linestyle='solid' )


        # Create new triangles using the current vertex and the enclosing hull.
        # LOGN( "\t\tCreate new triangles" )
        for p0,p1 in hull:
            assert( p0 != p1 )
            triangle = tuple([p0,p1,vertex])
            # LOGN("\t\t\tNew triangle",triangle)
            triangles.append( triangle )
            completed[triangle] = False

            if do_plot:
                uberplot.plot_segments( ax, [(p0,vertex),(p1,vertex)], edgecolor = "green", alpha=1, linestyle='solid' )

        if do_plot:
            plot.savefig( plot_filename % it, dpi=150)
            plot.clf()

            it+=1
        LOG(".")

    # end for vertex in vertices
    LOGN(" done")


    # Remove triangles that have at least one of the supertriangle vertices.
    # LOGN( "\tRemove super-triangles" ) 

    # Filter out elements for which the predicate is False,
    # here: *keep* elements that *do not* have a common vertex.
    # The filter is a generator, so we must make a list with it to actually get the data.
    triangulation = list(filter_if_not( match_supertriangle, triangles ))

    if do_plot:
            ax = do_plot.add_subplot(111)
            plot_base(ax)
            uberplot.plot_segments( ax, edges_of(triangles), edgecolor = "red", alpha=0.5, linestyle='solid' )
            uberplot.plot_segments( ax, edges_of(triangulation), edgecolor = "blue", alpha=1, linestyle='solid' )
            plot.savefig( plot_filename % it, dpi=150)
            plot.clf()

    return triangulation
Exemplo n.º 20
0
def write(triangles, stream):
    for tri in triangles:
        assert (len(tri) == 3)
        p, q, r = tri
        stream.write("%f,%f %f,%f %f,%f\n" %
                     (x(p), y(p), x(q), y(q), x(r), y(r)))
Exemplo n.º 21
0
def write( triangles, stream ):
    for tri in triangles:
        assert(len(tri)==3)
        p,q,r = tri
        stream.write("%f,%f %f,%f %f,%f\n" % ( x(p),y(p), x(q),y(q), x(r),y(r) ) )
Exemplo n.º 22
0
def in_triangle(p0, triangle, exclude_edges=False):
    """Return True if the given point lies inside the given triangle"""

    p1, p2, p3 = triangle

    # Compute the barycentric coordinates
    alpha = ( (y(p2) - y(p3)) * (x(p0) - x(p3)) + (x(p3) - x(p2)) * (y(p0) - y(p3)) )   \
          / ( (y(p2) - y(p3)) * (x(p1) - x(p3)) + (x(p3) - x(p2)) * (y(p1) - y(p3)) )
    beta  = ( (y(p3) - y(p1)) * (x(p0) - x(p3)) + (x(p1) - x(p3)) * (y(p0) - y(p3)) )   \
          / ( (y(p2) - y(p3)) * (x(p1) - x(p3)) + (x(p3) - x(p2)) * (y(p1) - y(p3)) )
    gamma = 1.0 - alpha - beta

    if exclude_edges:
        # If all of alpha, beta, and gamma are strictly in ]0,1[,
        # then the point p0 strictly lies within the triangle.
        return all(0 < x < 1 for x in (alpha, beta, gamma))
    else:
        # If the inequality is not strict, then the point may lies on an edge.
        return all(0 <= x <= 1 for x in (alpha, beta, gamma))
Exemplo n.º 23
0
def in_triangle( p0, triangle, exclude_edges = False ):
    """Return True if the given point lies inside the given triangle"""

    p1,p2,p3 = triangle

    # Compute the barycentric coordinates
    alpha = ( (y(p2) - y(p3)) * (x(p0) - x(p3)) + (x(p3) - x(p2)) * (y(p0) - y(p3)) )   \
          / ( (y(p2) - y(p3)) * (x(p1) - x(p3)) + (x(p3) - x(p2)) * (y(p1) - y(p3)) )
    beta  = ( (y(p3) - y(p1)) * (x(p0) - x(p3)) + (x(p1) - x(p3)) * (y(p0) - y(p3)) )   \
          / ( (y(p2) - y(p3)) * (x(p1) - x(p3)) + (x(p3) - x(p2)) * (y(p1) - y(p3)) )
    gamma = 1.0 - alpha - beta

    if exclude_edges:
        # If all of alpha, beta, and gamma are strictly in ]0,1[,
        # then the point p0 strictly lies within the triangle.
        return all( 0 < x < 1 for x in (alpha, beta, gamma) )
    else:
        # If the inequality is not strict, then the point may lies on an edge.
        return all( 0 <= x <= 1 for x in (alpha, beta, gamma) )
Exemplo n.º 24
0
def turn(p, q, r):
    """Returns -1, 0, 1 if the sequence of points (p,q,r) forms a right, straight, or left turn."""
    qr = ( x(q) - x(p) ) * ( y(r) - y(p) )
    rq = ( x(r) - x(p) ) * ( y(q) - y(p) )
    # cmp(x,y) returns -1 if x<y, 0 if x==y, +1 if x>y
    return cmp( qr - rq, 0)
Exemplo n.º 25
0
def write_segments(segments, stream):
    for seg in segments:
        for p in seg:
            stream.write("%f,%f " % (x(p), y(p)))
        stream.write("\n")
Exemplo n.º 26
0
def write(graph, stream):
    for k in graph:
        stream.write("%f,%f:" % (x(k), y(k)))
        for p in graph[k]:
            stream.write("%f,%f " % (x(p), y(p)))
        stream.write("\n")