def __init__(self, db_file, title=None): try: self.db_fp = None if os.path.isfile(db_file): self.db_ip = libwdb.db_open(db_file, "r+w") if self.db_ip == libwdb.DBI_NULL: raise BRLCADException( "Can't open existing DB file: <{0}>".format(db_file)) if libwdb.db_dirbuild(self.db_ip) < 0: raise BRLCADException( "Failed loading directory of DB file: <{}>".format( db_file)) self.db_fp = libwdb.wdb_dbopen(self.db_ip, libwdb.RT_WDB_TYPE_DB_DISK) if self.db_fp == libwdb.RT_WDB_NULL: raise BRLCADException( "Failed read existing DB file: <{}>".format(db_file)) if not self.db_fp: self.db_fp = libwdb.wdb_fopen(db_file) if self.db_fp == libwdb.RT_WDB_NULL: raise BRLCADException( "Failed creating new DB file: <{}>".format(db_file)) self.db_ip = self.db_fp.contents.dbip if title: libwdb.mk_id(self.db_fp, title) except Exception as e: raise BRLCADException("Can't open DB file <{0}>: {1}".format( db_file, e))
def test_direct_calls(self): db_name = "direct_empty_db.g" if os.path.isfile(db_name): os.remove(db_name) # first time the DB is created: db_fp = libwdb.wdb_fopen(db_name) if db_fp == libwdb.RT_WDB_NULL: raise BRLCADException( "Failed creating new DB file: <{}>".format(db_name)) db_ip = db_fp.contents.dbip self.check_empty_db(db_ip) libwdb.wdb_close(db_fp) # second time the DB exists and it is re-opened: db_ip = libwdb.db_open(db_name, "r+w") if db_ip == libwdb.DBI_NULL: raise BRLCADException( "Can't open existing DB file: <{0}>".format(db_name)) if libwdb.db_dirbuild(db_ip) < 0: raise BRLCADException( "Failed loading directory of DB file: <{}>".format(db_name)) self.db_fp = libwdb.wdb_dbopen(db_ip, libwdb.RT_WDB_TYPE_DB_DISK) if self.db_fp == libwdb.RT_WDB_NULL: raise BRLCADException( "Failed read existing DB file: <{}>".format(db_name)) self.check_empty_db(db_ip)
def create_property(name, context, param_wrapper, calc_func=None, doc=None): """ Creates calculated properties of a geometry class. The returned property uses <calc_func> to calculate the value of the property. The value is only calculated once and cached for further access. This call also populates the calc_function_map and param_wrappers maps which allow programmatic access to the parameter handling. If calc_func is not provided, it will be looked up in the context as "_calculate_<name>", and if found, that one will be used. If there's no function with that name, the property will not be calculated, but must be initialized, making it a mandatory parameter of the geometry object. """ param_wrappers = context.get("param_wrappers") calc_function_map = context.get("calc_function_map") if param_wrappers is None or calc_function_map is None: raise BRLCADException( "GeometryObject subclasses must define the class properties: " "param_wrappers, calc_function_map") if name in calc_function_map or name in param_wrappers: raise BRLCADException( "Programmer error: duplicate parameter name {}".format(name)) param_wrappers[name] = param_wrapper if not calc_func: calc_func = context.get("_calculate_{}".format(name)) if calc_func: if calc_func in calc_function_map.values(): raise BRLCADException( "Programmer error: function {} is set up for parameter {}". format(calc_func, name)) calc_function_map[name] = calc_func if not doc: doc = getattr(calc_func, "__doc__", None) def getter(self): if self._param_status.get(name) is Calculating: return None value = self._props.get(name) if value is None: self._param_status[name] = Calculating if calc_func: value = calc_func(self) else: raise ValueError( "Mandatory parameter <{}> missing for: {}".format( name, self)) if value is None: raise ValueError( "Not enough information to calculate <{}> for: {}".format( name, self)) self._props[name] = value self._param_status[name] = Calculated return value return property(fget=getter, doc=doc)
def __new__(cls, node): if not isinstance(node, librt.union_tree): raise BRLCADException( "It's not possible to instantiate this class directly, use one of it's subclasses" ) op_class = OP_MAP.get(node.tr_a.tu_op) if not op_class: raise BRLCADException("Invalid operation code: {0}".format( node.tr_a.tu_op)) return op_class(node)
def add_face(self, face): if self.mode == 1 or self.mode == 2: if isinstance(face, Face): self.faces.append(face) else: raise BRLCADException("Invalid face type") elif self.mode == 3 or self.mode == 4: if isinstance(face, PlateFace): self.faces.append(face) else: raise BRLCADException("Invalid face type") else: raise BRLCADException("Invalid mode")
def points(p, point_count=None, point_size=3): if point_count == 0: return None fp = [x for x in iterate_numbers(p)] double_count = len(fp) if point_count is not None: expected_count = point_count * point_size if expected_count != double_count: raise BRLCADException("Expected {} doubles, got: {}".format( expected_count, double_count)) if double_count % point_size != 0: raise BRLCADException("Expected {}-tuples, got {} doubles !".format( point_size, double_count)) return ctypes.cast((ctypes.c_double * double_count)(*fp), ctypes.POINTER(ctypes.c_double * point_size))
def ged_open(file_name, dbtype=DBType.DB, existing_only=True): global _GED_INSTANCE ged_pointer = GED(file_name, dbtype=dbtype, existing_only=existing_only) if not ged_pointer: raise BRLCADException("Failed opening {}".format(file_name)) if _GED_INSTANCE: old_instance = _GED_INSTANCE _GED_INSTANCE = None try: old_instance.close() except: ged_pointer.close() raise BRLCADException("Error closing open GED: {}".format( old_instance.file_name)) _GED_INSTANCE = ged_pointer
def wrapper_func(mk_func): if primitive_class == primitives.Primitive: pass elif SAVE_MAP.has_key( primitive_class) and SAVE_MAP[primitive_class] != mk_func: raise BRLCADException( "Bad setup, multiple save functions ({}, {}) assigned to primitive: {}" .format(mk_func, SAVE_MAP[primitive_class], primitive_class)) else: def wrapped_func(db_self, *args, **kwargs): if len(args) == 1 and isinstance(args[0], primitives.Primitive): shape = args[0] if not isinstance(shape, primitive_class): raise ("{0} expects primitive of type {1} but got {2}". format(mk_func.func_name, primitive_class, type(shape))) shape.update_params(kwargs) mk_func(db_self, shape.name, **kwargs) else: mk_func(db_self, *args, **kwargs) SAVE_MAP[primitive_class] = wrapped_func return mk_func
def create_primitive(type_id, db_internal, directory): # TODO: research if this method won't cause a memory leak # because python will not free the structures received here name = str(directory.d_namep) type_info = MAGIC_TO_PRIMITIVE_TYPE.get(type_id) if type_info: magic = type_info[2] struct_type = type_info[3] data = struct_type.from_address(db_internal.idb_ptr) if struct_type else None # the first int32 is always the magic: data_magic = librt.cast(db_internal.idb_ptr, librt.POINTER(librt.c_uint32)).contents.value if magic: if magic != data_magic: raise BRLCADException("Invalid magic value, expected {0} but got {1}".format(magic, data_magic)) else: if type_info[2]: display_type_info = list(type_info) display_type_info[2] = hex(display_type_info[2]) else: display_type_info = type_info warnings.warn("No magic for type: {0}, {1}, {2}".format(type_id, hex(data_magic), display_type_info)) if type_info[1] == Primitive: return Primitive(name=name, primitive_type=type_info[0], data=data) else: return type_info[1].from_wdb(name=name, data=data) else: return Primitive(name=name, primitive_type="UNKNOWN")
def __init__(self, name, curves, copy=False): Primitive.__init__(self, name=name) if test_curves(curves): if copy: self.curves = [curve[:] for curve in curves] else: self.curves = curves else: raise BRLCADException("Invalid Curve Data in Ars")
def direction(d): fp = [x for x in iterate_numbers(d)] double_count = len(fp) if double_count == 3: return (ctypes.c_double * 3)(*fp) elif double_count == 6: return (ctypes.c_double * 3)(fp[3] - fp[0], fp[4] - fp[1], fp[5] - fp[2]) else: raise BRLCADException( "Expected 3 oder 6 doubles, got: {0}".format(double_count))
def transform(t, use_brlcad_malloc=False): """ Serializes a Transform-like object 't' (can be anything which will provide 16 floats) to the ctypes form of a transformation matrix as used by BRL-CAD code. """ fp = [x for x in iterate_numbers(t)] if len(fp) != 16: raise BRLCADException("Expected 16 doubles, got: {0}".format(len(fp))) result = (ctypes.c_double * 16)(*fp) if use_brlcad_malloc: result = brlcad_copy(result, "transform") return result
def __init__(self, bot, vertices, index=None, copy=False): self.bot = bot self._points = list( vertices) if copy or not isinstance(vertices, list) else vertices if index == None: if len(vertices) == 3: self.index = [] for i in range(0, len(self._points)): self.index.append(bot.vertex_index(self._points[i])) else: raise BRLCADException("A face requires 3 vertices") else: self.index = index
def __new__(cls, *args): if len(args) == 1 and isinstance(args[0], librt.union_tree): node = args[0] left = TreeNode(node.tr_b.tb_left.contents) right = TreeNode(node.tr_b.tb_right.contents) elif len(args) == 2: left = wrap_tree(args[0]) right = wrap_tree(args[1]) else: raise BRLCADException("{0} needs 2 arguments !".format(cls)) result = object.__new__(cls) result.left = left result.right = right result.symbol = cls.symbol return result
def doubles(p, double_count=None, flatten=True): if double_count == 0: return None if not p: if double_count is None: return None actual_count = 0 else: if flatten: p = [x for x in iterate_numbers(p)] actual_count = len(p) if double_count is not None and double_count != actual_count: raise BRLCADException("Expected {0} doubles, got: {1}".format( double_count, actual_count)) if actual_count == 0: return None return (ctypes.c_double * actual_count)(*p)
def iterate_numbers(container): """ Iterator which flattens nested hierarchies of geometry to plain list of numbers. Some examples: >>> [x for x in iterate_numbers(2)] [2] >>> [x for x in iterate_numbers([3])] [3] >>> [x for x in iterate_numbers([(1,2,3),(4,5,6)])] [1, 2, 3, 4, 5, 6] """ if isinstance(container, Number): yield container elif isinstance(container, np.ndarray): for x in container.flat: yield x elif isinstance(container, Iterable): for p in container: for x in iterate_numbers(p): yield x else: raise BRLCADException("Can't extract numbers from type: {0}".format( type(container)))
def _execute_ged_command(ged_func, *args, **kwargs): if not _GED_INSTANCE: raise BRLCADException("GED is not yet open !") ged_func(_GED_INSTANCE, *args, **kwargs)
def __init__(self, file_name, dbtype=DBType.DB, existing_only=True): self.file_name = file_name result = libged.ged_open(dbtype, file_name, cta.bool(existing_only)) if not result: raise BRLCADException("Error creating GED !") self._ged_pointer = result
def has_same_data(self, other): raise BRLCADException("Primitive subclass {} does not implement has_same_data !".format(self.__class__))
def copy(self): raise BRLCADException("Primitive subclass {} does not implement copy !".format(self.__class__))
def plane(p): fp = [x for x in iterate_numbers(p)] if len(fp) != 4: raise BRLCADException("Expected 4 doubles, got: {0}".format(len(fp))) return (ctypes.c_double * 4)(*fp)
def point(p, point_size=3): fp = [x for x in iterate_numbers(p)] if point_size != len(fp): raise BRLCADException("Expected {0} doubles, got: {1}".format( point_size, len(fp))) return (ctypes.c_double * point_size)(*fp)
def from_wdb(name, data): raise BRLCADException( "Bad setup in primitives/table.py for name: {}, data: {}, the from_wdb method must be overridden !".format( name, data ) )