osg::Node* makeLabelNode(const FilterContext& context, 
                             const Feature*       feature, 
                             const std::string&   value, 
                             const TextSymbol*    text, 
                             NumericExpression&   priorityExpr )
    {
        LabelNode* labelNode = new LabelNode(
            context.getSession()->getMapInfo().getProfile()->getSRS(),
            GeoPoint(feature->getSRS(), feature->getGeometry()->getBounds().center()),
            value,
            text );

        if ( text->priority().isSet() )
        {
            AnnotationData* data = new AnnotationData();
            data->setPriority( feature->eval(priorityExpr, &context) );
            labelNode->setAnnotationData( data );
        }

        return labelNode;
    }
Esempio n. 2
0
void
GeodeticGraticule::initLabelPool(CameraData& cdata)
{
    const osgEarth::SpatialReference* srs = osgEarth::SpatialReference::create("wgs84");

    Style style;
    TextSymbol* text = style.getOrCreateSymbol<TextSymbol>();
    text->alignment() = TextSymbol::ALIGN_CENTER_CENTER;
    text->fill()->color() = options().labelColor().get();
    AltitudeSymbol* alt = style.getOrCreateSymbol<AltitudeSymbol>();
    alt->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN;

    unsigned int labelPoolSize = 8 * options().gridLines().get();
    for (unsigned int i = 0; i < labelPoolSize; i++)
    {
        GeoPoint pt(srs, 0,0,0);
        LabelNode* label = new LabelNode(_mapNode.get(), pt, "0,0");
        label->setDynamic(true);
        label->setStyle(style);
        cdata._labelPool.push_back(label);
    }
}
bool
GraticuleLabelingEngine::cullTraverse(osgUtil::CullVisitor& nv, CameraData& data)
{    
    osg::Camera* cam = nv.getCurrentCamera();

    // Don't draw the labels if we are too far from North-Up:
    double heading = getCameraHeading(cam->getViewMatrix());
    if (osg::RadiansToDegrees(fabs(heading)) > 7.0)
        return false;

    // Initialize the label pool for this camera if we have not done so:
    if (data.xLabels.empty())
    {
        for (unsigned i = 0; i < MAX_LABELS; ++i)
        {
            LabelNode* label = new LabelNode();
            label->setDynamic(true);
            label->setStyle(_xLabelStyle);
            label->setHorizonCulling(false);
            label->setOcclusionCulling(false);
            data.xLabels.push_back(label);
        }

        for (unsigned i = 0; i < MAX_LABELS; ++i)
        {
            LabelNode* label = new LabelNode();
            label->setDynamic(true);
            label->setStyle(_yLabelStyle);
            label->setHorizonCulling(false);
            label->setOcclusionCulling(false);
            data.yLabels.push_back(label);
        }
    }

    // Start out with all labels off. We will then turn back on the ones we use:
    for (unsigned i = 0; i < MAX_LABELS; ++i)
    {
        data.xLabels[i]->setNodeMask(0);
        data.yLabels[i]->setNodeMask(0);
    }

    // Intersect the corners of the view frustum with the ellipsoid.
    // This will yield the approximate geo-extent of the view.
    // TODO: graduate this to the core if generally useful - could be helpful
    // for displaying the extent of the current view.

    // Calculate the "clip to world" matrix = MVPinv.
    osg::Matrix MVP = (*nv.getModelViewMatrix()) * cam->getProjectionMatrix();
    osg::Matrix MVPinv;
    MVPinv.invert(MVP);

    EllipsoidIntersector ellipsoid(_srs->getEllipsoid());

    // For each corner, transform the clip coordinates at the near and far
    // planes into world space and intersect that line with the ellipsoid:
    osg::Vec3d p0, p1;

    // find the lower-left corner of the frustum:
    osg::Vec3d LL_world;
    p0 = osg::Vec3d(-1, -1, -1) * MVPinv;
    p1 = osg::Vec3d(-1, -1, +1) * MVPinv;
    bool LL_ok = ellipsoid.intersectLine(p0, p1, LL_world);
    if (!LL_ok)
        return false;

    // find the upper-left corner of the frustum:
    osg::Vec3d UL_world;
    p0 = osg::Vec3d(-1, +1, -1) * MVPinv;
    p1 = osg::Vec3d(-1, +1, +1) * MVPinv;
    bool UL_ok = ellipsoid.intersectLine(p0, p1, UL_world);
    if (!UL_ok)
        return false;

    // find the lower-right corner of the frustum:
    osg::Vec3d LR_world;
    p0 = osg::Vec3d(+1, -1, -1) * MVPinv;
    p1 = osg::Vec3d(+1, -1, +1) * MVPinv;
    bool LR_ok = ellipsoid.intersectLine(p0, p1, LR_world);
    if (!LR_ok)
        return false;

    // Use this for clamping geopoints to the edges of the frustum:
    ClipSpace window(MVP, MVPinv);

    return updateLabels(LL_world, UL_world, LR_world, window, data);
}
Esempio n. 4
0
void 
GeodeticGraticule::updateLabels()
{
    const osgEarth::SpatialReference* srs = osgEarth::SpatialReference::create("wgs84");
    
    Threading::ScopedMutexLock lock(_cameraDataMapMutex);
    for (CameraDataMap::iterator i = _cameraDataMap.begin(); i != _cameraDataMap.end(); ++i)
    {
        CameraData& cdata = i->second;

        std::vector< GeoExtent > extents;
        if (cdata._viewExtent.crossesAntimeridian())
        {
            GeoExtent first, second;
            cdata._viewExtent.splitAcrossAntimeridian(first, second);
            extents.push_back(first);
            extents.push_back(second);
        }
        else
        {
            extents.push_back( cdata._viewExtent );
        }

        double resDegrees = cdata._resolution * 180.0;
        // We want half the resolution so the labels don't appear as often as the grid lines
        resDegrees *= 2.0;

    
        // Hide all the labels
        for (unsigned int i = 0; i < cdata._labelPool.size(); i++)
        {
            cdata._labelPool[i]->setNodeMask(0);
        }

        // Approximate offset in degrees
        double degOffset = cdata._metersPerPixel / 111000.0;
     
        unsigned int labelIndex = 0;


        bool done = false;
        for (unsigned int extentIndex = 0; extentIndex < extents.size() && !done; extentIndex++)
        {
            GeoExtent extent = extents[extentIndex];

            int minLonIndex = floor(((extent.xMin() + 180.0)/resDegrees));
            int maxLonIndex = ceil(((extent.xMax() + 180.0)/resDegrees));

            int minLatIndex = floor(((extent.yMin() + 90)/resDegrees));
            int maxLatIndex = ceil(((extent.yMax() + 90)/resDegrees));

            // Generate horizontal labels
            for (int i = minLonIndex; i <= maxLonIndex && !done; i++)
            {
                GeoPoint point(srs, -180.0 + (double)i * resDegrees, cdata._lat + (_centerOffset.y() * degOffset), 0, ALTMODE_ABSOLUTE);
                LabelNode* label = cdata._labelPool[labelIndex++].get();

                label->setNodeMask(~0u);
                label->setPosition(point);
                std::string text = getText( point, false);
                label->setText( text );
                if (labelIndex == cdata._labelPool.size() - 1)
                {
                    done = true;
                }
            }

            // Generate the vertical labels
            for (int i = minLatIndex; i <= maxLatIndex && !done; i++)
            {
                GeoPoint point(srs, cdata._lon + (_centerOffset.x() * degOffset), -90.0 + (double)i * resDegrees, 0, ALTMODE_ABSOLUTE);
                // Skip drawing labels at the poles
                if (osg::equivalent(osg::absolute( point.y()), 90.0, 0.1))
                {
                    continue;
                }
                LabelNode* label = cdata._labelPool[labelIndex++].get();
                label->setNodeMask(~0u);
                label->setPosition(point);
                std::string text = getText( point, true);
                label->setText( text );
                if (labelIndex == cdata._labelPool.size() - 1)
                {
                    done = true;
                }
            }
        }
    }
}