Example #1
0
def test_make_compound_path_stops():
    zero = [0, 0]
    paths = 3*[Path([zero, zero], [Path.MOVETO, Path.STOP])]
    compound_path = Path.make_compound_path(*paths)
    # the choice to not preserve the terminal STOP is arbitrary, but
    # documented, so we test that it is in fact respected here
    assert np.sum(compound_path.codes == Path.STOP) == 0
Example #2
0
def main():
    imagery = OSM()

    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1, projection=imagery.crs)
    ax.set_extent([-0.14, -0.1, 51.495, 51.515], ccrs.PlateCarree())

    # Construct concentric circles and a rectangle,
    # suitable for a London Underground logo.
    theta = np.linspace(0, 2 * np.pi, 100)
    circle_verts = np.vstack([np.sin(theta), np.cos(theta)]).T
    concentric_circle = Path.make_compound_path(Path(circle_verts[::-1]),
                                                Path(circle_verts * 0.6))

    rectangle = Path([[-1.1, -0.2], [1, -0.2], [1, 0.3], [-1.1, 0.3]])

    # Add the imagery to the map.
    ax.add_image(imagery, 14)

    # Plot the locations twice, first with the red concentric circles,
    # then with the blue rectangle.
    xs, ys = tube_locations().T
    ax.plot(xs, ys, transform=ccrs.OSGB(),
            marker=concentric_circle, color='red', markersize=9, linestyle='')
    ax.plot(xs, ys, transform=ccrs.OSGB(),
            marker=rectangle, color='blue', markersize=11, linestyle='')

    ax.set_title('London underground locations')
    plt.show()
Example #3
0
def main():
    imagery = OSM()

    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1, projection=imagery.crs)
    ax.set_extent([-0.14, -0.1, 51.495, 51.515], ccrs.PlateCarree())

    # Construct concentric circles and a rectangle,
    # suitable for a London Underground logo.
    theta = np.linspace(0, 2 * np.pi, 100)
    circle_verts = np.vstack([np.sin(theta), np.cos(theta)]).T
    concentric_circle = Path.make_compound_path(Path(circle_verts[::-1]),
                                                Path(circle_verts * 0.6))

    rectangle = Path([[-1.1, -0.2], [1, -0.2], [1, 0.3], [-1.1, 0.3]])

    # Add the imagery to the map.
    ax.add_image(imagery, 14)

    # Plot the locations twice, first with the red concentric circles,
    # then with the blue rectangle.
    xs, ys = tube_locations().T
    ax.plot(xs, ys, transform=ccrs.OSGB(),
            marker=concentric_circle, color='red', markersize=9, linestyle='')
    ax.plot(xs, ys, transform=ccrs.OSGB(),
            marker=rectangle, color='blue', markersize=11, linestyle='')

    ax.set_title('London underground locations')
    plt.show()
Example #4
0
def getPathFromShp(shpfile, region):
    try:
        sf = shapefile.Reader(shpfile)
        vertices = []  # 这块是已经修改的地方
        codes = []  # 这块是已经修改的地方
        paths = []
        for shape_rec in sf.shapeRecords():
            # if shape_rec.record[3] == region:  # 这里需要找到和region匹配的唯一标识符,record[]中必有一项是对应的。
            if region == [100000
                          ] or shape_rec.record[4] in region:  # 这块是已经修改的地方
                pts = shape_rec.shape.points
                prt = list(shape_rec.shape.parts) + [len(pts)]
                for i in range(len(prt) - 1):
                    for j in range(prt[i], prt[i + 1]):
                        vertices.append((pts[j][0], pts[j][1]))
                    codes += [Path.MOVETO]
                    codes += [Path.LINETO] * (prt[i + 1] - prt[i] - 2)
                    codes += [Path.CLOSEPOLY]
                path = Path(vertices, codes)
                paths.append(path)
        if paths:
            path = Path.make_compound_path(*paths)
        else:
            path = None
        return path
    except Exception as err:
        print(err)
        return None
        def transform_path(self, path):
            vertices = path.vertices
            # Intelligent interpolation needed
#            ipath = path.interpolated(self._resolution)
            ipath = path
            ipath = path.interpolated(10)
#            ipath = path.interpolated(3050)
            
            verts = self.transform_no_mod(ipath.vertices)
            codes = ipath.codes
#            print verts.shape
#            print 'transforming lon range:', np.min(verts[:, 0]), np.max(verts[:, 0])
#            if np.isnan(np.max(verts[:, 0])):
#                print 'Got nan: ', path, verts
                 
            paths = []
            paths.append(Path(verts, codes))
            
#            # Have any of the points wrapped? If so, pick up the pen, and start from -360
#            if any(ipath.vertices[:, 0] > np.pi):
#                v = ipath.vertices.copy()
#                print 'splitting -:'
#                v[:, 0] -= 2 * np.pi                
#                print v
#                v = self.transform_no_mod(v)
#                paths.append(Path(v))
#                 
#            # Have any of the points wrapped? If so, pick up the pen, and start from +360
#            if any(ipath.vertices[:, 0] < -np.pi):
#                v = ipath.vertices.copy()
#                v[:, 0] += 2 * np.pi
#                print 'splitting +:'
#                v = self.transform_no_mod(v)
#                paths.append(Path(v))
            s_pole = np.deg2rad(np.array([0, -89.9999]))
            if path.contains_point(s_pole):
                print 'POLE ALERT!!!', path 
                path = Path(verts[:-31])
                paths = [path]
            
            if len(paths) == 1:
                path = paths[0]
            else:
                for path in paths:
                    if path.codes is not None:
                        if path.codes[0] == Path.MOVETO and all(path.codes[1:] == Path.LINETO):
                            path.codes = None
                        else:
                            # This is a bit strict... but a condition of make_compound_path
                            raise ValueError('Cannot draw discontiguous polygons.')
#                        print path.codes
                path = Path.make_compound_path(*paths)
                                      
            return path
Example #6
0
 def _plot(self, ax, legend, alpha, ec='#222222'):
     groups = self.groups('shape')
     for key in self.classes.index:
         group = groups.get_group(key)
         paths = []
         for g in group['shape']:
             paths.append(PolygonPath(g))
         patch = PathPatch(Path.make_compound_path(*paths), fc=legend[key], ec=ec, alpha=alpha, zorder=2, label='{} ({})'.format(key, len(group)))
         ax.add_patch(patch)
     ax.margins(0.025, 0.025)
     ax.get_yaxis().set_tick_params(which='both', direction='out')
     ax.get_xaxis().set_tick_params(which='both', direction='out')
     return ax
Example #7
0
def shape_to_patch(shape, **kwargs):

    if isinstance(shape, Polygon):
        return patches.Polygon(list(shape.exterior.coords)[1:], **kwargs)

    if isinstance(shape, MultiPolygon):
        paths = [polygon_path(list(o.exterior.coords)[1:]) for o in shape.geoms]
        for p in paths:
            print("path", p)
        path = Path.make_compound_path(*paths)
        return PathPatch(path, **kwargs)

    if isinstance(shape, LineString):
        path_data = [(Path.MOVETO, shape.coords[0])]
        for coord in shape.coords[1:]:
            path_data.append((Path.LINETO, coord))
        codes, verts = zip(*path_data)
        path = Path(verts, codes, closed=False)
        return PathPatch(path, **kwargs)
Example #8
0
def _PolygonPatch(polygon, **kwargs):
    """Constructs a matplotlib patch from a Polygon geometry

    The `kwargs` are those supported by the matplotlib.patches.PathPatch class
    constructor. Returns an instance of matplotlib.patches.PathPatch.

    Example (using Shapely Point and a matplotlib axes)::

        b = shapely.geometry.Point(0, 0).buffer(1.0)
        patch = _PolygonPatch(b, fc='blue', ec='blue', alpha=0.5)
        ax.add_patch(patch)

    GeoPandas originally relied on the descartes package by Sean Gillies
    (BSD license, https://pypi.org/project/descartes) for PolygonPatch, but
    this dependency was removed in favor of the below matplotlib code.
    """
    from matplotlib.patches import PathPatch
    from matplotlib.path import Path

    path = Path.make_compound_path(
        Path(np.asarray(polygon.exterior.coords)[:, :2]),
        *[Path(np.asarray(ring.coords)[:, :2]) for ring in polygon.interiors])
    return PathPatch(path, **kwargs)
Example #9
0
def test_make_compound_path_empty():
    # We should be able to make a compound path with no arguments.
    # This makes it easier to write generic path based code.
    r = Path.make_compound_path()
    assert r.vertices.shape == (0, 2)
Example #10
0
def test_make_compound_path_empty():
    # We should be able to make a compound path with no arguments.
    # This makes it easier to write generic path based code.
    r = Path.make_compound_path()
    assert r.vertices.shape == (0, 2)
def pcolor_mask_geoms(cube, geoms, transform):
    path = Path.make_compound_path(*geos_to_path(geoms))
    im = iplt.pcolor(cube)
    im.set_clip_path(path, transform=transform)
Example #12
0
ax.yaxis.set_major_formatter(lat_formatter)
#刻度字体大小
ax.tick_params(labelsize=15)

contourf = ax.contourf(lon,lat,u1_avg,lev,cmap='Blues',transform=proj,extend='both')

countries = shp.records()
cn_multipoly, = [country.geometry for country in countries
                 if country.attributes['CNTRY_NAME'] == 'China']  # 选择地图属性下'NAME'属性里名字是'China'的一条多边形

paths = []
for i in range(len(cn_multipoly)):
    cn_geom, = geos_to_path(cn_multipoly.geoms[i])
    paths.append(cn_geom)

path = Path.make_compound_path(*paths)
for collection in contourf.collections:
    collection.set_clip_path(path, proj._as_mpl_transform(ax))

# 白化刻度
# contour = ax.contour(lon,lat,u1_avg,lev,cmap='Blues',transform=proj,extend='both')
# cn_label = plt.clabel(contour,inline=1,fontsize=10,fmt="%.fr")
# if cn_label:
#     clip_map_shapely = Polygon(path.vertices)
#     for text_object in cn_label:
#         if not clip_map_shapely.contains(Point(text_object.get_position())):
#             text_object.set_visible(False)

ax.add_geometries(cn_multipoly, crs=proj, edgecolor='black', linewidths=1, facecolor='none', zorder=10, alpha=0.8)

#ax.gridlines(color="black", linestyle="--")
Example #13
0
def compress_points(points):
    bi, bj, bx, by = get_boundary_intersections(points)

    f = bi == bj
    alone_points = points[bi[f]]
    alone_paths = [Path.circle(xy, 0.5) for xy in alone_points]

    edge_lists = [[] for i in range(len(points))]
    n = 0
    for i, j, x, y in zip(bi, bj, bx, by):
        if i != j:
            edge_lists[j].append((i, x, y))
            n += 1

    print("%s points in total: %s edges, %s alone points" %
          (len(points), n, len(alone_points)))

    def patan2(dy, dx):
        """
        Return pseudo-arctangent of dy/dx such that
            patan2(y1, x1) < patan2(y2, x2)
            if and only if
            atan2(y1, x1) < atan2(y2, x2)
        """
        if dy > 0 and dx > 0:
            return (0, dy - dx)
        elif dy > 0 and dx <= 0:
            return (1, -dy - dx)
        elif dy <= 0 and dx > 0:
            return (2, dx - dy)
        else:
            return (3, dx + dy)

    def shift(u, v):
        if v < u:
            return (v[0] + 4, v[1])
        else:
            return v

    def pop_next(i, ox, oy):
        def local_patan2(y, x):
            return patan2(y - points[i, 1], x - points[i, 0])
        u = local_patan2(oy, ox)
        j = min(range(len(edge_lists[i])),
                key=lambda j: shift(u, local_patan2(edge_lists[i][j][2],
                                                    edge_lists[i][j][1])))
        return edge_lists[i].pop(j)

    paths = []
    # print("<path fill=\"black\" fillrule=\"wind\">")
    while n > 0:
        assert sum(len(e) for e in edge_lists) == n
        i = 0
        while not edge_lists[i]:
            i += 1
        start = i
        j, ox, oy = edge_lists[i].pop(0)
        startx, starty = ox, oy
        ux, uy = ox, oy
        # path = ['%s %s m' % (startx, starty)]
        path_vert_lists = [[[startx, starty]]]
        path_code_lists = [[Path.MOVETO]]

        n -= 1
        while j != start:
            i = j
            j, vx, vy = pop_next(i, ux, uy)
            n -= 1
            # path.append(
            #     '%s 0 0 %s %s %s %s %s a' %
            #     (R, R, points[i, 0], points[i, 1], ox, oy))
            ox, oy = points[i]
            theta1 = np.arctan2(uy - oy, ux - ox)
            theta2 = np.arctan2(vy - oy, vx - ox)
            a = Path.arc(theta1 * 180 / np.pi, theta2 * 180 / np.pi)
            a = a.transformed(Affine2D().scale(0.5).translate(ox, oy))
            path_vert_lists.append(a._vertices[1:])
            path_code_lists.append(a._codes[1:])
            ux, uy = vx, vy
        # path.append(
        #     '%s 0 0 %s %s %s %s %s a' %
        #     (R, R, points[j, 0], points[j, 1], startx, starty))
        ox, oy = points[j]
        theta1 = np.arctan2(uy - oy, ux - ox)
        theta2 = np.arctan2(starty - oy, startx - ox)
        a = Path.arc(theta1 * 180 / np.pi, theta2 * 180 / np.pi)
        a = a.transformed(Affine2D().scale(0.5).translate(ox, oy))
        path_vert_lists.append(a._vertices[1:])
        path_code_lists.append(a._codes[1:])
        # print('\n'.join(path))
        paths.append(
            Path(np.concatenate(path_vert_lists),
                 np.concatenate(path_code_lists).astype(Path.code_type)))
    # print("</path>")
    return Path.make_compound_path(*(alone_paths + paths))
    def plot(self):

        if self.filetype == "geotiff":
            f, fname = tempfile.mkstemp()
            os.close(f)

            driver = gdal.GetDriverByName("GTiff")
            outRaster = driver.Create(
                fname,
                self.latitude.shape[1],
                self.longitude.shape[0],
                1,
                gdal.GDT_Float64,
            )
            x = np.array([self.longitude[0, 0], self.longitude[-1, -1]])
            y = np.array([self.latitude[0, 0], self.latitude[-1, -1]])
            outRasterSRS = osr.SpatialReference()

            pts = self.plot_projection.transform_points(
                self.pc_projection, x, y)
            x = pts[:, 0]
            y = pts[:, 1]
            outRasterSRS.ImportFromProj4(self.plot_projection.proj4_init)

            pixelWidth = (x[-1] - x[0]) / self.longitude.shape[0]
            pixelHeight = (y[-1] - y[0]) / self.latitude.shape[0]
            outRaster.SetGeoTransform(
                (x[0], pixelWidth, 0, y[0], 0, pixelHeight))

            outband = outRaster.GetRasterBand(1)
            d = self.data.astype(np.float64)
            ndv = d.fill_value
            outband.WriteArray(d.filled(ndv))
            outband.SetNoDataValue(ndv)
            outRaster.SetProjection(outRasterSRS.ExportToWkt())
            outband.FlushCache()
            outRaster = None

            with open(fname, "r", encoding="latin-1") as f:
                buf = f.read()
            os.remove(fname)

            return (buf, self.mime, self.filename.replace(".geotiff", ".tif"))
        # Figure size
        figuresize = list(map(float, self.size.split("x")))
        fig, map_plot = basemap.load_map(
            self.plot_projection,
            self.plot_extent,
            figuresize,
            self.dpi,
            self.plot_res,
        )

        ax = plt.gca()

        if self.scale:
            vmin = self.scale[0]
            vmax = self.scale[1]
        else:
            vmin, vmax = utils.normalize_scale(
                self.data,
                self.dataset_config.variable[f"{self.variables[0]}"])

        c = map_plot.imshow(
            self.data,
            vmin=vmin,
            vmax=vmax,
            cmap=self.cmap,
            extent=self.plot_extent,
            transform=self.plot_projection,
            origin="lower",
            zorder=0,
        )

        if len(self.quiver_data) == 2:
            qx, qy = self.quiver_data
            qx, qy = self.plot_projection.transform_vectors(
                self.pc_projection, self.quiver_longitude,
                self.quiver_latitude, qx, qy)
            pts = self.plot_projection.transform_points(
                self.pc_projection, self.quiver_longitude,
                self.quiver_latitude)
            x = pts[:, :, 0]
            y = pts[:, :, 1]

            qx = np.ma.masked_where(np.ma.getmask(self.quiver_data[0]), qx)
            qy = np.ma.masked_where(np.ma.getmask(self.quiver_data[1]), qy)

            if self.quiver["magnitude"] != "length":
                qx = qx / self.quiver_magnitude
                qy = qy / self.quiver_magnitude
                qscale = 50
            else:
                qscale = None

            if self.quiver["magnitude"] == "color":
                if (self.quiver["colormap"] is None
                        or self.quiver["colormap"] == "default"):
                    qcmap = colormap.colormaps.get("speed")
                else:
                    qcmap = colormap.colormaps.get(self.quiver["colormap"])
                q = map_plot.quiver(
                    x,
                    y,
                    qx,
                    qy,
                    self.quiver_magnitude,
                    width=0.0035,
                    headaxislength=4,
                    headlength=4,
                    scale=qscale,
                    pivot="mid",
                    cmap=qcmap,
                    transform=self.plot_projection,
                )
            else:
                q = map_plot.quiver(
                    x,
                    y,
                    qx,
                    qy,
                    width=0.0025,
                    headaxislength=4,
                    headlength=4,
                    scale=qscale,
                    pivot="mid",
                    transform=self.plot_projection,
                    zorder=6,
                )

            if self.quiver["magnitude"] == "length":
                unit_length = np.mean(self.quiver_magnitude) * 2
                unit_length = np.round(unit_length,
                                       -int(np.floor(np.log10(unit_length))))
                if unit_length >= 1:
                    unit_length = int(unit_length)

                plt.quiverkey(
                    q,
                    0.65,
                    0.01,
                    unit_length,
                    self.quiver_name.title() + " " + str(unit_length) + " " +
                    utils.mathtext(self.quiver_unit),
                    coordinates="figure",
                    labelpos="E",
                )

        if self.show_bathymetry:
            # Plot bathymetry on top
            cs = map_plot.contour(
                self.longitude,
                self.latitude,
                self.bathymetry,
                linewidths=0.5,
                norm=FuncNorm((lambda x: np.log10(x), lambda x: 10**x),
                              vmin=1,
                              vmax=6000),
                cmap="Greys",
                levels=[100, 200, 500, 1000, 2000, 3000, 4000, 5000, 6000],
                transform=self.pc_projection,
                zorder=4,
            )
            plt.clabel(cs, fontsize="x-large", fmt="%1.0fm")

        if self.area and self.show_area:
            for a in self.area:
                polys = []
                for co in a["polygons"] + a["innerrings"]:
                    coords = np.array(co).transpose()
                    coords_transform = self.plot_projection.transform_points(
                        self.pc_projection, coords[1], coords[0])
                    mx = coords_transform[:, 0]
                    my = coords_transform[:, 1]
                    map_coords = list(zip(mx, my))
                    polys.append(Polygon(map_coords))

                paths = []
                for poly in polys:
                    paths.append(poly.get_path())
                path = Path.make_compound_path(*paths)

                for ec, lw in zip(["w", "k"], [5, 3]):
                    poly = PathPatch(
                        path,
                        fill=None,
                        edgecolor=ec,
                        linewidth=lw,
                        transform=self.plot_projection,
                        zorder=3,
                    )
                    map_plot.add_patch(poly)

            if self.names is not None and len(self.names) > 1:
                for idx, name in enumerate(self.names):
                    pts = self.plot_projection.transform_points(
                        self.pc_projection, self.centroids[idx].x,
                        self.centroids[idx].y)
                    x = pts[:, 0]
                    y = pts[:, 1]
                    plt.annotate(
                        xy=(x, y),
                        s=name,
                        ha="center",
                        va="center",
                        size=12,
                        # weight='bold'
                    )

        if len(self.contour_data) > 0:
            if self.contour_data[0].min() != self.contour_data[0].max():
                cmin, cmax = utils.normalize_scale(
                    self.contour_data[0],
                    self.dataset_config.variable[self.contour["variable"]],
                )
                levels = None
                if (self.contour.get("levels") is not None
                        and self.contour["levels"] != "auto"
                        and self.contour["levels"] != ""):
                    try:
                        levels = list(
                            set([
                                float(xx)
                                for xx in self.contour["levels"].split(",")
                                if xx.strip()
                            ]))
                        levels.sort()
                    except ValueError:
                        pass

                if levels is None:
                    levels = np.linspace(cmin, cmax, 5)
                cmap = self.contour["colormap"]
                if cmap is not None:
                    cmap = colormap.colormaps.get(cmap)
                    if cmap is None:
                        cmap = colormap.find_colormap(self.contour_name)

                if not self.contour.get("hatch"):
                    contours = map_plot.contour(
                        self.longitude,
                        self.latitude,
                        self.contour_data[0],
                        linewidths=2,
                        levels=levels,
                        cmap=cmap,
                        transform=self.pc_projection,
                        zorder=5,
                    )
                else:
                    hatches = [
                        "//", "xx", "\\\\", "--", "||", "..", "oo", "**"
                    ]
                    if len(levels) + 1 < len(hatches):
                        hatches = hatches[0:len(levels) + 2]
                    map_plot.contour(
                        self.longitude,
                        self.latitude,
                        self.contour_data[0],
                        linewidths=1,
                        levels=levels,
                        colors="k",
                        transform=self.pc_projection,
                        zorder=5,
                    )
                    contours = map_plot.contourf(
                        self.longitude,
                        self.latitude,
                        self.contour_data[0],
                        colors=["none"],
                        levels=levels,
                        hatches=hatches,
                        vmin=cmin,
                        vmax=cmax,
                        extend="both",
                        transform=self.pc_projection,
                        zorder=5,
                    )

                if self.contour["legend"]:
                    handles, l = contours.legend_elements()
                    labels = []
                    for i, lab in enumerate(l):
                        if self.contour.get("hatch"):
                            if self.contour_unit == "fraction":
                                if i == 0:
                                    labels.append(
                                        "$x \\leq {0: .0f}\\%$".format(
                                            levels[i] * 100))
                                elif i == len(levels):
                                    labels.append("$x > {0: .0f}\\%$".format(
                                        levels[i - 1] * 100))
                                else:
                                    labels.append(
                                        "${0:.0f}\\% < x \\leq {1:.0f}\\%$".
                                        format(levels[i - 1] * 100,
                                               levels[i] * 100))
                            else:
                                if i == 0:
                                    labels.append("$x \\leq %.3g$" % levels[i])
                                elif i == len(levels):
                                    labels.append("$x > %.3g$" % levels[i - 1])
                                else:
                                    labels.append("$%.3g < x \\leq %.3g$" %
                                                  (levels[i - 1], levels[i]))
                        else:
                            if self.contour_unit == "fraction":
                                labels.append("{0:.0%}".format(levels[i]))
                            else:
                                labels.append(
                                    "%.3g %s" %
                                    (levels[i],
                                     utils.mathtext(self.contour_unit)))

                    ax = plt.gca()

                    if self.contour_unit != "fraction" and not self.contour.get(
                            "hatch"):
                        contour_title = "%s (%s)" % (
                            self.contour_name,
                            utils.mathtext(self.contour_unit),
                        )
                    else:
                        contour_title = self.contour_name

                    leg = ax.legend(
                        handles[::-1],
                        labels[::-1],
                        loc="lower left",
                        fontsize="medium",
                        frameon=True,
                        framealpha=0.75,
                        title=contour_title,
                    )
                    leg.get_title().set_fontsize("medium")
                    if not self.contour.get("hatch"):
                        for legobj in leg.legendHandles:
                            legobj.set_linewidth(3)

        title = self.plotTitle

        if self.plotTitle is None or self.plotTitle == "":
            area_title = "\n".join(wrap(", ".join(self.names), 60)) + "\n"

            title = "%s %s %s, %s" % (
                area_title,
                self.variable_name.title(),
                self.depth_label,
                self.date_formatter(self.timestamp),
            )
        plt.title(title.strip())
        axpos = map_plot.get_position()
        pos_x = axpos.x0 + axpos.width + 0.01
        pos_y = axpos.y0
        cax = fig.add_axes([pos_x, pos_y, 0.03, axpos.height])
        bar = plt.colorbar(c, cax=cax)
        bar.set_label(
            "%s (%s)" %
            (self.variable_name.title(), utils.mathtext(self.variable_unit)),
            fontsize=14,
        )

        if (self.quiver is not None and self.quiver["variable"] != ""
                and self.quiver["variable"] != "none"
                and self.quiver["magnitude"] == "color"):
            pos_x = axpos.x0
            pos_y = axpos.y0 - 0.05
            bax = fig.add_axes([pos_x, pos_y, axpos.width, 0.03])
            qbar = plt.colorbar(q, orientation="horizontal", cax=bax)
            qbar.set_label(
                self.quiver_name.title() + " " +
                utils.mathtext(self.quiver_unit),
                fontsize=14,
            )

        return super(MapPlotter, self).plot(fig)
def plot_working_area(l_1,
                      l_2,
                      theta_1_min,
                      theta_1_max,
                      theta_2_min,
                      theta_2_max,
                      plot=True):
    ################################################################
    ################  Transform angles to radians   ################
    ################################################################
    theta_1_min = math.radians(theta_1_min)
    theta_1_max = math.radians(theta_1_max)
    theta_2_min = math.radians(theta_2_min)
    theta_2_max = math.radians(theta_2_max)
    ################################################################
    ################     Calculate Working Area     ################
    ################################################################
    wa = l_1 * l_2 * (math.cos(theta_2_min) -
                      math.cos(theta_2_max)) * (theta_1_max - theta_1_min)
    ################################################################
    ################           Setup Graph          ################
    ################################################################
    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1)
    ax.spines['left'].set_position('center')
    ax.spines['bottom'].set_position('center')
    ax.spines['right'].set_color('none')
    ax.spines['top'].set_color('none')
    ax.xaxis.set_ticks_position('bottom')
    ax.yaxis.set_ticks_position('left')
    ax.autoscale(True, 'both')
    ################################################################
    ################        Common Variables        ################
    ################################################################
    o = [0, 0]
    ################################################################
    ################        Link 2 at minimum       ################
    ################################################################
    start_point = forward_kinematics(l_1, l_2, theta_1_min, theta_2_min, True)
    end_point = forward_kinematics(l_1, l_2, theta_1_max, theta_2_min, True)
    radius = math.dist(end_point, o)
    start_angle = angle(start_point, [1, 0])
    end_angle = angle(end_point, [1, 0])
    ################################################################
    current_path = Path.arc(start_angle, end_angle)
    new_verts = current_path.deepcopy().vertices
    for new_vert in new_verts:
        new_vert[0] = new_vert[0] * radius
        new_vert[1] = new_vert[1] * radius
    new_verts = new_verts[:]
    current_path = Path(new_verts, current_path.deepcopy().codes[:])
    paths.append(current_path)
    patches.append(PathPatch(current_path))
    ax.add_patch(patches[0])
    ################################################################
    ################        Link 2 at maximum       ################
    ################################################################
    end_point = forward_kinematics(l_1, l_2, theta_1_min, theta_2_max, True)
    start_point = forward_kinematics(l_1, l_2, theta_1_max, theta_2_max, True)
    radius = math.dist(end_point, o)
    start_angle = angle_clockwise(start_point, [1, 0])
    end_angle = angle_clockwise(end_point, [1, 0])
    ################################################################
    current_path = Path.arc(start_angle, end_angle)
    new_verts = current_path.deepcopy().vertices
    for new_vert in new_verts:
        new_vert[0] = new_vert[0] * radius
        new_vert[1] = new_vert[1] * radius * -1
    new_verts = new_verts[:]
    current_path = Path(new_verts, current_path.deepcopy().codes[:])
    paths.append(current_path)
    patches.append(PathPatch(current_path))
    ax.add_patch(patches[1])
    ################################################################
    ################        Link 1 at minimum       ################
    ################################################################
    center = (l_1 * math.cos(theta_1_min), l_1 * math.sin(theta_1_min))
    end_point = forward_kinematics(l_1, l_2, theta_1_min, theta_2_min, True)
    end_point = [end_point[0] - center[0], end_point[1] - center[1]]
    start_point = forward_kinematics(l_1, l_2, theta_1_min, theta_2_max, True)
    start_point = [start_point[0] - center[0], start_point[1] - center[1]]
    radius = l_2
    start_angle = angle_clockwise(start_point, [1, 0])
    end_angle = angle_clockwise(end_point, [1, 0])
    ################################################################
    current_path = Path.arc(start_angle, end_angle)
    new_verts = current_path.deepcopy().vertices
    for new_vert in new_verts:
        new_vert[0] = (new_vert[0] * radius + center[0])
        new_vert[1] = (new_vert[1] * radius + center[1]) * -1
    new_verts[np.shape(new_verts)[0] - 1] = paths[0].vertices[0]
    new_verts = new_verts[:]

    current_path = Path(new_verts, current_path.deepcopy().codes[:])
    paths.append(current_path)
    patches.append(PathPatch(current_path))
    ax.add_patch(patches[2])
    ################################################################
    ################        Link 1 at maximum       ################
    ################################################################
    center = (l_1 * math.cos(theta_1_max), l_1 * math.sin(theta_1_max))
    start_point = forward_kinematics(l_1, l_2, theta_1_max, theta_2_min, True)
    start_point = [start_point[0] - center[0], start_point[1] - center[1]]
    end_point = forward_kinematics(l_1, l_2, theta_1_max, theta_2_max, True)
    end_point = [end_point[0] - center[0], end_point[1] - center[1]]
    radius = l_2
    start_angle = angle(start_point, [1, 0])
    end_angle = angle(end_point, [1, 0])
    ################################################################
    current_path = Path.arc(start_angle, end_angle)
    new_verts = current_path.deepcopy().vertices
    for new_vert in new_verts:
        new_vert[0] = new_vert[0] * radius + center[0]
        new_vert[1] = new_vert[1] * radius + center[1]
    new_verts = new_verts[:]
    current_path = Path(new_verts, current_path.deepcopy().codes[:])
    paths.append(current_path)
    patches.append(PathPatch(current_path))
    ax.add_patch(patches[3])
    ################################################################
    ################           Plot curves          ################
    ################################################################
    ax.set_title("Working Area = {wa:.3f}".format(wa=wa))

    new_path = Path.make_compound_path(
        paths[0],
        paths[3],
        paths[1],
        paths[2],
    )

    old_vertices = new_path.deepcopy().vertices
    old_codes = new_path.deepcopy().codes
    new_path_vertices = []
    new_path_codes = []

    for i, old_vertex in enumerate(old_vertices, start=0):
        if (i == 0):
            new_path_vertices.append(old_vertex)
            new_path_codes.append(old_codes[i])
        else:
            if (old_codes[i] != 1):
                new_path_vertices.append(old_vertex)
                new_path_codes.append(old_codes[i])

    new_path = Path(new_path_vertices, new_path_codes)

    patches[0].remove()
    patches[1].remove()
    patches[2].remove()
    patches[3].remove()

    path_patch = PathPatch(new_path, fill=False, hatch='/', clip_on=True)
    patches.append(path_patch)
    ax.add_patch(path_patch)
    if (plot == True):
        plt.show()
    return [ax, plt, fig]