Return the points within the convex hulls of objects
    
    ch_pts - a Nx3 array of columns of label #, i and j as output by convex_hull
    ch_counts - the number of points per object
    
    returns the points in ijv format.
500422
def fill_convex_hulls(ch_pts, ch_counts):
    '''
    '''
    if len(ch_pts) == 0:
        return np.zeros((0,3), int)
    #
    # Connect the last line to the first
    #
    ch_counts = ch_counts[ch_counts != 0]
    indexer_in = Indexes(ch_counts)
    #
    # Get line ends. This involves connecting the last
    # point with the first.
    #
    idx_1 = np.arange(ch_pts.shape[0]) + 1
    idx_1[indexer_in.fwd_idx+indexer_in.counts - 1] = indexer_in.fwd_idx
    ch_pts1 = ch_pts[idx_1, 1:]
    #
    # Get J at each I (floating point) for each line
    # Generate two points (min J, max J) for horizontal lines
    #
    n_i = np.abs(ch_pts[:, 1] - ch_pts1[:, 0]) + 1
    horizontal = n_i == 1
    if (np.any(horizontal)):
        i_horiz = ch_pts[horizontal, 1]
        l_horiz = ch_pts[horizontal, 0]
        j_first_horiz = ch_pts[horizontal, 2]
        j_last_horiz = ch_pts1[horizontal, 1]
    else:
        i_horiz = l_horiz = j_first_horiz = j_last_horiz = np.zeros(0, int)
    
    if (np.any(~ horizontal)):
        ch_pts, ch_pts1, n_i = [x[~horizontal] for x in (ch_pts, ch_pts1, n_i)]
        indexer = Indexes(n_i)
        l = ch_pts[indexer.rev_idx, 0]
        sign = np.sign(ch_pts1[:, 0] - ch_pts[:, 1])
        i = ch_pts[indexer.rev_idx, 1] + sign[indexer.rev_idx] * indexer.idx[0]
        j = ch_pts[indexer.rev_idx, 2] + \
            indexer.idx[0] * (ch_pts1[indexer.rev_idx, 1] - 
                              ch_pts[indexer.rev_idx, 2]).astype(float) / \
            (n_i[indexer.rev_idx] - 1)
    else:
        i = l = np.zeros(0, int)
        j = np.zeros(0)
    line_labels = np.concatenate((l_horiz, l_horiz, l))
    i = np.concatenate((i_horiz, i_horiz, i))
    j = np.concatenate((j_first_horiz.astype(float),
                        j_last_horiz.astype(float), j))
    #
    # Sort by label, then i, then j
    #
    order = np.lexsort((j, i, line_labels))
    i, j, line_labels = i[order], j[order], line_labels[order]
    #
    # Find the min and max j for every i and label. Then we
    # can make runs of them.
    #
    firsts = np.hstack(
        [[0], 
         np.argwhere((line_labels[:-1] != line_labels[1:]) | 
                     (i[:-1] != i[1:])).flatten() + 1, 
         [len(line_labels)]])
    counts = firsts[1:] - firsts[:-1]
    run_indexer = Indexes(counts)
    #
    # Find the first and last J for each i and create rasters of j
    #
    i = i[run_indexer.fwd_idx]
    j0 = np.ceil(j[run_indexer.fwd_idx]).astype(int)
    j1 = np.floor(j[run_indexer.fwd_idx + run_indexer.counts[0]-1]).astype(int)
    l = line_labels[run_indexer.fwd_idx]
    out_indexer = Indexes(j1-j0+1)
    ijv = np.column_stack((
        i[out_indexer.rev_idx], j0[out_indexer.rev_idx]+out_indexer.idx[0],
        l[out_indexer.rev_idx]))
    return ijv
381968
def simplices(self):
        
        return [Simplex([self.points[i] for i in v]) for v in self.vertices]
953422
def _get_coords(self, obj):
        
        xdim, ydim = obj.dimensions(label=True)[:2]
        xcoords = obj.dimension_values(xdim, False)
        ycoords = obj.dimension_values(ydim, False)

        # Determine global orderings of y-values using topological sort
        grouped = obj.groupby(xdim, container_type=OrderedDict,
                              group_type=Dataset).values()
        orderings = OrderedDict()
        sort = True
        for group in grouped:
            vals = group.dimension_values(ydim, False)
            if len(vals) == 1:
                orderings[vals[0]] = [vals[0]]
            else:
                for i in range(len(vals)-1):
                    p1, p2 = vals[i:i+2]
                    orderings[p1] = [p2]
            if sort:
                if vals.dtype.kind in ('i', 'f'):
                    sort = (np.diff(vals)>=0).all()
                else:
                    sort = np.array_equal(np.sort(vals), vals)
        if sort or one_to_one(orderings, ycoords):
            ycoords = np.sort(ycoords)
        elif not is_cyclic(orderings):
            coords = list(itertools.chain(*sort_topologically(orderings)))
            ycoords = coords if len(coords) == len(ycoords) else np.sort(ycoords)
        return xcoords, ycoords
643134
def points(self):
        
        x = vtk_to_numpy(self.GetXCoordinates())
        y = vtk_to_numpy(self.GetYCoordinates())
        z = vtk_to_numpy(self.GetZCoordinates())
        xx, yy, zz = np.meshgrid(x,y,z, indexing='ij')
        return np.c_[xx.ravel(), yy.ravel(), zz.ravel()]
126191
function(points, bbox) {
        var result = [];
        for (var i = 0; i < points.length; i++) {
            var point = points[i];
            if (this.bboxContainsPoint(point, bbox)) {
                result.push(point);
            }
        }
        return result;
    }
899396
static List<Point2D> grahamScan(final List<Point2D> points) {

        if (points.size() <= 3) return new ArrayList<Point2D>(points);

        Collections.sort(points, new CompareYThenX());
        Collections.sort(points, new PolarComparator(points.get(0)));

        Deque<Point2D> hull = new ArrayDeque<Point2D>();

        hull.push(points.get(0));
        hull.push(points.get(1));
        hull.push(points.get(2));

        for (int i = 3; i < points.size(); i++) {
            Point2D top = hull.pop();
            while (!hull.isEmpty() && !isLeftTurn(hull.peek(), top, points.get(i))) {
                top = hull.pop();
            }
            hull.push(top);
            hull.push(points.get(i));
        }

        return new ArrayList<Point2D>(hull);
    }
694626
def within(self, x, ctrs, kdtree=None):
        """"""

        if kdtree is None:
            # If no KDTree is provided, execute a brute-force search
            # over all cubes.
            idxs = np.where(np.max(np.abs(ctrs - x), axis=1) <= self.hside)[0]
        else:
            # If a KDTree is provided, find all points within r (`hside`).
            idxs = kdtree.query_ball_point(x, self.hside, p=np.inf, eps=0)

        return idxs
1356444
def _get_attrs(self):
        """"""
        attrs = []
        attrs.append(("N Cells", self.GetNumberOfCells(), "{}"))
        attrs.append(("N Points", self.GetNumberOfPoints(), "{}"))
        bds = self.bounds
        attrs.append(("X Bounds", (bds[0], bds[1]), "{:.3e}, {:.3e}"))
        attrs.append(("Y Bounds", (bds[2], bds[3]), "{:.3e}, {:.3e}"))
        attrs.append(("Z Bounds", (bds[4], bds[5]), "{:.3e}, {:.3e}"))
        # if self.n_cells <= vtki.REPR_VOLUME_MAX_CELLS and self.n_cells > 0:
        #     attrs.append(("Volume", (self.volume), "{:.3e}"))
        return attrs
403211
def points(self):
        
        if not self._points:
            self._points = MetricPoints(self.api_client)
        return self._points
851510
def points(self, points):
        
        if not isinstance(points, np.ndarray):
            raise TypeError('Points must be a numpy array')
        # get the unique coordinates along each axial direction
        x = np.unique(points[:,0])
        y = np.unique(points[:,1])
        z = np.unique(points[:,2])
        nx, ny, nz = len(x), len(y), len(z)
        # TODO: this needs to be tested (unique might return a tuple)
        dx, dy, dz = np.unique(np.diff(x)), np.unique(np.diff(y)), np.unique(np.diff(z))
        ox, oy, oz = np.min(x), np.min(y), np.min(z)
        # Build the vtk object
        self._from_specs((nx,ny,nz), (dx,dy,dz), (ox,oy,oz))
        #self._point_ref = points
        self.Modified()
846252
def _get_points(self):
        
        return tuple([self._getitem__points(i)
                     for i in range(self._len__points())])
1036156
def referenced_vertices(self):
        
        # no entities no reference
        if len(self.entities) == 0:
            return np.array([], dtype=np.int64)
        referenced = np.concatenate([e.points for e in self.entities])
        referenced = np.unique(referenced.astype(np.int64))

        return referenced
971366
def sortCorners(corners):
    '''
    
    '''
    corners = np.asarray(corners)
    # bring edges in order:
    corners2 = corners[ConvexHull(corners).vertices]
   
    if len(corners2) == 3:
        # sometimes ConvexHull one point is missing because it is
        # within the hull triangle
        # find the right position of set corner as the minimum perimeter
        # built with that point as different indices
        for c in corners:
            if c not in corners2:
                break
        perimeter = []
        for n in range(0, 4):
            corners3 = np.insert(corners2, n, c, axis=0)
            perimeter.append(
                np.linalg.norm(
                    np.diff(
                        corners3,
                        axis=0),
                    axis=1).sum())
        n = np.argmin(perimeter)
        corners2 = np.insert(corners2, n, c, axis=0)

    # find the edge with the right angle to the quad middle:
    mn = corners2.mean(axis=0)
    d = (corners2 - mn)
    ascent = np.arctan2(d[:, 1], d[:, 0])
    bl = np.abs(BL_ANGLE + ascent).argmin()
    # build a index list starting with bl:
    i = list(range(bl, 4))
    i.extend(list(range(0, bl)))
    return corners2[i]
520886
def _points(self, x_pos):
        
        for serie in self.all_series:
            serie.points = [(x_pos[i], v) for i, v in enumerate(serie.values)]
            if serie.points and self.interpolate:
                serie.interpolated = self._interpolate(x_pos, serie.values)
            else:
                serie.interpolated = []
154156
def facets_on_hull(self):
        
        # facets plane, origin and normal
        normals = self.facets_normal
        origins = self.facets_origin

        # (n,3) convex hull vertices
        convex = self.convex_hull.vertices.view(np.ndarray).copy()

        # boolean mask for which facets are on convex hull
        on_hull = np.zeros(len(self.facets), dtype=np.bool)

        for i, normal, origin in zip(range(len(normals)), normals, origins):
            # a facet plane is on the convex hull if every vertex
            # of the convex hull is behind that plane
            # which we are checking with dot products
            dot = np.dot(normal, (convex - origin).T)
            on_hull[i] = (dot < tol.merge).all()

        return on_hull
780567
def getPoints(self, pared=False):
        
        points = self._points[:]
        if pared:
            np = NodePare()
            np.addPoints(points)
            np.parePoints()
            points = np.getParedPoints()

        return points
140967
def multipointz(self, points):
        """"""
        shapeType = MULTIPOINTZ
        points = [points] # nest the points inside a list to be compatible with the generic shapeparts method
        self._shapeparts(parts=points, shapeType=shapeType)