osgEarth 2.1.1
Public Member Functions

osgEarth::Symbology::GeometryExtrudeSymbolizer Class Reference

List of all members.

Public Member Functions

 GeometryExtrudeSymbolizer ()
osg::Geode * extrude (Geometry *geom, double offset, double height, SymbolizerContext *context)
void tessellate (osg::Geometry *geom)
bool compile (State< GeometryContent > *state, osg::Group *attachPoint)

Detailed Description

Definition at line 29 of file GeometryExtrudeSymbolizer.


Constructor & Destructor Documentation

GeometryExtrudeSymbolizer::GeometryExtrudeSymbolizer ( )

Definition at line 31 of file GeometryExtrudeSymbolizer.cpp.

{
}

Member Function Documentation

bool GeometryExtrudeSymbolizer::compile ( State< GeometryContent > *  state,
osg::Group *  attachPoint 
)

Definition at line 46 of file GeometryExtrudeSymbolizer.cpp.

{
    if ( !state || !attachPoint || !state->getContent() || !state->getStyle() )
        return false;

    osg::ref_ptr<osg::Group> newSymbolized = new osg::Group;

    const GeometryList& geometryList = state->getContent()->getGeometryList();
    for (GeometryList::const_iterator it = geometryList.begin(); it != geometryList.end(); ++it)
    {
        Geometry* geometry = *it;
        if (!geometry)
            continue;

        GeometryIterator geomIterator( geometry );
        geomIterator.traverseMultiGeometry() = true;
        geomIterator.traversePolygonHoles() = true;
        while( geomIterator.hasMore() )
        {
            Geometry* part = geomIterator.next();
            if (!part)
                continue;

            osg::Vec4 color = osg::Vec4(1.0, 0.0, 1.0, 1.);
            float height = 1.0;
            float offset = 1.0;

            switch( part->getType())
            {
            case Geometry::TYPE_LINESTRING:
            case Geometry::TYPE_RING:
            {
                const ExtrudedLineSymbol* line = state->getStyle()->getSymbol<ExtrudedLineSymbol>();
                if (line) 
                {
                    color = line->stroke()->color();
                    height = line->extrude()->height();
                    offset = line->extrude()->offset();
                }
            }
            break;

            case Geometry::TYPE_POLYGON:
            {
                const ExtrudedPolygonSymbol* polygon = state->getStyle()->getSymbol<ExtrudedPolygonSymbol>();
                if (polygon)
                {
                    color  = polygon->fill()->color();
                    height = polygon->extrude()->height();
                    offset = polygon->extrude()->offset();
                }
            }
            break;
            default:
                continue;
                break;
            }

            osg::Geode* geode = extrude(part, offset, height, state->getContext() );
            if (geode && geode->getNumDrawables()) 
            {
                osg::Material* material = new osg::Material;
                material->setDiffuse(osg::Material::FRONT_AND_BACK, color);
                geode->getOrCreateStateSet()->setAttributeAndModes(material);
                newSymbolized->addChild(geode);
            }
        }
    }

    if (newSymbolized->getNumChildren())
    {
        attachPoint->removeChildren(0, attachPoint->getNumChildren());
        attachPoint->addChild(newSymbolized.get());
        return true;
    }

    return false;
}

Here is the call graph for this function:

osg::Geode * GeometryExtrudeSymbolizer::extrude ( Geometry geom,
double  offset,
double  height,
SymbolizerContext *  context 
)

Definition at line 126 of file GeometryExtrudeSymbolizer.cpp.

{
    if ( !geom ) return 0L;

    int numRings = 0;

    // start by offsetting the input data.
    {
        GeometryIterator i( geom );
        i.traverseMultiGeometry() = true;
        i.traversePolygonHoles() = true;
        while( i.hasMore() )
        {
            Geometry* part = i.next();
            if (offset != 0.0)
            {
                for( osg::Vec3dArray::iterator j = part->begin(); j != part->end(); j++ )
                {
                    {
                        (*j).z() += offset;
                    }
                }
            }

            // in the meantime, count the # of closed geoms. We will need to know this in 
            // order to pre-allocate the proper # of verts.
            if ( part->getType() == Geometry::TYPE_POLYGON || part->getType() == Geometry::TYPE_RING )
            {
                numRings++;
            }
        }
    }

    // now, go thru and remove any coplanar segments from the geometry. The tesselator will
    // not work include a vert connecting two colinear segments in the tesselation, and this
    // will break the stenciling logic.
#define PARALLEL_EPSILON 0.01
    GeometryIterator i( geom );
    i.traverseMultiGeometry() = true;
    i.traversePolygonHoles() = true;
    while( i.hasMore() )
    {
        Geometry* part = i.next();
        if ( part->size() >= 3 )
        {
            osg::Vec3d prevVec = part->front() - part->back();
            prevVec.normalize();

            for( osg::Vec3dArray::iterator j = part->begin(); part->size() >= 3 && j != part->end(); )
            {
                osg::Vec3d& p0 = *j;
                osg::Vec3d& p1 = j+1 != part->end() ? *(j+1) : part->front();
                osg::Vec3d vec = p1-p0; vec.normalize();

                // if the vectors are essentially parallel, remove the extraneous vertex.
                if ( (prevVec ^ vec).length() < PARALLEL_EPSILON )
                {
                    j = part->erase( j );
                    //OE_NOTICE << "removed colinear segment" << std::endl;
                }
                else
                {
                    ++j;
                    prevVec = vec;
                }
            }
        }
    }


    bool made_geom = true;

    // total up all the points so we can pre-allocate the vertex arrays.
    int num_cap_verts = geom->getTotalPointCount();
    int num_wall_verts = 2 * (num_cap_verts + numRings); // add in numRings b/c we need to close each wall

    osg::Geometry* walls = new osg::Geometry();
    osg::Vec3Array* verts = new osg::Vec3Array( num_wall_verts );
    walls->setVertexArray( verts );

    osg::Geometry* top_cap = new osg::Geometry();
    osg::Vec3Array* top_verts = new osg::Vec3Array( num_cap_verts );
    top_cap->setVertexArray( top_verts );

    osg::Geometry* bottom_cap = new osg::Geometry();
    osg::Vec3Array* bottom_verts = new osg::Vec3Array( num_cap_verts );
    bottom_cap->setVertexArray( bottom_verts );

    int wall_vert_ptr = 0;
    int top_vert_ptr = 0;
    int bottom_vert_ptr = 0;

    //double target_len = height;

    // now generate the extruded geometry.
    GeometryIterator k( geom );
    while( k.hasMore() )
    {
        Geometry* part = k.next();

        unsigned int wall_part_ptr = wall_vert_ptr;
        unsigned int top_part_ptr = top_vert_ptr;
        unsigned int bottom_part_ptr = bottom_vert_ptr;
        double part_len = 0.0;

        GLenum prim_type = part->getType() == Geometry::TYPE_POINTSET ? GL_LINES : GL_TRIANGLE_STRIP;

        for( osg::Vec3dArray::const_iterator m = part->begin(); m != part->end(); ++m )
        {
            osg::Vec3d extrude_vec;
            {
                extrude_vec.set( m->x(), m->y(), height );
            }

            (*top_verts)[top_vert_ptr++] = extrude_vec;
            (*bottom_verts)[bottom_vert_ptr++] = *m;
             
            part_len += wall_vert_ptr > wall_part_ptr?
                (extrude_vec - (*verts)[wall_vert_ptr-2]).length() :
                0.0;

            int p;

            p = wall_vert_ptr++;
            (*verts)[p] = extrude_vec;

            p = wall_vert_ptr++;
            (*verts)[p] = *m;
        }

        // close the wall if it's a ring/poly:
        if ( part->getType() == Geometry::TYPE_RING || part->getType() == Geometry::TYPE_POLYGON )
        {
            part_len += wall_vert_ptr > wall_part_ptr?
                ((*verts)[wall_part_ptr] - (*verts)[wall_vert_ptr-2]).length() :
                0.0;

            int p;

            p = wall_vert_ptr++;
            (*verts)[p] = (*verts)[wall_part_ptr];

            p = wall_vert_ptr++;
            (*verts)[p] = (*verts)[wall_part_ptr+1];
        }

        walls->addPrimitiveSet( new osg::DrawArrays(
                                    prim_type,
                                    wall_part_ptr, wall_vert_ptr - wall_part_ptr ) );

        top_cap->addPrimitiveSet( new osg::DrawArrays(
                                      osg::PrimitiveSet::LINE_LOOP,
                                      top_part_ptr, top_vert_ptr - top_part_ptr ) );

        // reverse the bottom verts so the front face is down:
        std::reverse( bottom_verts->begin()+bottom_part_ptr, bottom_verts->begin()+bottom_vert_ptr );

        bottom_cap->addPrimitiveSet( new osg::DrawArrays(
                                         osg::PrimitiveSet::LINE_LOOP,
                                         bottom_part_ptr, bottom_vert_ptr - bottom_part_ptr ) );
    }

    // build solid surfaces for the caps:
    tessellate( top_cap );
    tessellate( bottom_cap );

    osg::Geode* geode = new osg::Geode();
    geode->addDrawable( walls );
    geode->addDrawable( top_cap );
    geode->addDrawable( bottom_cap );

    return geode;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void GeometryExtrudeSymbolizer::tessellate ( osg::Geometry *  geom)

Definition at line 36 of file GeometryExtrudeSymbolizer.cpp.

{
    osgUtil::Tessellator tess;
    tess.setTessellationType( osgUtil::Tessellator::TESS_TYPE_GEOMETRY );
    tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_ODD );
//    tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_POSITIVE );
    tess.retessellatePolygons( *geom );
}

Here is the caller graph for this function:


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines