Exemplo n.º 1
0
void ClusterNode::getClusters(osgUtil::CullVisitor* cv, ClusterList& out)
{
    _nextLabel = 0;

    osg::Camera* camera = cv->getCurrentCamera();

    osg::Viewport* viewport = camera->getViewport();
    if (!viewport)
    {
        return;
    }

    osg::Matrixd mvpw = camera->getViewMatrix() *
        camera->getProjectionMatrix() *
        camera->getViewport()->computeWindowMatrix();

    std::vector<TPoint> points;

    osg::NodeList validPlaces;

    buildIndex();

    for (osg::NodeList::iterator itr = _clusterIndex.begin(); itr != _clusterIndex.end(); ++itr)
    {
        osg::Group* index = static_cast<osg::Group*>(itr->get());
        if (cv->isCulled(index->getBound()))
        {
            continue;
        }

        for (unsigned int i = 0; i < index->getNumChildren(); i++)
        {
            osg::Node* node = index->getChild(i);
            osg::Vec3d world = node->getBound().center();

            if (cv->isCulled(*node))
            {
                continue;
            }

            if (!_horizon->isVisible(world))
            {
                continue;
            }

            osg::Vec3d screen = world * mvpw;

            if (screen.x() >= 0 && screen.x() <= viewport->width() &&
                screen.y() >= 0 && screen.y() <= viewport->height())
            {
                validPlaces.push_back(node);
                points.push_back(TPoint(screen.x(), screen.y()));
            }
        }
    }

    if (validPlaces.size() == 0) return;

    kdbush::KDBush<TPoint> index(points);
    std::set< unsigned int > clustered;

    for (unsigned int i = 0; i < validPlaces.size(); i++)
    {
        TPoint &screen = points[i];
        osg::Node* node = validPlaces[i].get();

        // If this thing is already part of a cluster then just continue.
        if (clustered.find(i) != clustered.end())
        {
            continue;
        }

        osg::Vec3d world = node->getBound().center();

        // Get any matching indices that are part of this cluster.
        TIds indices;

        index.range(screen.first - _radius, screen.second - _radius, screen.first + _radius, screen.second + _radius, indices);

        // Create a new cluster.
        Cluster cluster;

        unsigned int actualCount = 0;

        // Add all of the points to the cluster.
        for (unsigned int j = 0; j < indices.size(); j++)
        {
            if (clustered.find(indices[j]) == clustered.end())
            {
                if (_canClusterCallback.valid())
                {
                    bool canCluster = (*_canClusterCallback)(node, validPlaces[indices[j]].get());
                    if (!canCluster) {
                        continue;
                    }
                }
                cluster.nodes.push_back(validPlaces[indices[j]]);
                actualCount++;
                clustered.insert(indices[j]);
            }
        }

        std::stringstream buf;
        buf << actualCount << std::endl;

        PlaceNode* marker = getOrCreateLabel();
        GeoPoint markerPos;
        markerPos.fromWorld(_mapNode->getMapSRS(), world);
        marker->setPosition(markerPos);
        marker->setText(buf.str());

        cluster.marker = marker;
        out.push_back(cluster);

        clustered.insert(i);
    }
}