Exemple #1
0
def run(starter):
    """This function goes through the complete Pychop3D process, including the beam search for the optimal
    cutting planes, determining the connector locations, adding the connectors to the part meshes, then saving the
    STLs, the tree json and the configuration file.

    :param starter: Either an unpartitioned mesh or an already partitioned tree to begin the process using
    :type starter: `trimesh.Trimesh`
    :type starter: `bsp_tree.BSPTree`
    """
    config = Configuration.config
    # basic logging setup
    logging.basicConfig(
        level=logging.INFO,
        format="%(asctime)s  %(name)s  [%(levelname)s]  %(message)s",
        handlers=[
            logging.FileHandler(os.path.join(config.directory, "info.log")),
            logging.StreamHandler()
        ])
    # mark starting time
    t0 = time.time()
    # complete the beam search using the starter, no search will take place if the starter tree is already
    # adequately partitioned
    tree = beam_search(starter)
    logger.info(f"Best BSP-tree found in {time.time() - t0} seconds")
    # save the tree now in case the connector placement fails
    utils.save_tree(tree, "final_tree.json")

    # mark starting time
    t0 = time.time()
    logger.info("finding best connector arrangement")
    # create connector placer object, this creates all potential connectors and determines their collisions
    connector_placer = connector.ConnectorPlacer(tree)
    if connector_placer.n_connectors > 0:
        # use simulated annealing to determine the best combination of connectors
        state = connector_placer.simulated_annealing_connector_placement()
        logger.info(
            f"Best connector arrangement found in {time.time() - t0} seconds")
        # save the final tree including the state
        utils.save_tree(tree, "final_tree_with_connectors.json", state)
        # add the connectors / subtract the slots from the parts of the partitioned input object
        logger.info(f"inserting {state.sum()} connectors...")
        tree = connector_placer.insert_connectors(tree, state)

    # export the parts of the partitioned object
    utils.export_tree_stls(tree)
    logger.info("Finished")
Exemple #2
0
def test_sa_objective_2():
    """Verifies:
        - large faces prefer multiple connectors
    """
    config = Configuration.config
    config.connector_spacing = 5
    mesh = trimesh.primitives.Box(extents=[30, 30, 80])
    tree = bsp_tree.BSPTree(mesh)
    normal = np.array([0, 0, 1])
    origin = np.zeros(3)
    tree = bsp_tree.expand_node(tree, tree.nodes[0].path, (origin, normal))
    connector_placer = connector.ConnectorPlacer(tree)

    # single connector
    state = np.zeros(connector_placer.n_connectors, dtype=bool)
    state[12] = True
    ob1 = connector_placer.evaluate_connector_objective(state)

    # double connector in opposite corners
    state = np.zeros(connector_placer.n_connectors, dtype=bool)
    state[0] = True
    state[24] = True
    ob2 = connector_placer.evaluate_connector_objective(state)

    # connector in each corner
    state = np.zeros(connector_placer.n_connectors, dtype=bool)
    state[0] = True
    state[4] = True
    state[20] = True
    state[24] = True
    ob3 = connector_placer.evaluate_connector_objective(state)

    # connector in each corner and in middle (too many connectors)
    state = np.zeros(connector_placer.n_connectors, dtype=bool)
    state[0] = True
    state[4] = True
    state[12] = True
    state[20] = True
    state[24] = True
    ob4 = connector_placer.evaluate_connector_objective(state)

    assert ob1 > ob2 > ob3
    assert ob4 > ob3

    config.restore_defaults()
Exemple #3
0
def test_sa_objective_2(config):
    """Verifies:
        - large faces prefer multiple connectors

        NOTE: every time grid_sample code changes, this will need to be changed which obviously isnt ideal
    """
    config.connector_spacing = 5
    mesh = trimesh.primitives.Box(extents=[30, 30, 80])
    tree = bsp_tree.BSPTree(mesh)
    normal = np.array([0, 0, 1])
    origin = np.zeros(3)
    tree, result = bsp_tree.expand_node(tree, tree.nodes[0].path,
                                        (origin, normal))
    connector_placer = connector.ConnectorPlacer(tree)

    # single connector
    state = np.zeros(connector_placer.n_connectors, dtype=bool)
    state[12] = True
    ob1 = connector_placer.evaluate_connector_objective(state)

    # double connector in opposite corners
    state = np.zeros(connector_placer.n_connectors, dtype=bool)
    state[0] = True
    state[24] = True
    ob2 = connector_placer.evaluate_connector_objective(state)

    # connector in each corner
    state = np.zeros(connector_placer.n_connectors, dtype=bool)
    state[0] = True
    state[4] = True
    state[20] = True
    state[24] = True
    ob3 = connector_placer.evaluate_connector_objective(state)

    # connector in each corner and in middle (too many connectors)
    state = np.zeros(connector_placer.n_connectors, dtype=bool)
    state[0] = True
    state[4] = True
    state[12] = True
    state[20] = True
    state[24] = True
    ob4 = connector_placer.evaluate_connector_objective(state)

    assert ob1 > ob2 > ob3
    assert ob4 > ob3
Exemple #4
0
def test_sa_objective_1():
    """Verifies:
        - connected components without a connector are penalized
        - small connected components with a single connector have a reasonably low objective
        - connected components with a connector collision are penalized
    """
    config = Configuration.config
    mesh = trimesh.primitives.Box(extents=[10, 10, 40])
    tree = bsp_tree.BSPTree(mesh)
    normal = np.array([0, 0, 1])
    origin = np.zeros(3)
    tree = bsp_tree.expand_node(tree, tree.nodes[0].path, (origin, normal))
    connector_placer = connector.ConnectorPlacer(tree)
    assert connector_placer.evaluate_connector_objective(np.array([False, False])) >= 1 / config.empty_cc_penalty
    ob2 = connector_placer.evaluate_connector_objective(np.array([False, True]))
    ob3 = connector_placer.evaluate_connector_objective(np.array([True, False]))
    assert ob2 == ob3
    assert ob2 < 5
    assert connector_placer.evaluate_connector_objective(np.array([True, True])) >= config.connector_collision_penalty
Exemple #5
0
def main(mesh_filepath):

    # set configuration options
    config = Configuration.config
    config.name = 'output'
    config.mesh = mesh_filepath
    config.beam_width = 3
    config.connector_diameter = 6
    config.connector_spacing = 10
    config.part_separation = True
    config.scale_factor = 5
    config.save()

    # open the input mesh as the starter
    starter = utils.open_mesh()

    # separate pieces
    if config.part_separation and starter.body_count > 1:
        starter = utils.separate_starter(starter)

    # complete the beam search using the starter, no search will take place if the starter tree is adequately partitioned
    tree = beam_search(starter)
    # save the tree now in case the connector placement fails
    utils.save_tree(tree, "final_tree.json")

    try:
        # mark starting time
        t0 = time.time()
        # create connector placer object, this creates all potential connectors and determines their collisions
        connector_placer = connector.ConnectorPlacer(tree)
        if connector_placer.n_connectors > 0:
            # use simulated annealing to determine the best combination of connectors
            state = connector_placer.simulated_annealing_connector_placement()
            # save the final tree including the state
            utils.save_tree(tree, "final_tree_with_connectors.json", state)
            # add the connectors / subtract the slots from the parts of the partitioned input object
            tree = connector_placer.insert_connectors(tree, state)
    except Exception as e:
        # fail gently so that the STLs still get exported
        warnings.warn(e, Warning, stacklevel=2)

    # export the parts of the partitioned object
    utils.export_tree_stls(tree)
Exemple #6
0
def run(starter):
    """This function goes through the complete Pychop3D process, including the beam search for the optimal
    cutting planes, determining the connector locations, adding the connectors to the part meshes, then saving the
    STLs, the tree json and the configuration file.

    :param starter: Either an unpartitioned mesh or an already partitioned tree to begin the process using
    :type starter: `trimesh.Trimesh`
    :type starter: `bsp_tree.BSPTree`
    """
    # mark starting time
    t0 = time.time()
    # complete the beam search using the starter, no search will take place if the starter tree is already
    # adequately partitioned
    tree = beam_search(starter)
    logger.info(f"Best BSP-tree found in {time.time() - t0} seconds")
    # save the tree now in case the connector placement fails
    utils.save_tree(tree, "final_tree.json")

    try:
        # mark starting time
        t0 = time.time()
        # create connector placer object, this creates all potential connectors and determines their collisions
        connector_placer = connector.ConnectorPlacer(tree)
        if connector_placer.n_connectors > 0:
            # use simulated annealing to determine the best combination of connectors
            state = connector_placer.simulated_annealing_connector_placement()
            # save the final tree including the state
            utils.save_tree(tree, "final_tree_with_connectors.json", state)
            # add the connectors / subtract the slots from the parts of the partitioned input object
            tree = connector_placer.insert_connectors(tree, state)
        logger.info(
            f"Best connector arrangement found in {time.time() - t0} seconds")
    except Exception as e:
        # fail gently so that the STLs still get exported
        logger.error("Connector placement failed")
        logger.error(e)

    # export the parts of the partitioned object
    utils.export_tree_stls(tree)
    logger.info("Finished")
Exemple #7
0
import time
import logging

from pychop3d import utils
from pychop3d import connector
from pychop3d.configuration import Configuration

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s  %(name)s  [%(levelname)s]  %(message)s",
    handlers=[logging.StreamHandler()])

Configuration.config = Configuration(
    "C:\\Users\\Greg\\Documents\\things\\table\\config.yml")
tree_file = "C:\\Users\\Greg\\Documents\\things\\table\\table_platform_20200503_040048\\final_tree_with_connectors.json"
tree = utils.open_tree(tree_file)
connector_placer = connector.ConnectorPlacer(tree)
state = utils.load_connector_configuration(tree_file)
tree = connector_placer.insert_connectors(tree, state)

utils.export_tree_stls(tree)