#pragma once #include #include #include namespace algoim::organizer { // 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 ? 1 : 2; for (unsigned int nowIdx = nodeIdx; nowIdx != rootIdx; ++nodeIdx) { const auto& nowNode = tree.structure[nowIdx]; unsigned int nextIdx = isLeft(nowNode) ? nowNode.ancestor : nodeIdx + 1; auto& nextNode = tree.structure[nextIdx]; if (nextNode.inOut != 0) { return; } if (nowNode.inOut == 2) { // out if (nextNode.nodeOp == 1) { // intersection } else if (nextNode.nodeOp == 2 && isLeft(nowNode)) { // difference and left nextNode.inOut = 2; } else if (nextNode.oneChildInOut == 1) { // 两种情况,Union: in, Difference: NowNode一定是right,in-out,还是in nextNode.inOut = 1; } else if (nextNode.oneChildInOut == 2) { // 两种情况,Union: out, Difference: out-out, 还是out nextNode.inOut = 2; } else { nextNode.oneChildInOut = 2; return; } } else if (nowNode.inOut == 1) { // in if (nextNode.nodeOp == 0) { // union nextNode.inOut = 1; } else if (nextNode.nodeOp == 2 && !isLeft(nowNode)) { // difference and right nextNode.inOut = 2; } else if (nextNode.oneChildInOut == 1) { // 两种情况,Intersection: in, Difference: in-in,out nextNode.inOut = nextNode.nodeOp == 1 ? 1 : 2; } else if (nextNode.oneChildInOut == 2) { // 两种情况,Intersection: out, Difference: NowNode一定是left,in-out,in nextNode.inOut = nextNode.nodeOp == 1 ? 2 : 1; } else { nextNode.oneChildInOut = 1; return; } } nextIdx = nowIdx; } return; } // 这里传入的BlobTree是拷贝,因为要修改且不同traversal的修改不相互影响 // TODO: 最好优化掉拷贝 // TODO: std::vector 可以改成bitset之TT /** * relatedPrimitives 是当次traversal需要care的primitives的索引,例如OcTree子问题中管理的Primitive */ bool 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 != 0) { return tree.structure.back().inOut == 1; } } std::cerr << "should not be here" << std::endl; return false; } }; // namespace algoim::organizer