Пример #1
0
KdTree::ObstacleTreeNode* KdTree::buildObstacleTreeRecursive(const std::vector<Obstacle*>& obstacles)
{
    if (obstacles.empty()) {
        return 0;
    } else {
        ObstacleTreeNode* const node = new ObstacleTreeNode;

        size_t optimalSplit = 0;
        size_t minLeft = obstacles.size();
        size_t minRight = obstacles.size();

        for (size_t i = 0; i < obstacles.size(); ++i) {
            size_t leftSize = 0;
            size_t rightSize = 0;

            const Obstacle* const obstacleI1 = obstacles[i];
            const Obstacle* const obstacleI2 = obstacleI1->nextObstacle;

            /* Compute optimal split node. */
            for (size_t j = 0; j < obstacles.size(); ++j) {
                if (i == j) {
                    continue;
                }

                const Obstacle* const obstacleJ1 = obstacles[j];
                const Obstacle* const obstacleJ2 = obstacleJ1->nextObstacle;

                const float j1LeftOfI = leftOf(obstacleI1->point_, obstacleI2->point_, obstacleJ1->point_);
                const float j2LeftOfI = leftOf(obstacleI1->point_, obstacleI2->point_, obstacleJ2->point_);

                if (j1LeftOfI >= -RVO_EPSILON && j2LeftOfI >= -RVO_EPSILON) {
                    ++leftSize;
                } else if (j1LeftOfI <= RVO_EPSILON && j2LeftOfI <= RVO_EPSILON) {
                    ++rightSize;
                } else {
                    ++leftSize;
                    ++rightSize;
                }

                if (std::make_pair(std::max(leftSize, rightSize), std::min(leftSize, rightSize)) >= std::make_pair(std::max(minLeft, minRight), std::min(minLeft, minRight))) {
                    break;
                }
            }

            if (std::make_pair(std::max(leftSize, rightSize), std::min(leftSize, rightSize)) < std::make_pair(std::max(minLeft, minRight), std::min(minLeft, minRight))) {
                minLeft = leftSize;
                minRight = rightSize;
                optimalSplit = i;
            }
        }

        /* Build split node. */
        std::vector<Obstacle*> leftObstacles(minLeft);
        std::vector<Obstacle*> rightObstacles(minRight);

        size_t leftCounter = 0;
        size_t rightCounter = 0;
        const size_t i = optimalSplit;

        const Obstacle* const obstacleI1 = obstacles[i];
        const Obstacle* const obstacleI2 = obstacleI1->nextObstacle;

        for (size_t j = 0; j < obstacles.size(); ++j) {
            if (i == j) {
                continue;
            }

            Obstacle* const obstacleJ1 = obstacles[j];
            Obstacle* const obstacleJ2 = obstacleJ1->nextObstacle;

            const float j1LeftOfI = leftOf(obstacleI1->point_, obstacleI2->point_, obstacleJ1->point_);
            const float j2LeftOfI = leftOf(obstacleI1->point_, obstacleI2->point_, obstacleJ2->point_);

            if (j1LeftOfI >= -RVO_EPSILON && j2LeftOfI >= -RVO_EPSILON) {
                leftObstacles[leftCounter++] = obstacles[j];
            } else if (j1LeftOfI <= RVO_EPSILON && j2LeftOfI <= RVO_EPSILON) {
                rightObstacles[rightCounter++] = obstacles[j];
            } else {
                /* Split obstacle j. */
                const float t = det(obstacleI2->point_ - obstacleI1->point_, obstacleJ1->point_ - obstacleI1->point_) / det(obstacleI2->point_ - obstacleI1->point_, obstacleJ1->point_ - obstacleJ2->point_);

                const Vector2 splitpoint = obstacleJ1->point_ + t * (obstacleJ2->point_ - obstacleJ1->point_);

                Obstacle* const newObstacle = new Obstacle();
                newObstacle->point_ = splitpoint;
                newObstacle->prevObstacle = obstacleJ1;
                newObstacle->nextObstacle = obstacleJ2;
                newObstacle->isConvex_ = true;
                newObstacle->unitDir_ = obstacleJ1->unitDir_;

                newObstacle->id_ = sim_->obstacles_.size();

                sim_->obstacles_.push_back(newObstacle);

                obstacleJ1->nextObstacle = newObstacle;
                obstacleJ2->prevObstacle = newObstacle;

                if (j1LeftOfI > 0.0f) {
                    leftObstacles[leftCounter++] = obstacleJ1;
                    rightObstacles[rightCounter++] = newObstacle;
                } else {
                    rightObstacles[rightCounter++] = obstacleJ1;
                    leftObstacles[leftCounter++] = newObstacle;
                }
            }
        }

        node->obstacle = obstacleI1;
        node->left = buildObstacleTreeRecursive(leftObstacles);
        node->right = buildObstacleTreeRecursive(rightObstacles);
        return node;
    }
}
Пример #2
0
		ObstacleTreeNode* ObstacleKDTree::buildTreeRecursive( const std::vector<Obstacle*>& obstacles) {
			if ( obstacles.empty() ) {
				return 0x0;
			} else {
				ObstacleTreeNode* const node = new ObstacleTreeNode;

				size_t optimalSplit = 0;
				size_t minLeft = obstacles.size();
				size_t minRight = obstacles.size();

				for (size_t i = 0; i < obstacles.size(); ++i) {
					size_t leftSize = 0;
					size_t rightSize = 0;

					const Obstacle* const obstacleI = obstacles[i];
					const Vector2 I0 = obstacleI->getP0();
					const Vector2 I1 = obstacleI->getP1();
					
					/* Compute optimal split node. */
					for (size_t j = 0; j < obstacles.size(); ++j) {
						if (i == j) {
							continue;
						}

						const Obstacle* const obstacleJ = obstacles[j];
						const Vector2 J0 = obstacleJ->getP0();
						const Vector2 J1 = obstacleJ->getP1();

						const float j1LeftOfI = leftOf( I0, I1, J0 );
						const float j2LeftOfI = leftOf( I0, I1, J1 );

						if (j1LeftOfI >= -EPS && j2LeftOfI >= -EPS) {
							++leftSize;
						} else if (j1LeftOfI <= EPS && j2LeftOfI <= EPS ) {
							++rightSize;
						} else {
							++leftSize;
							++rightSize;
						}

						if (std::make_pair(std::max(leftSize, rightSize), std::min(leftSize, rightSize)) >= std::make_pair(std::max(minLeft, minRight), std::min(minLeft, minRight))) {
							break;
						}
					}

					if (std::make_pair(std::max(leftSize, rightSize), std::min(leftSize, rightSize)) < std::make_pair(std::max(minLeft, minRight), std::min(minLeft, minRight))) {
						minLeft = leftSize;
						minRight = rightSize;
						optimalSplit = i;
					}
				}

				/* Build split node. */
				std::vector<Obstacle*> leftObstacles(minLeft);
				std::vector<Obstacle*> rightObstacles(minRight);

				size_t leftCounter = 0;
				size_t rightCounter = 0;
				const size_t i = optimalSplit;

				const Obstacle* const obstacleI = obstacles[i];
				const Vector2 I0 = obstacleI->getP0();
				const Vector2 I1 = obstacleI->getP1();

				for (size_t j = 0; j < obstacles.size(); ++j) {
					if (i == j) {
						continue;
					}

					Obstacle* const obstacleJ = obstacles[j];
					const Vector2 J0 = obstacleJ->getP0();
					const Vector2 J1 = obstacleJ->getP1();

					const float j1LeftOfI = leftOf( I0, I1, J0 );
					const float j2LeftOfI = leftOf( I0, I1, J1 );

					if (j1LeftOfI >= -EPS && j2LeftOfI >= -EPS ) {
						leftObstacles[leftCounter++] = obstacles[j];
					} else if (j1LeftOfI <= EPS && j2LeftOfI <= EPS ) {
						rightObstacles[rightCounter++] = obstacles[j];
					} else {
						/* Split obstacle j. */
						const float t = det( I1 - I0, J0 - I0 ) / det( I1 -I0, J0 - J1 );

						const Vector2 splitpoint = J0 + t * ( J1 - J0 );

						Obstacle* const newObstacle = new Obstacle();
						newObstacle->_point = splitpoint;
						newObstacle->_prevObstacle = obstacleJ;
						newObstacle->_nextObstacle = obstacleJ->_nextObstacle;
						if ( newObstacle->_nextObstacle ) {
							obstacleJ->_nextObstacle = newObstacle;
						}
						newObstacle->_isConvex = true;
						newObstacle->_unitDir = obstacleJ->_unitDir;
						newObstacle->_length = abs( J1 - newObstacle->_point );

						newObstacle->_id = _obstacles.size();
						newObstacle->_class = obstacleJ->_class;

						_obstacles.push_back(newObstacle);

						obstacleJ->_nextObstacle = newObstacle;
						obstacleJ->_length = abs( J0 - newObstacle->_point );

						if (j1LeftOfI > 0.0f) {
							leftObstacles[leftCounter++] = obstacleJ;
							rightObstacles[rightCounter++] = newObstacle;
						} else {
							rightObstacles[rightCounter++] = obstacleJ;
							leftObstacles[leftCounter++] = newObstacle;
						}
					}
				}

				node->_obstacle = obstacleI;
				node->_left = buildTreeRecursive(leftObstacles);
				node->_right = buildTreeRecursive(rightObstacles);
				return node;
			}
		}