Beispiel #1
0
    def asdf(self, region=None, resolution=None, mm_per_unit=None,
             merge_leafs=True, interrupt=None):
        """ @brief Constructs an ASDF from a math tree.
            @details Runs in up to eight threads.
            @param region Evaluation region (if None, taken from expression bounds)
            @param resolution Render resolution in voxels/unit
            @param mm_per_unit Real-world scale
            @param merge_leafs Boolean determining whether leaf cells are combined
            @param interrupt threading.Event that aborts rendering if set
            @returns ASDF data structure
        """

        if region is None:
            if not self.bounded:
                raise Exception('Unknown render region!')
            elif resolution is None:
                raise Exception('Region or resolution must be provided!')
            region = Region(
                (self.xmin, self.ymin, self.zmin if self.zmin else 0),
                (self.xmax, self.ymax, self.zmax if self.zmax else 0),
                resolution
            )

        if interrupt is None:   interrupt = threading.Event()

        # Shared flag to interrupt rendering
        halt = ctypes.c_int(0)

        # Split the region into up to 8 sections
        split = region.octsect(all=True)
        subregions = [split[i] for i in range(8) if split[i] is not None]
        ids = [i for i in range(8) if split[i] is not None]

        threads = len(subregions)
        clones  = [self.clone() for i in range(threads)]
        packed  = [libfab.make_packed(c.ptr) for c in clones]

        # Generate a root for the tree
        asdf = ASDF(libfab.asdf_root(packed[0], region), color=self.color)

        # Multithread the solver process
        q = Queue.Queue()
        args = zip(packed, ids, subregions, [q]*threads)

        # Helper function to construct a single branch
        def construct_branch(ptree, id, region, queue):
            asdf = libfab.build_asdf(ptree, region, merge_leafs, halt)
            queue.put((id, asdf))

        # Run the constructor in parallel to make the branches
        multithread(construct_branch, args, interrupt, halt)
        for p in packed:    libfab.free_packed(p)

        # Attach the branches to the root
        for s in subregions:
            try:                id, branch = q.get_nowait()
            except Queue.Empty: break
            else:               asdf.ptr.contents.branches[id] = branch
        libfab.get_d_from_children(asdf.ptr)
        libfab.simplify(asdf.ptr, merge_leafs)

        # Set a scale on the ASDF if one was provided
        if mm_per_unit is not None:     asdf.rescale(mm_per_unit)

        return asdf
Beispiel #2
0
    def asdf(self,
             region=None,
             resolution=None,
             mm_per_unit=None,
             merge_leafs=True,
             interrupt=None):
        """ @brief Constructs an ASDF from a math tree.
            @details Runs in up to eight threads.
            @param region Evaluation region (if None, taken from expression bounds)
            @param resolution Render resolution in voxels/unit
            @param mm_per_unit Real-world scale
            @param merge_leafs Boolean determining whether leaf cells are combined
            @param interrupt threading.Event that aborts rendering if set
            @returns ASDF data structure
        """

        if region is None:
            if not self.bounded:
                raise Exception('Unknown render region!')
            elif resolution is None:
                raise Exception('Region or resolution must be provided!')
            region = Region(
                (self.xmin, self.ymin, self.zmin if self.zmin else 0),
                (self.xmax, self.ymax, self.zmax if self.zmax else 0),
                resolution)

        if interrupt is None: interrupt = threading.Event()

        # Shared flag to interrupt rendering
        halt = ctypes.c_int(0)

        # Split the region into up to 8 sections
        split = region.octsect(all=True)
        subregions = [split[i] for i in range(8) if split[i] is not None]
        ids = [i for i in range(8) if split[i] is not None]

        threads = len(subregions)
        clones = [self.clone() for i in range(threads)]
        packed = [libfab.make_packed(c.ptr) for c in clones]

        # Generate a root for the tree
        asdf = ASDF(libfab.asdf_root(packed[0], region), color=self.color)
        asdf.lock.acquire()

        # Multithread the solver process
        q = Queue.Queue()
        args = zip(packed, ids, subregions, [q] * threads)

        # Helper function to construct a single branch
        def construct_branch(ptree, id, region, queue):
            asdf = libfab.build_asdf(ptree, region, merge_leafs, halt)
            queue.put((id, asdf))

        # Run the constructor in parallel to make the branches
        multithread(construct_branch, args, interrupt, halt)
        for p in packed:
            libfab.free_packed(p)

        # Attach the branches to the root
        for s in subregions:
            try:
                id, branch = q.get_nowait()
            except Queue.Empty:
                break
            else:
                # Make sure we didn't get a NULL pointer back
                # (which could occur if the halt flag was raised)
                try:
                    branch.contents
                except ValueError:
                    asdf.lock.release()
                    return None
                asdf.ptr.contents.branches[id] = branch
        libfab.get_d_from_children(asdf.ptr)
        libfab.simplify(asdf.ptr, merge_leafs)
        asdf.lock.release()

        # Set a scale on the ASDF if one was provided
        if mm_per_unit is not None: asdf.rescale(mm_per_unit)

        return asdf