void
KML_Model::parseStyle(const Config& conf, KMLContext& cx, Style& style)
{    
    MarkerSymbol* marker = 0L;
    
    std::string url = KMLUtils::parseLink(conf);
    if ( !url.empty() )
    {
        if ( !marker ) marker = style.getOrCreate<MarkerSymbol>();
        marker->url() = StringExpression( Stringify() << "\"" << url << "\"" );
        marker->url()->setURIContext( URIContext(conf.referrer()) );        
    }

    Config scale = conf.child("scale");
    if (!scale.empty())
    {
        if ( !marker ) marker = style.getOrCreate<MarkerSymbol>();
        //TODO:  Support XYZ scale instead of single value
        marker->scale() = scale.value("x", 1.0);
    }

    Config orientation = conf.child("orientation");
    if (!orientation.empty())
    {
        if ( !marker ) marker = style.getOrCreate<MarkerSymbol>();
        double h = orientation.value("heading", 0);
        double p = orientation.value("tilt", 0);
        double r = orientation.value("roll", 0);        
        marker->orientation() = osg::Vec3d(h,p,r);
    }

    // since we know this is a model, not an icon.
    if ( marker )
        marker->isModel() = true;

    KML_Geometry::parseStyle(conf, cx, style);
}
示例#2
0
void
PlaceNode::init()
{
    _geode = new osg::Geode();

    osg::Drawable* text = 0L;

    if ( !_image.valid() && _style.getSymbol<MarkerSymbol>() )
    {
        _image = _style.getSymbol<MarkerSymbol>()->getImage();
    }

    if ( _image.get() )
    {
        // this offset anchors the image at the bottom
        osg::Vec2s offset;
        MarkerSymbol* marker = _style.get<MarkerSymbol>();
        if ((marker == NULL) || !marker->alignment().isSet())
        {	
            // default to bottom center
            offset.set(0.0, (_image->t() / 2.0));
        }
        else
        {	// default to bottom center
            switch (marker->alignment().value())
            {
            case MarkerSymbol::ALIGN_LEFT_TOP:
                offset.set((_image->s() / 2.0), -(_image->t() / 2.0));
                break;
            case MarkerSymbol::ALIGN_LEFT_CENTER:
                offset.set((_image->s() / 2.0), 0.0);
                break;
            case MarkerSymbol::ALIGN_LEFT_BOTTOM:
                offset.set((_image->s() / 2.0), (_image->t() / 2.0));
                break;
            case MarkerSymbol::ALIGN_CENTER_TOP:
                offset.set(0.0, -(_image->t() / 2.0));
                break;
            case MarkerSymbol::ALIGN_CENTER_CENTER:
                offset.set(0.0, 0.0);
                break;
            case MarkerSymbol::ALIGN_CENTER_BOTTOM:
            default:
                offset.set(0.0, (_image->t() / 2.0));
                break;
            case MarkerSymbol::ALIGN_RIGHT_TOP:
                offset.set(-(_image->s() / 2.0), -(_image->t() / 2.0));
                break;
            case MarkerSymbol::ALIGN_RIGHT_CENTER:
                offset.set(-(_image->s() / 2.0), 0.0);
                break;
            case MarkerSymbol::ALIGN_RIGHT_BOTTOM:
                offset.set(-(_image->s() / 2.0), (_image->t() / 2.0));
                break;
            }
        }

        // Apply a rotation to the marker if requested:
        double heading = 0.0;
        if ( marker && marker->orientation().isSet() )
        {
            //Just get the heading
            heading = osg::DegreesToRadians(marker->orientation().value().x());
        }

        //We must actually rotate the geometry itself and not use a MatrixTransform b/c the 
        //decluttering doesn't respect Transforms above the drawable.
        osg::Geometry* imageGeom = AnnotationUtils::createImageGeometry( _image.get(), offset, 0, heading );
        if ( imageGeom )
            _geode->addDrawable( imageGeom );

        text = AnnotationUtils::createTextDrawable(
            _text,
            _style.get<TextSymbol>(),
            osg::Vec3( (offset.x() + (_image->s() / 2.0) + 2), offset.y(), 0 ) );
    }
    else
    {
        text = AnnotationUtils::createTextDrawable(
            _text,
            _style.get<TextSymbol>(),
            osg::Vec3( 0, 0, 0 ) );
    }

    if ( text )
        _geode->addDrawable( text );
    
    osg::StateSet* stateSet = _geode->getOrCreateStateSet();
    stateSet->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS, 0, 1, false), 1 );

    getAttachPoint()->addChild( _geode );

    // for clamping
    applyStyle( _style );
}
示例#3
0
void 
KML_Placemark::build( const Config& conf, KMLContext& cx )
{
    Style style;
    if ( conf.hasValue("styleurl") )
    {
        // process a "stylesheet" style
        const Style* ref_style = cx._sheet->getStyle( conf.value("styleurl"), false );
        if ( ref_style )
            style = *ref_style;
    }
    else if ( conf.hasChild("style") )
    {
        // process an "inline" style
        KML_Style kmlStyle;
        kmlStyle.scan( conf.child("style"), cx );
        style = cx._activeStyle;
    }

    // parse the geometry. the placemark must have geometry to be valid. The 
    // geometry parse may optionally specify an altitude mode as well.
    KML_Geometry geometry;
    geometry.build(conf, cx, style);

    // KML's default altitude mode is clampToGround.
    AltitudeMode altMode = ALTMODE_RELATIVE;

    AltitudeSymbol* altSym = style.get<AltitudeSymbol>();
    if ( !altSym )
    {
        altSym = style.getOrCreate<AltitudeSymbol>();
        altSym->clamping() = AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN;
    }
    else if ( !altSym->clamping().isSetTo(AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN) )
    {
        altMode = ALTMODE_ABSOLUTE;
    }
    
    if ( geometry._geom.valid() && geometry._geom->getTotalPointCount() > 0 )
    {
        Geometry* geom = geometry._geom.get();

        GeoPoint position(cx._srs.get(), geom->getBounds().center(), altMode);

        bool isPoly = geom->getComponentType() == Geometry::TYPE_POLYGON;
        bool isPoint = geom->getComponentType() == Geometry::TYPE_POINTSET;

        // read in the Marker if there is one.
        URI                      markerURI;
        osg::ref_ptr<osg::Image> markerImage;
        osg::ref_ptr<osg::Node>  markerModel;

        MarkerSymbol* marker = style.get<MarkerSymbol>();

        if ( marker && marker->url().isSet() )
        {
            if ( marker->isModel() == false )
            {
                markerImage = marker->getImage( *cx._options->iconMaxSize() );
            }
            else
            {
                markerURI = URI( marker->url()->eval(), marker->url()->uriContext() );
                markerModel = markerURI.getNode();

                // We can't leave the marker symbol in the style, or the GeometryCompiler will
                // think we want to do Point-model substitution. So remove it. A bit of a hack
                if ( marker )
                    style.removeSymbol(marker);
            }
        }

        std::string text = conf.hasValue("name") ? conf.value("name") : "";

        AnnotationNode* fNode = 0L;
        AnnotationNode* pNode = 0L;

        // place a 3D model:
        if ( markerModel.valid() )
        {
            LocalGeometryNode* lg = new LocalGeometryNode(cx._mapNode, markerModel.get(), style, false);
            lg->setPosition( position );
            if ( marker )
            {
                if ( marker->scale().isSet() )
                {
                    float scale = marker->scale()->eval();
                    lg->setScale( osg::Vec3f(scale,scale,scale) );
                }
                if ( marker->orientation().isSet() )
                {
                   // lg->setRotation( );
                }
            }

            fNode = lg;
            //Feature* feature = new Feature(geometry._geom.get(), cx._srs.get(), style);
            //fNode = new FeatureNode( cx._mapNode, feature, false );
        }

        // Place node (icon + text) or Label node (text only)
        else if ( marker || geometry._geom->getTotalPointCount() == 1 )
        {
            if ( !markerImage.valid() )
            {
                markerImage = cx._options->defaultIconImage().get();
                if ( !markerImage.valid() )
                {
                    markerImage = cx._options->defaultIconURI()->getImage();
                }
            }
            
            if ( !style.get<TextSymbol>() && cx._options->defaultTextSymbol().valid() )
            {
                style.addSymbol( cx._options->defaultTextSymbol().get() );
            }

            if ( markerImage.valid() )
                pNode = new PlaceNode( cx._mapNode, position, markerImage.get(), text, style );
            else
                pNode = new LabelNode( cx._mapNode, position, text, style );
        }

        if ( geometry._geom->getTotalPointCount() > 1 )
        {
            const ExtrusionSymbol* ex = style.get<ExtrusionSymbol>();
            const AltitudeSymbol* alt = style.get<AltitudeSymbol>();    

            if ( style.get<MarkerSymbol>() )
                style.removeSymbol(style.get<MarkerSymbol>());

            bool draped =
                isPoly   && 
                ex == 0L && 
                (alt == 0L || alt->clamping() == AltitudeSymbol::CLAMP_TO_TERRAIN);

            // Make a feature node; drape if we're not extruding.
            GeometryCompilerOptions options;
            options.clustering() = false;            
            Feature* feature = new Feature(geometry._geom.get(), cx._srs.get(), style);
            fNode = new FeatureNode( cx._mapNode, feature, draped, options );

            if ( !ex )
            {
                fNode->getOrCreateStateSet()->setMode(GL_LIGHTING, 0);
            }
        }
        
        if ( pNode && fNode )
        {
            osg::Group* group = new osg::Group();
            group->addChild( fNode );
            group->addChild( pNode );
            cx._groupStack.top()->addChild( group );
            if ( cx._options->declutter() == true )
                Decluttering::setEnabled( pNode->getOrCreateStateSet(), true );
            KML_Feature::build( conf, cx, pNode );
            KML_Feature::build( conf, cx, fNode );
        }

        else if ( pNode )
        {
            if ( cx._options->iconAndLabelGroup().valid() )
            {
                cx._options->iconAndLabelGroup()->addChild( pNode );
            }
            else
            {
                cx._groupStack.top()->addChild( pNode );
                if ( cx._options->declutter() == true )
                    Decluttering::setEnabled( pNode->getOrCreateStateSet(), true );
            }
            KML_Feature::build( conf, cx, pNode );
        }

        else if ( fNode )
        {
            cx._groupStack.top()->addChild( fNode );
            KML_Feature::build( conf, cx, fNode );
        }
    }
}