#pragma once #include #include #include namespace algoim::organizer { const int NODE_IN_OUT_UNKNOWN = 0; const int NODE_IN = 1; const int NODE_OUT = 2; const int OP_UNION = 0; const int OP_INTERSECTION = 1; const int OP_DIFFERENCE = 2; // bitfield struct Blob { unsigned int isPrimitive : 1; // 1 for leaf unsigned int nodeOp : 2; // 0 for union, 1 for intersection, 2 for difference // unsigned int ignoreMod : 2; // 目前用不到 unsigned int inOut : 2; // 0 for unknown, 1 for in, 2 for out unsigned int oneChildInOut : 2; // 0 for unknown, 1 for in, 2 for out unsigned int isLeft : 1; unsigned int ancestor : 24; }; bool isPrimitive(Blob b) { return b.isPrimitive == 1; } unsigned int type(Blob b) { return 0; } bool isLeft(Blob b) { return b.isLeft == 1; } class BlobTree { public: std::vector structure; std::vector primitiveNodeIdx; // 由primitive数组下标指向node中对应leaf的下标 BlobTree() {} }; void propagate(BlobTree& tree, unsigned int nodeIdx, bool in) { const std::size_t rootIdx = tree.structure.size() - 1; auto& node = tree.structure[nodeIdx]; assert(node.inOut == 0); node.inOut = in ? NODE_IN : NODE_OUT; for (unsigned int nowIdx = nodeIdx; nowIdx != rootIdx;) { const auto& nowNode = tree.structure[nowIdx]; unsigned int nextIdx = isLeft(nowNode) ? nowNode.ancestor : nodeIdx + 1; auto& nextNode = tree.structure[nextIdx]; // father if (nextNode.inOut != 0) { return; } if (nowNode.inOut == NODE_OUT) { if (nextNode.nodeOp == OP_INTERSECTION) { nextNode.inOut = NODE_OUT; } else if (nextNode.nodeOp == OP_DIFFERENCE && isLeft(nowNode)) { nextNode.inOut = NODE_OUT; } else if (nextNode.oneChildInOut == NODE_IN) { // 两种情况,Union: in, Difference: NowNode一定是right,in-out,还是in nextNode.inOut = NODE_IN; } else if (nextNode.oneChildInOut == NODE_OUT) { // 两种情况,Union: out, Difference: out-out, 还是out nextNode.inOut = NODE_OUT; } else { nextNode.oneChildInOut = NODE_OUT; return; } } else if (nowNode.inOut == NODE_IN) { if (nextNode.nodeOp == OP_UNION) { nextNode.inOut = NODE_IN; } else if (nextNode.nodeOp == OP_DIFFERENCE && !isLeft(nowNode)) { // difference and right nextNode.inOut = NODE_OUT; } else if (nextNode.oneChildInOut == NODE_IN) { // 两种情况,Intersection: in, Difference: in-in,out nextNode.inOut = nextNode.nodeOp == OP_INTERSECTION ? NODE_IN : NODE_OUT; } else if (nextNode.oneChildInOut == NODE_OUT) { // 两种情况,Intersection: out, Difference: NowNode一定是left,in-out,in nextNode.inOut = nextNode.nodeOp == OP_INTERSECTION ? NODE_OUT : NODE_IN; } else { nextNode.oneChildInOut = NODE_IN; return; } } nowIdx = nextIdx; } return; } // TODO: std::vector 可以改成bitset之类 /** * relatedPrimitives 是当次traversal需要care的primitives的索引,例如OcTree子问题中关联的Primitive */ int traverse(BlobTree& tree, const std::vector& relatedPrimitives, const std::vector& primitiveInout) { assert(relatedPrimitives.size() == primitiveInout.size()); for (int primitiveIdx : relatedPrimitives) { propagate(tree, tree.primitiveNodeIdx[primitiveIdx], primitiveInout[primitiveIdx]); if (tree.structure.back().inOut != NODE_IN_OUT_UNKNOWN) { return tree.structure.back().inOut; } } return NODE_IN_OUT_UNKNOWN; } int traverse(BlobTree& tree, const int relatedPrimitive, const bool primitiveInout) { propagate(tree, tree.primitiveNodeIdx[relatedPrimitive], primitiveInout); return tree.structure.back().inOut; } }; // namespace algoim::organizer