Beispiel #1
0
def contour_area(con):
    """Calculate the area, convex hull area, and convexity deficiency
    of a polygon contour.

    Parameters
    ----------
    con : arraylike
        A 2D array of vertices with shape (N,2) that follows the scikit
        image conventions (con[:,0] are j indices)

    Returns
    -------
    region_area : float
    hull_area : float
    convexity_deficiency : float
    """
    # reshape the data to x, y order
    con_points = con[:, ::-1]

    # calculate area of polygon
    region_area = polygon_area(con_points)

    # find convex hull
    hull = qhull.ConvexHull(con_points)
    #hull_points = np.array([con_points[pt] for pt in hull.vertices])
    hull_area = hull.volume

    cd = (hull_area - region_area) / region_area

    return region_area, hull_area, cd
Beispiel #2
0
    def _update(self):
        """Update the :math:`A_{ineq}` matrix and the :math:`b_u` vector"""
        # if time to update
        if self._cnt % self._ticks == 0:
            # compute convex hull
            try:
                self._hull = qhull.ConvexHull(self._points)
            except qhull.QhullError:
                print(
                    "Not enough different points to compute the convex hull, using the old one."
                )

            if self._hull is not None:

                # convex hull equations
                A = self._hull.equations[:, :
                                         -2]  # shape: (F,2) - we only care about x and y (and not z))
                b = 1 * self._hull.equations[:, -1] - self.safety_margin

                # get jacobian (note that we only care about x and y (and not z))
                jacobian = self.model.get_com_jacobian(
                    full=False)[:2]  # shape: (2,N)

                # get current com position
                x_com = self.model.get_com_position()[:2]  # shape: (2,)

                # constraint matrix and vector
                self._A_ineq = A.dot(jacobian)  # (F,N)
                self._b_upper_bound = b - self._margin - A.dot(x_com)  # (F,)

            # reset counter
            self._cnt = 0

        # update counter
        self._cnt += 1
Beispiel #3
0
        def check(name):
            points = DATASETS[name]

            tri = qhull.Delaunay(points)
            hull = qhull.ConvexHull(points)

            assert_hulls_equal(points, tri.convex_hull, hull.simplices)
 def test_incremental_volume_area_random_input(self):
     """Test that incremental mode gives the same volume/area as
     non-incremental mode and incremental mode with restart"""
     nr_points = 20
     dim = 3
     points = np.random.random((nr_points, dim))
     inc_hull = qhull.ConvexHull(points[:dim+1, :], incremental=True)
     inc_restart_hull = qhull.ConvexHull(points[:dim+1, :], incremental=True)
     for i in range(dim+1, nr_points):
         hull = qhull.ConvexHull(points[:i+1, :])
         inc_hull.add_points(points[i:i+1, :])
         inc_restart_hull.add_points(points[i:i+1, :], restart=True)
         assert_allclose(hull.volume, inc_hull.volume, rtol=1e-7)
         assert_allclose(hull.volume, inc_restart_hull.volume, rtol=1e-7)
         assert_allclose(hull.area, inc_hull.area, rtol=1e-7)
         assert_allclose(hull.area, inc_restart_hull.area, rtol=1e-7)
Beispiel #5
0
def test_convex(points, bpoints, radius=0.0):
    is_convex = True
    # compute the convex hull of the region
    try:
        hull = qhull.ConvexHull(points)
        qhull_success = True
    except:
        # qhull can fail if the points are all on the same line
        # if we have five points on the same line,
        # these are note the drones we're looking for
        qhull_success = False
        is_convex = False

    # turn into a matplotib polygon
    if qhull_success:
        vertices = [[points[v, 0], points[v, 1]] for v in hull.vertices]
        # add dummy endpoint (ignored but used to close polygon)
        vertices.append(vertices[-1])
        codes = np.ones(len(vertices)) * mplPath.Path.LINETO
        codes[0] = mplPath.Path.MOVETO
        codes[-1] = mplPath.Path.CLOSEPOLY
        bbPath = mplPath.Path(vertices, codes)

        for bpt in bpoints:
            # the hull should not contain any of the boundary points
            if bbPath.contains_point(bpt, radius=radius):
                is_convex = False
                # need to get rid of the most recently added point,
                # which is the one responsible for breaking convexity
    #print 'test_convex:', is_convex
    return is_convex
Beispiel #6
0
    def test_volume_area(self):
        # Basic check that we get back the correct volume and area for a cube
        points = np.array([(0, 0, 0), (0, 1, 0), (1, 0, 0), (1, 1, 0),
                           (0, 0, 1), (0, 1, 1), (1, 0, 1), (1, 1, 1)])
        tri = qhull.ConvexHull(points)

        assert_allclose(tri.volume, 1., rtol=1e-14)
        assert_allclose(tri.area, 6., rtol=1e-14)
Beispiel #7
0
    def test_incremental(self, name):
        # Test incremental construction of the convex hull
        chunks, _ = INCREMENTAL_DATASETS[name]
        points = np.concatenate(chunks, axis=0)

        obj = qhull.ConvexHull(chunks[0], incremental=True)
        for chunk in chunks[1:]:
            obj.add_points(chunk)

        obj2 = qhull.ConvexHull(points)

        obj3 = qhull.ConvexHull(chunks[0], incremental=True)
        if len(chunks) > 1:
            obj3.add_points(np.concatenate(chunks[1:], axis=0), restart=True)

        # Check that the incremental mode agrees with upfront mode
        assert_hulls_equal(points, obj.simplices, obj2.simplices)
        assert_hulls_equal(points, obj.simplices, obj3.simplices)
    def test_volume_area(self):
        #Basic check that we get back the correct volume and area for a cube
        points = np.array([(0, 0, 0), (0, 1, 0), (1, 0, 0), (1, 1, 0),
                           (0, 0, 1), (0, 1, 1), (1, 0, 1), (1, 1, 1)])
        hull = qhull.ConvexHull(points)

        assert_allclose(hull.volume, 1., rtol=1e-14,
                        err_msg="Volume of cube is incorrect")
        assert_allclose(hull.area, 6., rtol=1e-14,
                        err_msg="Area of cube is incorrect")
Beispiel #9
0
 def test_good2d(self, incremental):
     # Make sure the QGn option gives the correct value of "good".
     points = np.array([[0.2, 0.2], [0.2, 0.4], [0.4, 0.4], [0.4, 0.2],
                        [0.3, 0.6]])
     hull = qhull.ConvexHull(points=points,
                             incremental=incremental,
                             qhull_options='QG4')
     expected = np.array([False, True, False, False], dtype=bool)
     actual = hull.good
     assert_equal(actual, expected)
Beispiel #10
0
 def test_good2d_inside(self, incremental):
     # Make sure the QGn option gives the correct value of "good".
     # When point n is inside the convex hull of the rest, good is
     # all False.
     points = np.array([[0.2, 0.2], [0.2, 0.4], [0.4, 0.4], [0.4, 0.2],
                        [0.3, 0.3]])
     hull = qhull.ConvexHull(points=points,
                             incremental=incremental,
                             qhull_options='QG4')
     expected = np.array([False, False, False, False], dtype=bool)
     actual = hull.good
     assert_equal(actual, expected)
Beispiel #11
0
    def test_vertices_2d(self):
        # The vertices should be in counterclockwise order in 2-D
        np.random.seed(1234)
        points = np.random.rand(30, 2)

        hull = qhull.ConvexHull(points)
        assert_equal(np.unique(hull.simplices), np.sort(hull.vertices))

        # Check counterclockwiseness
        x, y = hull.points[hull.vertices].T
        angle = np.arctan2(y - y.mean(), x - x.mean())
        assert_(np.all(np.diff(np.unwrap(angle)) > 0))
Beispiel #12
0
        def check(name):
            points = DATASETS[name]

            tri = qhull.Delaunay(points)
            hull = qhull.ConvexHull(points)

            assert_hulls_equal(points, tri.convex_hull, hull.simplices)

            # Check that the hull extremes are as expected
            if points.shape[1] == 2:
                assert_equal(np.unique(hull.simplices), np.sort(hull.vertices))
            else:
                assert_equal(np.unique(hull.simplices), hull.vertices)
Beispiel #13
0
 def test_good2d_no_option(self, incremental):
     # handle case where good attribue doesn't exist
     # because Qgn or Qg-n wasn't specified
     points = np.array([[0.2, 0.2], [0.2, 0.4], [0.4, 0.4], [0.4, 0.2],
                        [0.3, 0.6]])
     hull = qhull.ConvexHull(points=points, incremental=incremental)
     actual = hull.good
     assert actual is None
     # preserve None after incremental addition
     if incremental:
         hull.add_points(np.zeros((1, 2)))
         actual = hull.good
         assert actual is None
Beispiel #14
0
        def check(name, chunksize):
            points = DATASETS[name]
            ndim = points.shape[1]

            if name == 'pathological-1':
                # include enough points so that we get different x-coordinates
                nmin = 12
            else:
                nmin = ndim +2

            obj = qhull.ConvexHull(points[:nmin], incremental=True)
            for j in xrange(nmin, len(points), chunksize):
                obj.add_points(points[j:j+chunksize])

            obj2 = qhull.ConvexHull(points)

            obj3 = qhull.ConvexHull(points[:nmin], incremental=True)
            obj3.add_points(points[nmin:], restart=True)

            # Check that the incremental mode agrees with upfront mode
            assert_hulls_equal(points, obj.simplices, obj2.simplices)
            assert_hulls_equal(points, obj.simplices, obj3.simplices)
Beispiel #15
0
 def test_good3d(self, incremental):
     # Make sure the QGn option gives the correct value of "good"
     # for a 3d figure
     points = np.array([[0.0, 0.0, 0.0],
                        [0.90029516, -0.39187448, 0.18948093],
                        [0.48676420, -0.72627633, 0.48536925],
                        [0.57651530, -0.81179274, -0.09285832],
                        [0.67846893, -0.71119562, 0.18406710]])
     hull = qhull.ConvexHull(points=points,
                             incremental=incremental,
                             qhull_options='QG0')
     expected = np.array([True, False, False, False], dtype=bool)
     assert_equal(hull.good, expected)
Beispiel #16
0
 def test_good2d_incremental_changes(self, new_gen, expected, visibility):
     # use the usual square convex hull
     # generators from test_good2d
     points = np.array([[0.2, 0.2], [0.2, 0.4], [0.4, 0.4], [0.4, 0.2],
                        [0.3, 0.6]])
     hull = qhull.ConvexHull(points=points,
                             incremental=True,
                             qhull_options=visibility)
     hull.add_points(new_gen)
     actual = hull.good
     if '-' in visibility:
         expected = np.invert(expected)
     assert_equal(actual, expected)
Beispiel #17
0
    def test_hull_consistency_tri(self, name):
        # Check that a convex hull returned by qhull in ndim
        # and the hull constructed from ndim delaunay agree
        points = DATASETS[name]

        tri = qhull.Delaunay(points)
        hull = qhull.ConvexHull(points)

        assert_hulls_equal(points, tri.convex_hull, hull.simplices)

        # Check that the hull extremes are as expected
        if points.shape[1] == 2:
            assert_equal(np.unique(hull.simplices), np.sort(hull.vertices))
        else:
            assert_equal(np.unique(hull.simplices), hull.vertices)
    def test_random_volume_area(self):
        #Test that the results for a random 10-point convex are
        #coherent with the output of qconvex Qt s FA
        points = np.array([(0.362568364506, 0.472712355305, 0.347003084477),
                           (0.733731893414, 0.634480295684, 0.950513180209),
                           (0.511239955611, 0.876839441267, 0.418047827863),
                           (0.0765906233393, 0.527373281342, 0.6509863541),
                           (0.146694972056, 0.596725793348, 0.894860986685),
                           (0.513808585741, 0.069576205858, 0.530890338876),
                           (0.512343805118, 0.663537132612, 0.037689295973),
                           (0.47282965018, 0.462176697655, 0.14061843691),
                           (0.240584597123, 0.778660020591, 0.722913476339),
                           (0.951271745935, 0.967000673944, 0.890661319684)])

        hull = qhull.ConvexHull(points)
        assert_allclose(hull.volume, 0.14562013, rtol=1e-07,
                        err_msg="Volume of random polyhedron is incorrect")
        assert_allclose(hull.area, 1.6670425, rtol=1e-07,
                        err_msg="Area of random polyhedron is incorrect")
Beispiel #19
0
 def _construct_hull(properties):
     """ Returns points on convex hull. """
     hull = qhull.ConvexHull(properties.coords)
     return hull.points[hull.vertices].astype(int).tolist()
ha = hexgrid.HexArray(shape=(10, 10))
pos = np.array([ha.pos(n) for n in range(ha.N)])
x, y = pos.T
nmid = ha.N / 2 + ha.Nx / 2
r = -np.sqrt((x - x[nmid])**2 + (y - y[nmid])**2)
mask = r <= 3
plt.scatter(*pos.T, c=mask, cmap='Greys')
hr = hexgrid.HexArrayRegion(ha)

bpos = np.array([ha.pos(n) for n in hr.interior_boundary()])
ebpos = np.array([ha.pos(n) for n in hr.exterior_boundary()])
plt.scatter(*bpos.T, c='m')
plt.scatter(*ebpos.T, c='c')

hull = qhull.ConvexHull(bpos)
hv = np.hstack([hull.vertices, hull.vertices[0]])
plt.plot(*hull.points[hv].T, color='k')


def pnpoly(vertx, verty, testx, testy):
    nvert = len(vertx)
    i = 0
    j = nvert - 1
    c = False
    while (i < nvert):
        #for (i = 0, j = nvert-1; i < nvert; j = i++) {
        if (((verty[i] > testy) != (verty[j] > testy))
                and (testx < (vertx[j] - vertx[i]) * (testy - verty[i]) /
                     (verty[j] - verty[i]) + vertx[i])):
            c = not c