/* A "wrapping" combination is a combination that contains a single object * and does not apply a matrix to it */ int Comb_Is_Wrapper(struct directory *dp, struct rt_wdb *wdbp) { struct rt_db_internal comb_intern; struct rt_db_internal comb_child_intern; struct rt_comb_internal *comb; union tree *child; struct directory *child_dp; int node_count = 0; rt_db_get_internal(&comb_intern, dp, wdbp->dbip, bn_mat_identity, &rt_uniresource); RT_CK_DB_INTERNAL(&comb_intern); if (comb_intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_COMBINATION) { rt_db_free_internal(&comb_intern); return -1; } /* If this comb has more than one child, it isn't a wrapper */ comb = (struct rt_comb_internal *)comb_intern.idb_ptr; if (comb->tree) { node_count = db_count_tree_nodes(comb->tree, 0); if (node_count > 1) { rt_db_free_internal(&comb_intern); return 1; } } else { /* Empty comb */ return -2; } /* If the child doesn't exist, this isn't a wrapper */ child = _db_tree_get_child(comb->tree); child_dp = db_lookup(wdbp->dbip, child->tr_l.tl_name, LOOKUP_QUIET); if (child_dp == RT_DIR_NULL) { rt_db_free_internal(&comb_intern); return 1; } /* If the child is a comb, this isn't a wrapper */ rt_db_get_internal(&comb_child_intern, child_dp, wdbp->dbip, bn_mat_identity, &rt_uniresource); RT_CK_DB_INTERNAL(&comb_child_intern); if (comb_child_intern.idb_minor_type == DB5_MINORTYPE_BRLCAD_COMBINATION) { rt_db_free_internal(&comb_intern); rt_db_free_internal(&comb_child_intern); return 1; } /* If the child has a matrix over it, this isn't a wrapper */ if (child->tr_l.tl_mat) { rt_db_free_internal(&comb_intern); rt_db_free_internal(&comb_child_intern); return 1; } /* If we made it here, we have a wrapper */ rt_db_free_internal(&comb_intern); rt_db_free_internal(&comb_child_intern); return 0; }
/* Convenience function to get a comb child's directory pointer * when it the comb only has one child */ struct directory * Comb_Get_Only_Child(struct directory *dp, struct rt_wdb *wdbp) { struct rt_db_internal comb_intern; struct rt_comb_internal *comb; union tree *child; struct directory *child_dp; int node_count = 0; rt_db_get_internal(&comb_intern, dp, wdbp->dbip, bn_mat_identity, &rt_uniresource); RT_CK_DB_INTERNAL(&comb_intern); if (comb_intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_COMBINATION) { rt_db_free_internal(&comb_intern); return RT_DIR_NULL; } /* If this comb has more than one child, there exists no "only" child */ comb = (struct rt_comb_internal *)comb_intern.idb_ptr; if (comb->tree) { node_count = db_count_tree_nodes(comb->tree, 0); if (node_count > 1) { rt_db_free_internal(&comb_intern); return RT_DIR_NULL; } } else { /* Empty comb - there exists no "only" child */ return RT_DIR_NULL; } /* If the child doesn't exist, there exists no "only" child, so at * this point whatever db_lookup returns is fine */ child = _db_tree_get_child(comb->tree); child_dp = db_lookup(wdbp->dbip, child->tr_l.tl_name, LOOKUP_QUIET); rt_db_free_internal(&comb_intern); return child_dp; }
void pop_gop(int gop, char *parent1_id, char *parent2_id, char *child1_id, char *child2_id, struct db_i *dbi_p, struct db_i *dbi_c, struct resource *resp) { struct rt_db_internal in1, in2; struct rt_comb_internal *parent1; struct rt_comb_internal *parent2; struct directory *dp; union tree *cpoint, **cross_parent; struct node *add; int i = 0; struct node *chosen_node; int rand_node; RT_CHECK_DBI( dbi_p ); RT_CHECK_DBI( dbi_c ); RT_CK_RESOURCE( resp ); crossover_point = (union tree *)NULL; crossover_parent = (union tree **)NULL; node = (struct node*)NULL; if ( !rt_db_lookup_internal(dbi_p, parent1_id, &dp, &in1, LOOKUP_NOISY, &rt_uniresource)) bu_exit(EXIT_FAILURE, "Failed to read parent1"); shape_number =num_nodes= 0; parent1 = (struct rt_comb_internal *)in1.idb_ptr; mutate = 0; switch (gop) { case REPRODUCE: pop_functree(dbi_p, dbi_c, parent1->tree, resp, child1_id); break; case CROSSOVER: crossover = 1; /*load other parent */ if ( !rt_db_lookup_internal(dbi_p, parent2_id, &dp, &in2, LOOKUP_NOISY, resp)) bu_exit(EXIT_FAILURE, "Failed to read parent2"); parent2 = (struct rt_comb_internal *)in2.idb_ptr; BU_ALLOC(node, struct node); BU_LIST_INIT(&node->l); chosen_node = NULL; do{ num_nodes = 0; crossover_parent = &parent1->tree; crossover_node = (int)(pop_rand() * db_count_tree_nodes(parent1->tree, 0)); node_idx = 0; pop_functree(dbi_p, dbi_c, parent1->tree, resp, NULL); cross_parent = crossover_parent; cpoint = crossover_point; crossover_op = crossover_point->tr_op; #define MASK (OP_UNION | OP_XOR | OP_SUBTRACT|OP_INTERSECT) if (crossover_op & MASK)crossover_op = MASK; crossover_node = db_count_tree_nodes(crossover_point, 0); if (pop_find_nodes(parent2->tree) == crossover_node) { BU_ALLOC(add, struct node); add->s_parent = &parent2->tree; add->s_child = parent2->tree; BU_LIST_INSERT(&node->l, &add->l); ++num_nodes; } if (num_nodes > 0) { rand_node = (int)(pop_rand() * num_nodes); for (add=BU_LIST_FIRST(node, &node->l);BU_LIST_NOT_HEAD(add, &node->l) && chosen_node == NULL; add=BU_LIST_PNEXT(node, add)) { if (i++ == rand_node) { chosen_node = add; /* break cleanly...? */ } } } }while(chosen_node == NULL); /* cross trees */ *cross_parent = chosen_node->s_child; *chosen_node->s_parent =cpoint; while (BU_LIST_WHILE(add, node, &node->l)) { BU_LIST_DEQUEUE(&add->l); bu_free(add, "node"); } bu_free(node, "node"); crossover = 0; /*duplicate shapes held in trees*/ pop_functree(dbi_p, dbi_c, parent1->tree, resp, child1_id); shape_number = 0; pop_functree(dbi_p, dbi_c, parent2->tree, resp, child2_id); if ((dp = db_diradd(dbi_c, child2_id, -1, 0, dp->d_flags, (genptr_t)&dp->d_minor_type)) == RT_DIR_NULL) bu_exit(EXIT_FAILURE, "Failed to add new individual to child database"); if (rt_db_put_internal(dp, dbi_c, &in2, resp) < 0) bu_exit(EXIT_FAILURE, "Database write failure"); rt_db_free_internal(&in2); break; case MUTATE: crossover_parent = &parent1->tree; crossover_node = (int)(pop_rand() * db_count_tree_nodes(parent1->tree, 0)); node_idx = 0; mutate = 1; pop_functree(dbi_p, dbi_c, parent1->tree, resp, child1_id); mutate = 0; break; /* //random node to mutate n = (int)(pop_rand() * db_count_tree_nodes(parent1->tree, 0)); s_parent = &parent1->tree; s_node = n; node = 0; //find node pop_functree(dbi_p, dbi_c, parent1->tree, resp, NULL); */ default: bu_exit(EXIT_FAILURE, "illegal genetic operator\nfailed to execute genetic op"); } if ((dp=db_diradd(dbi_c, child1_id, -1, 0, dp->d_flags, (genptr_t)&dp->d_minor_type)) == RT_DIR_NULL) { bu_exit(EXIT_FAILURE, "Failed to add new individual to child database"); } if (rt_db_put_internal(dp, dbi_c, &in1, resp) < 0) bu_exit(EXIT_FAILURE, "Database write failure"); rt_db_free_internal(&in1); }