def check_inside(entities): """Heuristic check on whether an entity[0] is inside entity[1] if in some 2d slice, cardinal rays cast from some point in entity[0] all hit a block in entity[1], we say entity[0] is inside entity[1]. This allows an entity to be inside a ring or an open cylinder. This will fail for a "diagonal" ring. TODO: "enclosed", where the object is inside in the topological sense""" locs = [] for e in entities: l = util.get_locs_from_entity(e) if l is not None: locs.append(l) else: # this is not a thing we know how to assign 'inside' to return False for b in locs[0]: for i in range(3): inside = True coplanar = [c for c in locs[1] if c[i] == b[i]] for j in range(2): fixed = (i + 2 * j - 1) % 3 to_check = (i + 1 - 2 * j) % 3 colin = [c[to_check] for c in coplanar if c[fixed] == b[fixed]] if len(colin) == 0: inside = False else: if max(colin) <= b[to_check] or min(colin) >= b[to_check]: inside = False if inside: return True return False
def find_between(entities): """Heurisitc search for points between entities[0] and entities[1] for now : just pick the point half way between their means TODO: fuzz a bit if target is unreachable""" for e in entities: means = [] l = util.get_locs_from_entity(e) if l is not None: means.append(np.mean(l, axis=0)) else: # this is not a thing we know how to assign 'between' to return None return (means[0] + means[1]) / 2
def find_inside(entity): """Return a point inside the entity if it can find one. TODO: heuristic quick check to find that there aren't any, and maybe make this not d^3""" l = util.get_locs_from_entity(entity) if l is None: return None m = np.round(np.mean(l, axis=0)) maxes = np.max(l, axis=0) mins = np.min(l, axis=0) inside = [] for x in range(mins[0], maxes[0] + 1): for y in range(mins[1], maxes[1] + 1): for z in range(mins[2], maxes[2] + 1): if check_inside([(x, y, z), entity]): inside.append((x, y, z)) return sorted(inside, key=lambda x: util.euclid_dist(x, m))
def find_inside(entity): """Return a point inside the entity if it can find one. TODO: heuristic quick check to find that there aren't any, and maybe make this not d^3""" # is this a negative object? if yes, just return its mean: if hasattr(entity, "blocks"): if all(b == (0, 0) for b in entity.blocks.values()): m = np.mean(list(entity.blocks.keys()), axis=0) return [util.to_block_pos(m)] l = util.get_locs_from_entity(entity) if l is None: return None m = np.round(np.mean(l, axis=0)) maxes = np.max(l, axis=0) mins = np.min(l, axis=0) inside = [] for x in range(mins[0], maxes[0] + 1): for y in range(mins[1], maxes[1] + 1): for z in range(mins[2], maxes[2] + 1): if check_inside([(x, y, z), entity]): inside.append((x, y, z)) return sorted(inside, key=lambda x: util.euclid_dist(x, m))
def check_between(entities, fat_scale=0.2): """ Heuristic check if entities[0] is between entities[1] and entities[2] by checking if the locs of enitity[0] are in the convex hull of union of the max cardinal points of entity[1] and entity[2]""" locs = [] means = [] for e in entities: l = util.get_locs_from_entity(e) if l is not None: locs.append(l) means.append(np.mean(l, axis=0)) else: # this is not a thing we know how to assign 'between' to return False mean_separation = util.euclid_dist(means[1], means[2]) fat = fat_scale * mean_separation bounding_locs = [] for l in locs: if len(l) > 1: bl = [] idx = np.argmax(l, axis=0) for i in range(3): f = np.zeros(3) f[i] = fat bl.append(np.array(l[idx[i]]) + fat) idx = np.argmin(l, axis=0) for i in range(3): f = np.zeros(3) f[i] = fat bl.append(np.array(l[idx[i]]) - fat) bounding_locs.append(np.concatenate(bl)) else: bounding_locs.append(np.array(l)) x = np.mean(bounding_locs[0], axis=0) points = np.concatenate(bounding_locs[1], bounding_locs[2]) return in_hull(points, x)