static Node * SubtreeInsert(Node *subtree, Node *leaf, cpBBTree *tree) { if(subtree == NULL){ return leaf; } else if(NodeIsLeaf(subtree)){ return NodeNew(tree, leaf, subtree); } else { cpFloat cost_a = cpBBArea(subtree->B->bb) + cpBBMergedArea(subtree->A->bb, leaf->bb); cpFloat cost_b = cpBBArea(subtree->A->bb) + cpBBMergedArea(subtree->B->bb, leaf->bb); if(cost_a == cost_b){ cost_a = cpBBProximity(subtree->A->bb, leaf->bb); cost_b = cpBBProximity(subtree->B->bb, leaf->bb); } if(cost_b < cost_a){ NodeSetB(subtree, SubtreeInsert(subtree->B, leaf, tree)); } else { NodeSetA(subtree, SubtreeInsert(subtree->A, leaf, tree)); } subtree->bb = cpBBMerge(subtree->bb, leaf->bb); return subtree; } }
void NodeConstruct(Node ** root, void * pointer, int type ){ Node * node; node = NodeNew( ); node->p = pointer; node->type = type; ADD( (*root), node); }
void EermMaxNodeNew(EermMax *m, Symbol *msg, short ac, Atom *av) { int i; MTraceCall("eermMax:\tNodeNew."); MErrorVoid((m != NULL) && (msg != NULL) && (av != NULL), "Missing argument"); MErrorVoid (ac == 1, "wrong num args to NodeNew"); i = EermNodeAdd(m->e, NodeNew(m->e->Nn, m->e->tmpnode->Nf, m->e->NnMax)); MErrorVoid(i >= 0, "Max Nnodes reached."); MTrace4("eermMax:\tNodeNew: Index=%d, Nn=%d, Nf=%d, NnMax=%d", i, m->e->Nn, m->e->tmpnode->Nf, m->e->NnMax); //Set Node Label MErrorVoid(av[0].a_type == A_SYM, "Node Label expected"); EermMaxNodeSetLabel(m, i, av[0].a_w.w_sym->s_name); MTraceCall("eermMax:\tNodeNew finished.."); // Note: don't bother to set tp here, since we connect simplices, not nodes. // node->tp is not important for the present application. (perhaps later.) }
static Node * partitionNodes(cpBBTree *tree, Node **nodes, int count) { if(count == 1){ return nodes[0]; } else if(count == 2) { return NodeNew(tree, nodes[0], nodes[1]); } // Find the AABB for these nodes cpBB bb = nodes[0]->bb; for(int i=1; i<count; i++) bb = cpBBMerge(bb, nodes[i]->bb); // Split it on it's longest axis cpBool splitWidth = (bb.r - bb.l > bb.t - bb.b); // Sort the bounds and use the median as the splitting point cpFloat *bounds = (cpFloat *)cpcalloc(count*2, sizeof(cpFloat)); if(splitWidth){ for(int i=0; i<count; i++){ bounds[2*i + 0] = nodes[i]->bb.l; bounds[2*i + 1] = nodes[i]->bb.r; } } else { for(int i=0; i<count; i++){ bounds[2*i + 0] = nodes[i]->bb.b; bounds[2*i + 1] = nodes[i]->bb.t; } } qsort(bounds, count*2, sizeof(cpFloat), (int (*)(const void *, const void *))cpfcompare); cpFloat split = (bounds[count - 1] + bounds[count])*0.5f; // use the medain as the split cpfree(bounds); // Generate the child BBs cpBB a = bb, b = bb; if(splitWidth) a.r = b.l = split; else a.t = b.b = split; // Partition the nodes int right = count; for(int left=0; left < right;){ Node *node = nodes[left]; if(cpBBMergedArea(node->bb, b) < cpBBMergedArea(node->bb, a)){ // if(cpBBProximity(node->bb, b) < cpBBProximity(node->bb, a)){ right--; nodes[left] = nodes[right]; nodes[right] = node; } else { left++; } } if(right == count){ Node *node = NULL; for(int i=0; i<count; i++) node = SubtreeInsert(node, nodes[i], tree); return node; } // Recurse and build the node! return NodeNew(tree, partitionNodes(tree, nodes, right), partitionNodes(tree, nodes + right, count - right) ); }