Пример #1
0
void
MovementSolute::divide_top_outgoing (const Geometry& geo, 
                                     const Chemical& chemical,
                                     const double J_above,
                                     std::map<size_t, double>& J_primary,
                                     std::map<size_t, double>& J_secondary,
                                     std::map<size_t, double>& J_tertiary)
{
  daisy_assert (J_above > 0.0); // Positive upward flux.
  const std::vector<size_t>& edge_above 
    = geo.cell_edges (Geometry::cell_above);
  const size_t edge_above_size = edge_above.size ();
  double total_amount = 0.0;    // [g/cm]
  double total_area = 0.0;      // [cm^2]

  // Find total content in primary domain in cells connected to border.
  for (size_t i = 0; i < edge_above_size; i++)
    {
      const size_t edge = edge_above[i];
      const int cell = geo.edge_other (edge, Geometry::cell_above);
      daisy_assert (geo.cell_is_internal (cell));
      const double area = geo.edge_area (edge);

      // No flux out of tertiary or secondary domains.
      J_tertiary[edge] = 0.0;
      J_secondary[edge] = 0.0;

      // Find content 
      const double M = chemical.M_primary (cell); // [g/cm^3]
      const double amount =  M * area;            // [g/cm]
      total_amount += amount;                     // [g/cm]
      total_area += area;
      J_primary[edge] = M;                        // [g/cm^3]
    }

  // Scale with content
  if (total_amount > 0.0)
    {
      // [cm/h] = [g/cm^2/h] * [cm^2] / [g/cm]
      const double scale = -J_above * total_area / total_amount;
      for (size_t i = 0; i < edge_above_size; i++)
        {
          const size_t edge = edge_above[i];
          const double in_sign 
            = geo.cell_is_internal (geo.edge_to (edge)) ? 1.0 : -1.0;
          // [g/cm^2/h] = [g/cm^3] * [cm/h]
          J_tertiary[edge] = 0.0;
          J_secondary[edge] = 0.0;
          J_primary[edge] *= in_sign * scale;
        }
    }
  else
    {
      daisy_assert (iszero (total_amount));
      for (size_t i = 0; i < edge_above_size; i++)
        {
          const size_t edge = edge_above[i];
          const double in_sign 
            = geo.cell_is_internal (geo.edge_to (edge)) ? 1.0 : -1.0;
          J_tertiary[edge] = 0.0;
          J_secondary[edge] = 0.0;
          J_primary[edge] = -J_above * in_sign;
        }
    }
}
Пример #2
0
Geometry * PolyParser::Parse ( cvct::VCTGeometry & geo )
{
	typedef std::vector<std::string> Ring;//存线
	typedef std::vector<Ring> RingList;//存环

	Ring pt;
	RingList ringlist;

	char * pTemp = NULL;
	Read ( &pTemp, geo.start_pos, geo.end_pos );
	char ** poLine = CSLTokenizeString2 ( pTemp, " \n\r\t,", 0 );

	Geometry * pGeo = new Geometry();

	//由线转面
	//线变成一个环
	//变成一个环
	//先判断是否反转
	//查找对象
	//变成一个环
	poLine = CSLAddString(poLine, "0");

	for ( int i = 0; i != CSLCount ( poLine ); ++i )
	{
		if ( EQUAL ( poLine[i], "0" ) )
		{
			ringlist.push_back ( pt );
			pt.clear();
		}

		else
		{
			pt.push_back ( std::string ( poLine[i] ) );
		}
	}

	for ( auto iRing = ringlist.begin(); iRing != ringlist.end(); ++iRing )
	{
		GeometryPart * ring = new GeometryPart();

		for ( auto iLine = iRing->begin(); iLine != iRing->end(); ++iLine )
		{
			bool bset;//true,表示反方向,false,正方向
			int  objid = atoi(iLine->c_str());

			//查找是否有“-”号,是否反转
			if ( objid > 0 )
			{
				bset = false;
			}

			else
			{
				objid = -objid;
				bset = true;
			}

			//在所有的要素中,查找线,或面对像
			auto it = vctindex->GetFeatureById(objid);

			Geometry * geoline = NULL;

			//解析线对象
			if (it->geotype == cvct::GT_LINE)
			{
				LineParser iline(vctfile, vctindex);
				geoline = iline.Parse ( it->geometry );
			}

			//解析面对象
			else if (it->geotype == cvct::GT_POLYGON)
			{
				PolyParser ipoly(vctfile, vctindex);
				geoline = ipoly.Parse ( it->geometry );
			}

			/// 增加结点个数
			geo.nVertices += it->geometry.nVertices;

			//将线对象放到环中
			if ( bset )
			{
				ring->insert ( ring->end(), geoline->operator[](0)->rbegin(), geoline->operator[](0)->rend() );
			}

			else
			{
				ring->insert ( ring->end(), geoline->operator[](0)->begin(), geoline->operator[](0)->end() );
			}

		}

		if (ring->empty())
		{
			continue;
		}

		else
		{
			pGeo->push_back ( ring );
		}
	}

	CSLDestroy ( poLine );
	CPLFree ( pTemp );

	return pGeo;
}
Пример #3
0
void
ImageOverlay::init()
{
    OpenThreads::ScopedLock< OpenThreads::Mutex > lock(_mutex);

    _geode->removeDrawables(0, _geode->getNumDrawables() );

    if ( getMapNode() )
    {
        double height = 0;
        osg::Geometry* geometry = new osg::Geometry();
        geometry->setUseVertexBufferObjects(true);

        const osg::EllipsoidModel* ellipsoid = getMapNode()->getMapSRS()->getEllipsoid();

        const SpatialReference* mapSRS = getMapNode()->getMapSRS();

        // calculate a bounding polytope in world space (for mesh clamping):
        osg::ref_ptr<Feature> f = new Feature( new Polygon(), mapSRS->getGeodeticSRS() );
        Geometry* g = f->getGeometry();
        g->push_back( osg::Vec3d(_lowerLeft.x(),  _lowerLeft.y(), 0) );
        g->push_back( osg::Vec3d(_lowerRight.x(), _lowerRight.y(), 0) );
        g->push_back( osg::Vec3d(_upperRight.x(), _upperRight.y(), 0) );
        g->push_back( osg::Vec3d(_upperLeft.x(),  _upperLeft.y(),  0) );
        //_boundingPolytope = f->getWorldBoundingPolytope();
        f->getWorldBoundingPolytope( getMapNode()->getMapSRS(), _boundingPolytope );

        // next, convert to world coords and create the geometry:
        osg::Vec3Array* verts = new osg::Vec3Array();
        verts->reserve(4);
        osg::Vec3d anchor;
        for( Geometry::iterator i = g->begin(); i != g->end(); ++i )
        {        
            osg::Vec3d map, world;        
            f->getSRS()->transform( *i, mapSRS, map);
            mapSRS->transformToWorld( map, world );
            if (i == g->begin())
            {
                anchor = world;
            }
            verts->push_back( world - anchor );
        }
        
        _transform->setMatrix( osg::Matrixd::translate( anchor ) );



        geometry->setVertexArray( verts );
        if ( verts->getVertexBufferObject() )
            verts->getVertexBufferObject()->setUsage(GL_STATIC_DRAW_ARB);

        osg::Vec4Array* colors = new osg::Vec4Array(1);
        (*colors)[0] = osg::Vec4(1,1,1,*_alpha);

        geometry->setColorArray( colors );
        geometry->setColorBinding( osg::Geometry::BIND_OVERALL );

         GLushort tris[6] = { 0, 1, 2,
                            0, 2, 3
                          };        
        geometry->addPrimitiveSet(new osg::DrawElementsUShort( GL_TRIANGLES, 6, tris ) );

        bool flip = false;
        if (_image.valid())
        {
            //Create the texture
            _texture = new osg::Texture2D(_image.get());        
            _texture->setResizeNonPowerOfTwoHint(false);
            updateFilters();
            _geode->getOrCreateStateSet()->setTextureAttributeAndModes(0, _texture, osg::StateAttribute::ON);    
            flip = _image->getOrigin()==osg::Image::TOP_LEFT;
        }

        osg::Vec2Array* texcoords = new osg::Vec2Array(4);
        (*texcoords)[0].set(0.0f,flip ? 1.0 : 0.0f);
        (*texcoords)[1].set(1.0f,flip ? 1.0 : 0.0f);
        (*texcoords)[2].set(1.0f,flip ? 0.0 : 1.0f);
        (*texcoords)[3].set(0.0f,flip ? 0.0 : 1.0f);
        geometry->setTexCoordArray(0, texcoords);

         
        //Only run the MeshSubdivider on geocentric maps
        if (getMapNode()->getMap()->isGeocentric())
        {
            MeshSubdivider ms(osg::Matrixd::inverse(_transform->getMatrix()), _transform->getMatrix());
            ms.run(*geometry, osg::DegreesToRadians(5.0), GEOINTERP_RHUMB_LINE);
        }

        _geode->addDrawable( geometry );

        _geometry = geometry;

        _dirty = false;
        
        // Set the annotation up for auto-clamping. We always need to auto-clamp a draped image
        // so that the mesh roughly conforms with the surface, otherwise the draping routine
        // might clip it.
        Style style;
        style.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN;
        applyStyle( style );
        setLightingIfNotSet( false );
        clampMesh( getMapNode()->getTerrain()->getGraph() );

        if ( Registry::capabilities().supportsGLSL() )
        {
            //OE_WARN << LC << "ShaderGen RUNNING" << std::endl;
            Registry::shaderGenerator().run( _geode, "osgEarth.ImageOverlay" );
        }
    }
}
osg::Geode*
BuildGeometryFilter::processPoints(FeatureList& features, FilterContext& context)
{
    osg::Geode* geode = new osg::Geode();

    bool makeECEF = false;
    const SpatialReference* featureSRS = 0L;
    const SpatialReference* mapSRS = 0L;

    // set up referencing information:
    if ( context.isGeoreferenced() )
    {
        makeECEF   = context.getSession()->getMapInfo().isGeocentric();
        featureSRS = context.extent()->getSRS();
        mapSRS     = context.getSession()->getMapInfo().getProfile()->getSRS();
    }

    for( FeatureList::iterator f = features.begin(); f != features.end(); ++f )
    {
        Feature* input = f->get();

        GeometryIterator parts( input->getGeometry(), true );
        while( parts.hasMore() )
        {
            Geometry* part = parts.next();

            // extract the required point symbol; bail out if not found.
            const PointSymbol* point =
                input->style().isSet() && input->style()->has<PointSymbol>() ? input->style()->get<PointSymbol>() :
                _style.get<PointSymbol>();

            if ( !point )
                continue;

            // resolve the color:
            osg::Vec4f primaryColor = point->fill()->color();
            
            osg::ref_ptr<osg::Geometry> osgGeom = new osg::Geometry();
            //osgGeom->setUseVertexBufferObjects( true );
            //osgGeom->setUseDisplayList( false );

            // embed the feature name if requested. Warning: blocks geometry merge optimization!
            if ( _featureNameExpr.isSet() )
            {
                const std::string& name = input->eval( _featureNameExpr.mutable_value(), &context );
                osgGeom->setName( name );
            }

            // build the geometry:
            osg::Vec3Array* allPoints = new osg::Vec3Array();

            transformAndLocalize( part->asVector(), featureSRS, allPoints, mapSRS, _world2local, makeECEF );

            osgGeom->addPrimitiveSet( new osg::DrawArrays(GL_POINTS, 0, allPoints->getNumElements()) );
            osgGeom->setVertexArray( allPoints );

            if ( input->style().isSet() )
            {
                //TODO: re-evaluate this. does it hinder geometry merging?
                applyPointSymbology( osgGeom->getOrCreateStateSet(), point );
            }

            // assign the primary color (PER_VERTEX required for later optimization)
            osg::Vec4Array* colors = new osg::Vec4Array;
            colors->assign( osgGeom->getVertexArray()->getNumElements(), primaryColor );
            osgGeom->setColorArray( colors );
            osgGeom->setColorBinding( osg::Geometry::BIND_PER_VERTEX );

            geode->addDrawable( osgGeom );

            // record the geometry's primitive set(s) in the index:
            if ( context.featureIndex() )
                context.featureIndex()->tagDrawable( osgGeom, input );
        
            // install clamping attributes if necessary
            if (_style.has<AltitudeSymbol>() &&
                _style.get<AltitudeSymbol>()->technique() == AltitudeSymbol::TECHNIQUE_GPU)
            {            
                Clamping::applyDefaultClampingAttrs( osgGeom, input->getDouble("__oe_verticalOffset", 0.0) );
            }
        }
    }
    
    return geode;
}
Пример #5
0
    void assemble_cortical(const Geometry& geo, Matrix& mat, const Head2EEGMat& M, const std::string& domain_name, const unsigned gauss_order, double alpha, double beta, const std::string &filename)
    {
        // Following the article: M. Clerc, J. Kybic "Cortical mapping by Laplace–Cauchy transmission using a boundary element method".
        // Assumptions:
        // - domain_name: the domain containing the sources is an innermost domain (defined as the interior of only one interface (called Cortex)
        // - Cortex interface is composed of one mesh only (no shared vertices)
        // TODO check orders of MxM products for efficiency ... delete intermediate matrices
        const Domain& SourceDomain = geo.domain(domain_name);
        const Interface& Cortex    = SourceDomain.begin()->interface();
        const Mesh& cortex         = Cortex.begin()->mesh();
        // test the assumption
        assert(SourceDomain.size() == 1);
        assert(Cortex.size() == 1);
        // shape of the new matrix:
        unsigned Nl = geo.size()-geo.outermost_interface().nb_triangles()-Cortex.nb_vertices()-Cortex.nb_triangles();
        unsigned Nc = geo.size()-geo.outermost_interface().nb_triangles();
        std::fstream f(filename.c_str());
        Matrix P;
        if ( !f ) {
            // build the HeadMat:
            // The following is the same as assemble_HM except N_11, D_11 and S_11 are not computed.
            SymMatrix mat_temp(Nc);
            mat_temp.set(0.0);
            double K = 1.0 / (4.0 * M_PI);
            // We iterate over the meshes (or pair of domains) to fill the lower half of the HeadMat (since its symmetry)
            for ( Geometry::const_iterator mit1 = geo.begin(); mit1 != geo.end(); ++mit1) {
                for ( Geometry::const_iterator mit2 = geo.begin(); (mit2 != (mit1+1)); ++mit2) {
                    // if mit1 and mit2 communicate, i.e they are used for the definition of a common domain
                    const int orientation = geo.oriented(*mit1, *mit2); // equals  0, if they don't have any domains in common
                    // equals  1, if they are both oriented toward the same domain
                    // equals -1, if they are not
                    if ( orientation != 0) {
                        double Scoeff =   orientation * geo.sigma_inv(*mit1, *mit2) * K;
                        double Dcoeff = - orientation * geo.indicator(*mit1, *mit2) * K;
                        double Ncoeff;
                        if ( !(mit1->outermost() || mit2->outermost()) && ( (*mit1 != *mit2)||( *mit1 != cortex) ) ) {
                            // Computing S block first because it's needed for the corresponding N block
                            operatorS(*mit1, *mit2, mat_temp, Scoeff, gauss_order);
                            Ncoeff = geo.sigma(*mit1, *mit2)/geo.sigma_inv(*mit1, *mit2);
                        } else {
                            Ncoeff = orientation * geo.sigma(*mit1, *mit2) * K;
                        }
                        if ( !mit1->outermost() && (( (*mit1 != *mit2)||( *mit1 != cortex) )) ) {
                            // Computing D block
                            operatorD(*mit1, *mit2, mat_temp, Dcoeff, gauss_order);
                        }
                        if ( ( *mit1 != *mit2 ) && ( !mit2->outermost() ) ) {
                            // Computing D* block
                            operatorD(*mit1, *mit2, mat_temp, Dcoeff, gauss_order, true);
                        }
                        // Computing N block
                        if ( (*mit1 != *mit2)||( *mit1 != cortex) ) {
                            operatorN(*mit1, *mit2, mat_temp, Ncoeff, gauss_order);
                        }
                    }
                }
            }
            // Deflate the diagonal block (N33) of 'mat' : (in order to have a zero-mean potential for the outermost interface)
            const Interface i = geo.outermost_interface();
            unsigned i_first = (*i.begin()->mesh().vertex_begin())->index();
            deflat(mat_temp, i, mat_temp(i_first, i_first) / (geo.outermost_interface().nb_vertices()));

            mat = Matrix(Nl, Nc);
            mat.set(0.0);
            // copy mat_temp into mat except the lines for cortex vertices [i_vb_c, i_ve_c] and cortex triangles [i_tb_c, i_te_c].
            unsigned iNl = 0;
            unsigned i_vb_c = (*cortex.vertex_begin())->index();
            unsigned i_ve_c = (*cortex.vertex_rbegin())->index();
            unsigned i_tb_c = cortex.begin()->index();
            unsigned i_te_c = cortex.rbegin()->index();
            for ( unsigned i = 0; i < Nc; ++i) {
                if ( !(i_vb_c<=i && i<=i_ve_c) && !(i_tb_c<=i && i<=i_te_c) ) {
                    mat.setlin(iNl, mat_temp.getlin(i));
                    ++iNl;
                }
            }
            // ** Construct P: the null-space projector **
            Matrix W;
            {
                Matrix U, s;
                mat.svd(U, s, W);
            }

            SparseMatrix S(Nc,Nc);
            // we set S to 0 everywhere, except in the last part of the diag:
            for ( unsigned i = Nl; i < Nc; ++i) {
                S(i, i) = 1.0;
            }
            P = (W * S) * W.transpose(); // P is a projector: P^2 = P and mat*P*X = 0
            if ( filename.length() != 0 ) {
                std::cout << "Saving projector P (" << filename << ")." << std::endl;
                P.save(filename);
            }
        } else {
            std::cout << "Loading projector P (" << filename << ")." << std::endl;
            P.load(filename);
        }

        // ** Get the gradient of P1&P0 elements on the meshes **
        Matrix MM(M.transpose() * M);
        SymMatrix RR(Nc, Nc); RR.set(0.);
        for ( Geometry::const_iterator mit = geo.begin(); mit != geo.end(); ++mit) {
            mit->gradient_norm2(RR);
        }

        // ** Choose Regularization parameter **
        SparseMatrix alphas(Nc,Nc); // diagonal matrix
        Matrix Z;
        if ( alpha < 0 ) { // try an automatic method... TODO find better estimation
            double nRR_v = RR.submat(0, geo.nb_vertices(), 0, geo.nb_vertices()).frobenius_norm();
            alphas.set(0.);
            alpha = MM.frobenius_norm() / (1.e3*nRR_v);
            beta  = alpha * 50000.;
            for ( Vertices::const_iterator vit = geo.vertex_begin(); vit != geo.vertex_end(); ++vit) {
                alphas(vit->index(), vit->index()) = alpha;
            }
            for ( Meshes::const_iterator mit = geo.begin(); mit != geo.end(); ++mit) {
                if ( !mit->outermost() ) {
                    for ( Mesh::const_iterator tit = mit->begin(); tit != mit->end(); ++tit) {
                        alphas(tit->index(), tit->index()) = beta;
                    }
                }
            }
            std::cout << "AUTOMATIC alphas = " << alpha << "\tbeta = " << beta << std::endl;
        } else {
            for ( Vertices::const_iterator vit = geo.vertex_begin(); vit != geo.vertex_end(); ++vit) {
                alphas(vit->index(), vit->index()) = alpha;
            }
            for ( Meshes::const_iterator mit = geo.begin(); mit != geo.end(); ++mit) {
                if ( !mit->outermost() ) {
                    for ( Mesh::const_iterator tit = mit->begin(); tit != mit->end(); ++tit) {
                        alphas(tit->index(), tit->index()) = beta;
                    }
                }
            }
            std::cout << "alphas = " << alpha << "\tbeta = " << beta << std::endl;
        }
        Z = P.transpose() * (MM + alphas*RR) * P;

        // ** PseudoInverse and return **
        // X = P * { (M*P)' * (M*P) + (R*P)' * (R*P) }¡(-1) * (M*P)'m
        // X = P * { P'*M'*M*P + P'*R'*R*P }¡(-1) * P'*M'm
        // X = P * { P'*(MM + a*RR)*P }¡(-1) * P'*M'm
        // X = P * Z¡(-1) * P' * M'm
        Matrix rhs = P.transpose() * M.transpose();
        mat = P * Z.pinverse() * rhs;
    }
Пример #6
0
void DecalSet::GetFaces(Vector<PODVector<DecalVertex> >& faces, Drawable* target, unsigned batchIndex, const Frustum& frustum,
    const Vector3& decalNormal, float normalCutoff)
{
    // Try to use the most accurate LOD level if possible
    Geometry* geometry = target->GetLodGeometry(batchIndex, 0);
    if (!geometry || geometry->GetPrimitiveType() != TRIANGLE_LIST)
        return;
    
    const unsigned char* positionData = 0;
    const unsigned char* normalData = 0;
    const unsigned char* skinningData = 0;
    const unsigned char* indexData = 0;
    unsigned positionStride = 0;
    unsigned normalStride = 0;
    unsigned skinningStride = 0;
    unsigned indexStride = 0;
    
    IndexBuffer* ib = geometry->GetIndexBuffer();
    if (ib)
    {
        indexData = ib->GetShadowData();
        indexStride = ib->GetIndexSize();
    }
    
    // For morphed models positions, normals and skinning may be in different buffers
    for (unsigned i = 0; i < geometry->GetNumVertexBuffers(); ++i)
    {
        VertexBuffer* vb = geometry->GetVertexBuffer(i);
        if (!vb)
            continue;
        
        unsigned elementMask = geometry->GetVertexElementMask(i);
        unsigned char* data = vb->GetShadowData();
        if (!data)
            continue;
        
        if (elementMask & MASK_POSITION)
        {
            positionData = data;
            positionStride = vb->GetVertexSize();
        }
        if (elementMask & MASK_NORMAL)
        {
            normalData = data + vb->GetElementOffset(ELEMENT_NORMAL);
            normalStride = vb->GetVertexSize();
        }
        if (elementMask & MASK_BLENDWEIGHTS)
        {
            skinningData = data + vb->GetElementOffset(ELEMENT_BLENDWEIGHTS);
            skinningStride = vb->GetVertexSize();
        }
    }
    
    // Positions and indices are needed
    if (!positionData)
    {
        // As a fallback, try to get the geometry's raw vertex/index data
        unsigned elementMask;
        geometry->GetRawData(positionData, positionStride, indexData, indexStride, elementMask);
        if (!positionData)
        {
            LOGWARNING("Can not add decal, target drawable has no CPU-side geometry data");
            return;
        }
    }
    
    if (indexData)
    {
        unsigned indexStart = geometry->GetIndexStart();
        unsigned indexCount = geometry->GetIndexCount();
        
        // 16-bit indices
        if (indexStride == sizeof(unsigned short))
        {
            const unsigned short* indices = ((const unsigned short*)indexData) + indexStart;
            const unsigned short* indicesEnd = indices + indexCount;
            
            while (indices < indicesEnd)
            {
                GetFace(faces, target, batchIndex, indices[0], indices[1], indices[2], positionData, normalData, skinningData,
                    positionStride, normalStride, skinningStride, frustum, decalNormal, normalCutoff);
                indices += 3;
            }
        }
        else
        // 32-bit indices
        {
            const unsigned* indices = ((const unsigned*)indexData) + indexStart;
            const unsigned* indicesEnd = indices + indexCount;
            
            while (indices < indicesEnd)
            {
                GetFace(faces, target, batchIndex, indices[0], indices[1], indices[2], positionData, normalData, skinningData,
                    positionStride, normalStride, skinningStride, frustum, decalNormal, normalCutoff);
                indices += 3;
            }
        }
    }
    else
    {
        // Non-indexed geometry
        unsigned indices = geometry->GetVertexStart();
        unsigned indicesEnd = indices + geometry->GetVertexCount();
        
        while (indices + 2 < indicesEnd)
        {
            GetFace(faces, target, batchIndex, indices, indices + 1, indices + 2, positionData, normalData, skinningData,
                positionStride, normalStride, skinningStride, frustum, decalNormal, normalCutoff);
            indices += 3;
        }
    }
}
osg::Geode*
BuildGeometryFilter::processPolygonizedLines(FeatureList&   features, 
                                             bool           twosided,
                                             FilterContext& context)
{
    osg::Geode* geode = new osg::Geode();

    // establish some referencing
    bool                    makeECEF   = false;
    const SpatialReference* featureSRS = 0L;
    const SpatialReference* mapSRS     = 0L;

    if ( context.isGeoreferenced() )
    {
        makeECEF   = context.getSession()->getMapInfo().isGeocentric();
        featureSRS = context.extent()->getSRS();
        mapSRS     = context.getSession()->getMapInfo().getProfile()->getSRS();
    }

    // iterate over all features.
    for( FeatureList::iterator i = features.begin(); i != features.end(); ++i )
    {
        Feature* input = i->get();
        // extract the required line symbol; bail out if not found.
        const LineSymbol* line =
            input->style().isSet() && input->style()->has<LineSymbol>() ? input->style()->get<LineSymbol>() :
            _style.get<LineSymbol>();

        if ( !line )
            continue;

        // run a symbol script if present.
        if ( line->script().isSet() )
        {
            StringExpression temp( line->script().get() );
            input->eval( temp, &context );
        }

        // The operator we'll use to make lines into polygons.
        PolygonizeLinesOperator polygonizer( *line->stroke() );

        // iterate over all the feature's geometry parts. We will treat
        // them as lines strings.
        GeometryIterator parts( input->getGeometry(), true );
        while( parts.hasMore() )
        {
            Geometry* part = parts.next();

            // if the underlying geometry is a ring (or a polygon), close it so the
            // polygonizer will generate a closed loop.
            Ring* ring = dynamic_cast<Ring*>(part);
            if ( ring )
                ring->close();

            // skip invalid geometry
            if ( part->size() < 2 )
                continue;

            // transform the geometry into the target SRS and localize it about 
            // a local reference point.
            osg::ref_ptr<osg::Vec3Array> verts   = new osg::Vec3Array();
            osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array();
            transformAndLocalize( part->asVector(), featureSRS, verts.get(), normals.get(), mapSRS, _world2local, makeECEF );

            // turn the lines into polygons.
            osg::Geometry* geom = polygonizer( verts.get(), normals.get(), twosided );
            if ( geom )
            {
                geode->addDrawable( geom );
            }

            // record the geometry's primitive set(s) in the index:
            if ( context.featureIndex() )
                context.featureIndex()->tagDrawable( geom, input );
        
            // install clamping attributes if necessary
            if (_style.has<AltitudeSymbol>() &&
                _style.get<AltitudeSymbol>()->technique() == AltitudeSymbol::TECHNIQUE_GPU)
            {
                Clamping::applyDefaultClampingAttrs( geom, input->getDouble("__oe_verticalOffset", 0.0) );
            }
        }

        polygonizer.installShaders( geode );
    }
    return geode;
}
Пример #8
0
void Implicit::Render()
{
  // Draw bounding box for debugging
  Bbox b = GetBoundingBox();

  Vector3<float> & v0 = b.pMin;
  Vector3<float> & v1 = b.pMax;

  if(mSelected) {
    glLineWidth(2.0f);
    glColor3f(0.8f,0.8f,0.8f);
  }
  else glColor3f(0.1f,0.1f,0.1f);

  glBegin(GL_LINE_STRIP);
  glVertex3f(v0[0], v0[1], v0[2]);
  glVertex3f(v1[0], v0[1], v0[2]);
  glVertex3f(v1[0], v1[1], v0[2]);
  glVertex3f(v0[0], v1[1], v0[2]);
  glVertex3f(v0[0], v0[1], v0[2]);
  glEnd();

  glBegin(GL_LINE_STRIP);
  glVertex3f(v0[0], v0[1], v1[2]);
  glVertex3f(v1[0], v0[1], v1[2]);
  glVertex3f(v1[0], v1[1], v1[2]);
  glVertex3f(v0[0], v1[1], v1[2]);
  glVertex3f(v0[0], v0[1], v1[2]);
  glEnd();

  glBegin(GL_LINES);
  glVertex3f(v0[0], v0[1], v0[2]);
  glVertex3f(v0[0], v0[1], v1[2]);

  glVertex3f(v1[0], v0[1], v0[2]);
  glVertex3f(v1[0], v0[1], v1[2]);

  glVertex3f(v0[0], v1[1], v0[2]);
  glVertex3f(v0[0], v1[1], v1[2]);

  glVertex3f(v1[0], v1[1], v0[2]);
  glVertex3f(v1[0], v1[1], v1[2]);
  glEnd();
  glLineWidth(1.0f);
  glPushMatrix();
  glMultMatrixf(mTransform.ToGLMatrix().GetArrayPtr());

  Geometry * mesh = dynamic_cast<Geometry *>(mMesh);
  if (mesh == NULL)
    std::cerr << "Error: implicit geometry not triangulated, add call to triangulate()" << std::endl;
  else {
    mesh->SetShowNormals(mShowNormals);
    mesh->SetWireframe(mWireframe);
    mesh->SetOpacity(mOpacity);

    mesh->Render();
  }

  if (mVisualizationMode == Gradients) {
    if(typeid(*mMesh) == typeid(SimpleMesh)){

      SimpleMesh * ptr = static_cast<SimpleMesh*>(mMesh);
      const std::vector<SimpleMesh::Vertex>& verts = ptr->GetVerts();

      glDisable(GL_LIGHTING);

      Matrix4x4<float> M = GetTransform().Transpose();

      glColor3f(0, 0, 1);
      glBegin(GL_LINES);
      for(unsigned int i=0; i < verts.size(); i++){
        const Vector3<float> vObject = verts.at(i).pos;

        // Transform vertex position to world space
        Vector4<float> vWorld = GetTransform() * Vector4<float>(vObject[0],vObject[1],vObject[2],1);

        // Get gradient in world space
        Vector3<float> nWorld = GetGradient(vWorld[0], vWorld[1], vWorld[2]);

        // Transform gradient to object space
        Vector4<float> nObject = M * Vector4<float>(nWorld[0],nWorld[1],nWorld[2],0);
        Vector3<float> n = Vector3<float>(nObject[0], nObject[1], nObject[2]);

        glVertex3fv(vObject.GetArrayPtr());
        glVertex3fv((vObject + n*0.1).GetArrayPtr());
      }
      glEnd();
    }
    else {
      std::cerr << "No Gradient visualization mode implemented for mesh type: " << typeid(*mMesh).name() << std::endl;
    }
  }

  glPopMatrix();

  GLObject::Render();
}
Пример #9
0
void
BuildGeometryFilter::tileAndBuildPolygon(Geometry*               ring,
                                         const SpatialReference* featureSRS,
                                         const SpatialReference* outputSRS,
                                         bool                    makeECEF,
                                         bool                    tessellate,
                                         osg::Geometry*          osgGeom,
                                         const osg::Matrixd      &world2local)
{
#define MAX_POINTS_PER_CROP_TILE 1024
//#define TARGET_TILE_SIZE_EXTENT_DEGREES 5

    if ( ring == 0L )
    {
        OE_WARN << LC << "Ring is NULL.\n";
        return;
    }
    
    // Tile the incoming polygon if necessary
    // NB: this breaks down at higher latitudes; see https://github.com/gwaldron/osgearth/issues/746

    GeometryCollection tiles;
    if (_maxPolyTilingAngle_deg.isSet())
        prepareForTesselation( ring, featureSRS, _maxPolyTilingAngle_deg.get(), MAX_POINTS_PER_CROP_TILE, tiles);    
    else
        tiles.push_back( ring );

    osg::ref_ptr<osg::Geode> geode = new osg::Geode;

    //OE_NOTICE << LC << "TABP: tiles = " << tiles.size() << "\n";

    // Process each ring independently
    for (int ringIndex = 0; ringIndex < tiles.size(); ringIndex++)
    {
        Geometry* geom = tiles[ringIndex].get();
        if (geom)
        {
            // temporary target geometry for this cell:
            osg::ref_ptr<osg::Geometry> temp = new osg::Geometry();
            temp->setVertexArray( new osg::Vec3Array() );

            // establish a local plane for this cell based on its centroid:
            GeoPoint cellCenter(featureSRS, geom->getBounds().center());
            cellCenter.transform(outputSRS, cellCenter);                        
            osg::Matrix world2cell;
            cellCenter.createWorldToLocal( world2cell );

            // build the localized polygon:
            buildPolygon(geom, featureSRS, outputSRS, makeECEF, temp.get(), world2cell);

            // if successful, transform the verts back into our master LTP:
            if ( temp->getNumPrimitiveSets() > 0 )
            {
                // Tesselate the polygon while the coordinates are still in the LTP
                if (tesselateGeometry( temp.get() ))
                {
                    osg::Vec3Array* verts = static_cast<osg::Vec3Array*>(temp->getVertexArray());
                    if ( verts->getNumElements() > 0 )
                    {
                        // Convert the coordinates back to the master LTP.
                        // This is ok, but you will probably run into precision errors if the tile size is very large.
                        osg::Matrix cell2world;
                        cell2world.invert( world2cell );
                        osg::Matrix cell2local = cell2world * world2local; // pre-multiply to avoid precision loss

                        for(int i=0; i<verts->size(); ++i)
                        {
                            (*verts)[i] = (*verts)[i] * cell2local;
                        }
                        geode->addDrawable(temp.get());
                    }
                }
            }
        }
        else
        {
            OE_TEST << LC << "TABP: Uh oh. found a non-Ring geometry: " << geom->toString(geom->getComponentType()) << "\n";
        }
    }

    // The geode is going to contain all of our polygons now, so merge them into one.
    osgUtil::Optimizer optimizer;
    osgUtil::Optimizer::MergeGeometryVisitor mgv;
    // We only want one Geometry, so don't limit the number of vertices.
    mgv.setTargetMaximumNumberOfVertices(UINT_MAX);
    mgv.apply( *geode.get() );

    // and copy them into the output geometry.
    if ( geode->getNumDrawables() > 0 )
    {
        // If we have more than one drawable after the MergeGeometryVisitor ran, we have a problem so
        // dump out some info to help debug.
        if (geode->getNumDrawables() != 1)
        {
            OE_WARN << LC << "MergeGeometryVisitor failed to merge geometries into a single one.  Num drawables " << geode->getNumDrawables() << std::endl;            
            for (unsigned int i = 0; i < geode->getNumDrawables(); i++)
            {
                osg::Geometry* g = geode->getDrawable(i)->asGeometry();
                if (g)
                {
                    osg::Vec3Array* verts = dynamic_cast<osg::Vec3Array*>(g->getVertexArray());
                    if (verts)
                    {
                        OE_WARN << "Geometry " << i << " has " << verts->size() << " verts" << std::endl;
                        OE_WARN << "Geometry " << i << " has " << g->getNumPrimitiveSets() << " primitive sets" << std::endl;
                        for (unsigned int j = 0; j < g->getNumPrimitiveSets(); j++)
                        {
                            osg::PrimitiveSet* ps = g->getPrimitiveSet(j);
                            OE_WARN << "PrimitiveSet " << j << ps->className() << std::endl;
                        }
                    }
                }
            }
        }
        osgGeom->setVertexArray( geode->getDrawable(0)->asGeometry()->getVertexArray() );
        osgGeom->setPrimitiveSetList( geode->getDrawable(0)->asGeometry()->getPrimitiveSetList() );
    }

    osgUtil::SmoothingVisitor::smooth( *osgGeom );
}
Пример #10
0
ref_ptr<osg::Geode>
arengine::Image::createGeodeForImage(osg::Image* image,int posx, int posy, int width, int height)
{
	if (image)
	{
		if (width>0 && height>0)
		{

			float y = 1.0;
			float x = y*((float)width/float(height));

			// set up the texture.

			Config *config = Singleton<Config>::getInstance();

			osg::Texture *texture;
			float texcoord_x;
			float texcoord_y;
			if (config->useTexture2D())
			{
				osg::Texture2D *texture2D = new osg::Texture2D;
				texture2D->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
				texture2D->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
				texture2D->setResizeNonPowerOfTwoHint(false);
				texture2D->setImage(image);

				texcoord_x = 1.0f;
				texcoord_y = 1.0f;
				texture = texture2D;
			}
			else
			{
				osg::TextureRectangle *textureRect = new osg::TextureRectangle;
				textureRect->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
				textureRect->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
				//texture->setResizeNonPowerOfTwoHint(false);
				textureRect->setImage(image);

				texcoord_x = image->s();
				texcoord_y = image->t();
				texture = textureRect;
			}

			// set up the drawstate.
			osg::StateSet* dstate = new osg::StateSet;
			dstate->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
			dstate->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
			dstate->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON);

			// set up the geoset.
			Geometry* geom = new Geometry;
			geom->setStateSet(dstate);

			Vec2Array* coords = new Vec2Array(4);
			(*coords)[0].set(posx, posy + height);
			(*coords)[1].set(posx, posy);
			(*coords)[2].set(posx + width, posy);
			(*coords)[3].set(posx + width, posy + height);
			geom->setVertexArray(coords);

			Vec2Array* tcoords = new Vec2Array(4);
			(*tcoords)[0].set(0.0f*texcoord_x,1.0f*texcoord_y);
			(*tcoords)[1].set(0.0f*texcoord_x,0.0f*texcoord_y);
			(*tcoords)[2].set(1.0f*texcoord_x,0.0f*texcoord_y);
			(*tcoords)[3].set(1.0f*texcoord_x,1.0f*texcoord_y);
			geom->setTexCoordArray(0,tcoords);

			osg::Vec4Array* colours = new osg::Vec4Array(1);
			(*colours)[0].set(1.0f,1.0f,1.0,1.0f);
			geom->setColorArray(colours);
			geom->setColorBinding(Geometry::BIND_OVERALL);

			geom->addPrimitiveSet(new DrawArrays(PrimitiveSet::QUADS,0,4));

			// set up the geode.
			osg::Geode* geode = new osg::Geode;
			geode->addDrawable(geom);

			return geode;

		}
		else
		{
			return NULL;
		}
	}
	else
	{
		return NULL;
	}
}
Пример #11
0
osg::Node* BuildTextOperator::operator()(const FeatureList&   features,
        const TextSymbol*    symbol,
        const FilterContext& context)
{
    if (!symbol) return 0;

    std::set< std::string > labelNames;

    bool removeDuplicateLabels = symbol->removeDuplicateLabels().isSet() ? symbol->removeDuplicateLabels().get() : false;

    StringExpression contentExpr = *symbol->content();

    osg::Geode* result = new osg::Geode;
    for (FeatureList::const_iterator itr = features.begin(); itr != features.end(); ++itr)
    {
        Feature* feature = itr->get();
        if (!feature->getGeometry()) continue;

        std::string text;
        //If the feature is a TextAnnotation, just get the value from it
        TextAnnotation* annotation = dynamic_cast<TextAnnotation*>(feature);
        if (annotation)
        {
            text = annotation->text();
        }
        else if (symbol->content().isSet())
        {
            //Get the text from the specified content and referenced attributes
            text = feature->eval( contentExpr );
            //std::string content = symbol->content().value();
            //text = parseAttributes(feature, content, symbol->contentAttributeDelimiter().value());
        }
        //else if (symbol->attribute().isSet())
        //{
        //    //Get the text from the specified attribute
        //    std::string attr = symbol->attribute().value();
        //    text = feature->getAttr(attr);
        //}

        if (text.empty()) continue;

        //See if there is a duplicate name
        if (removeDuplicateLabels && labelNames.find(text) != labelNames.end()) continue;

        bool rotateToScreen = symbol->rotateToScreen().isSet() ? symbol->rotateToScreen().value() : false;

        // find the centroid
        osg::Vec3d position;
        osg::Quat orientation;

        GeometryIterator gi( feature->getGeometry() );
        while( gi.hasMore() )
        {
            Geometry* geom = gi.next();

            TextSymbol::LinePlacement linePlacement = symbol->linePlacement().isSet() ? symbol->linePlacement().get() : TextSymbol::LINEPLACEMENT_ALONG_LINE;
            if (geom->getType() == Symbology::Geometry::TYPE_LINESTRING && linePlacement == TextSymbol::LINEPLACEMENT_ALONG_LINE)
            {
                //Compute the "middle" of the line string
                LineString* lineString = static_cast<LineString*>(geom);
                double length = lineString->getLength();
                double center = length / 2.0;
                osg::Vec3d start, end;
                if (lineString->getSegment(center, start, end))
                {
                    TextSymbol::LineOrientation lineOrientation = symbol->lineOrientation().isSet() ? symbol->lineOrientation().get() : TextSymbol::LINEORIENTATION_HORIZONTAL;

                    position = (end + start) / 2.0;
                    //We don't want to orient the text at all if we are rotating to the screen
                    if (!rotateToScreen && lineOrientation != TextSymbol::LINEORIENTATION_HORIZONTAL)
                    {
                        osg::Vec3d dir = (end-start);
                        dir.normalize();

                        if (lineOrientation == TextSymbol::LINEORIENTATION_PERPENDICULAR)
                        {
                            osg::Vec3d up(0,0,1);
                            const SpatialReference* srs = context.profile()->getSRS();
                            if (srs && context.isGeocentric() && srs->getEllipsoid())
                            {
                                osg::Vec3d w = context.toWorld( position );
                                up = srs->getEllipsoid()->computeLocalUpVector(w.x(), w.y(), w.z());
                            }
                            dir = up ^ dir;
                        }
                        orientation.makeRotate(osg::Vec3d(1,0,0), dir);
                    }
                }
                else
                {
                    //Fall back on using the center
                    position = lineString->getBounds().center();
                }
            }
            else
            {
                position = geom->getBounds().center();
            }
        }

        osgText::Text* t = new osgText::Text();
        t->setText( text );

        std::string font = "fonts/arial.ttf";
        if (symbol->font().isSet() && !symbol->font().get().empty())
        {
            font = symbol->font().value();
        }

        t->setFont( font );
        t->setAutoRotateToScreen( rotateToScreen );

        TextSymbol::SizeMode sizeMode = symbol->sizeMode().isSet() ? symbol->sizeMode().get() : TextSymbol::SIZEMODE_SCREEN;
        if (sizeMode == TextSymbol::SIZEMODE_SCREEN) {
            t->setCharacterSizeMode( osgText::TextBase::SCREEN_COORDS );
        }
        else if (sizeMode == TextSymbol::SIZEMODE_OBJECT) {
            t->setCharacterSizeMode( osgText::TextBase::OBJECT_COORDS );
        }
        float size = symbol->size().isSet() ? symbol->size().get() : 32.0f;
        t->setCharacterSize( size );
        /*
        //TODO:  We need to do something to account for autotransformed text that is under a LOD.  Setting the initial bound works sometimes but not all the time.
        if (rotateToScreen)
        {
            //Set the initial bound so that OSG will traverse the text even if it's under an LOD.
            osg::BoundingBox bb;
            bb.expandBy( osg::BoundingSphere(position, size));
            t->setInitialBound( bb);
        }*/
        //t->setCharacterSizeMode( osgText::TextBase::OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT );
        //t->setCharacterSize( 300000.0f );
        t->setPosition( position );
        t->setRotation( orientation);
        t->setAlignment( osgText::TextBase::CENTER_CENTER );
        t->getOrCreateStateSet()->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS), osg::StateAttribute::ON );
        t->getOrCreateStateSet()->setRenderBinDetails( 99999, "RenderBin", osg::StateSet::OVERRIDE_RENDERBIN_DETAILS );

        // apply styling as appropriate:
        osg::Vec4f textColor = symbol->fill()->color();
        osg::Vec4f haloColor = symbol->halo()->color();

        t->setColor( textColor );
        t->setBackdropColor( haloColor );
        t->setBackdropType( osgText::Text::OUTLINE );

        if ( context.isGeocentric() )
        {
            // install a cluster culler
            t->setCullCallback( new CullPlaneCallback( position * context.inverseReferenceFrame() ) );
        }

        if (_hideClutter)
        {
            osg::BoundingBox tBound = t->getBound();
            osg::ref_ptr<osgUtil::PolytopeIntersector> intersector = new osgUtil::PolytopeIntersector(osgUtil::Intersector::MODEL, tBound.xMin(), tBound.yMin(), tBound.xMax(), tBound.yMax());
            osgUtil::IntersectionVisitor intersectVisitor(intersector.get());
            result->accept(intersectVisitor);

            if (!intersector->containsIntersections())
            {
                result->addDrawable( t );
                if (removeDuplicateLabels) labelNames.insert(text);
            }
        }
        else
        {
            result->addDrawable( t );
            if (removeDuplicateLabels) labelNames.insert(text);
        }
    }
    return result;
}
Пример #12
0
bool
ExtrudeGeometryFilter::process( FeatureList& features, FilterContext& context )
{
    // seed our random number generators
    Random wallSkinPRNG( _wallSkinSymbol.valid()? *_wallSkinSymbol->randomSeed() : 0, Random::METHOD_FAST );
    Random roofSkinPRNG( _roofSkinSymbol.valid()? *_roofSkinSymbol->randomSeed() : 0, Random::METHOD_FAST );

    for( FeatureList::iterator f = features.begin(); f != features.end(); ++f )
    {
        Feature* input = f->get();

        GeometryIterator iter( input->getGeometry(), false );
        while( iter.hasMore() )
        {
            Geometry* part = iter.next();

            osg::ref_ptr<osg::Geometry> walls = new osg::Geometry();
            walls->setUseVertexBufferObjects( _useVertexBufferObjects.get() );
            
            osg::ref_ptr<osg::Geometry> rooflines = 0L;
            osg::ref_ptr<osg::Geometry> baselines = 0L;
            osg::ref_ptr<osg::Geometry> outlines  = 0L;
            
            if ( part->getType() == Geometry::TYPE_POLYGON )
            {
                rooflines = new osg::Geometry();
                rooflines->setUseVertexBufferObjects( _useVertexBufferObjects.get() );

                // prep the shapes by making sure all polys are open:
                static_cast<Polygon*>(part)->open();
            }

            // fire up the outline geometry if we have a line symbol.
            if ( _outlineSymbol != 0L )
            {
                outlines = new osg::Geometry();
                outlines->setUseVertexBufferObjects( _useVertexBufferObjects.get() );
            }

            // make a base cap if we're doing stencil volumes.
            if ( _makeStencilVolume )
            {
                baselines = new osg::Geometry();
                baselines->setUseVertexBufferObjects( _useVertexBufferObjects.get() );
            }

            // calculate the extrusion height:
            float height;

            if ( _heightCallback.valid() )
            {
                height = _heightCallback->operator()(input, context);
            }
            else if ( _heightExpr.isSet() )
            {
                height = input->eval( _heightExpr.mutable_value(), &context );
            }
            else
            {
                height = *_extrusionSymbol->height();
            }

            // calculate the height offset from the base:
            float offset = 0.0;
            if ( _heightOffsetExpr.isSet() )
            {
                offset = input->eval( _heightOffsetExpr.mutable_value(), &context );
            }

            osg::ref_ptr<osg::StateSet> wallStateSet;
            osg::ref_ptr<osg::StateSet> roofStateSet;

            // calculate the wall texturing:
            SkinResource* wallSkin = 0L;
            if ( _wallSkinSymbol.valid() )
            {
                if ( _wallResLib.valid() )
                {
                    SkinSymbol querySymbol( *_wallSkinSymbol.get() );
                    querySymbol.objectHeight() = fabs(height) - offset;
                    wallSkin = _wallResLib->getSkin( &querySymbol, wallSkinPRNG, context.getDBOptions() );
                }

                else
                {
                    //TODO: simple single texture?
                }
            }

            // calculate the rooftop texture:
            SkinResource* roofSkin = 0L;
            if ( _roofSkinSymbol.valid() )
            {
                if ( _roofResLib.valid() )
                {
                    SkinSymbol querySymbol( *_roofSkinSymbol.get() );
                    roofSkin = _roofResLib->getSkin( &querySymbol, roofSkinPRNG, context.getDBOptions() );
                }

                else
                {
                    //TODO: simple single texture?
                }
            }

            // calculate the colors:
            osg::Vec4f wallColor(1,1,1,0), wallBaseColor(1,1,1,0), roofColor(1,1,1,0), outlineColor(1,1,1,1);

            if ( _wallPolygonSymbol.valid() )
            {
                wallColor = _wallPolygonSymbol->fill()->color();
                if ( _extrusionSymbol->wallGradientPercentage().isSet() )
                {
                    wallBaseColor = Color(wallColor).brightness( 1.0 - *_extrusionSymbol->wallGradientPercentage() );
                }
                else
                {
                    wallBaseColor = wallColor;
                }
            }
            if ( _roofPolygonSymbol.valid() )
            {
                roofColor = _roofPolygonSymbol->fill()->color();
            }
            if ( _outlineSymbol.valid() )
            {
                outlineColor = _outlineSymbol->stroke()->color();
            }

            // Create the extruded geometry!
            if (extrudeGeometry( 
                    part, height, offset, 
                    *_extrusionSymbol->flatten(),
                    walls.get(), rooflines.get(), baselines.get(), outlines.get(),
                    wallColor, wallBaseColor, roofColor, outlineColor,
                    wallSkin, roofSkin,
                    context ) )
            {      
                if ( wallSkin )
                {
                    context.resourceCache()->getOrCreateStateSet( wallSkin, wallStateSet );
                }

                // generate per-vertex normals, altering the geometry as necessary to avoid
                // smoothing around sharp corners
                osgUtil::SmoothingVisitor::smooth(
                    *walls.get(), 
                    osg::DegreesToRadians(_wallAngleThresh_deg) );

                // tessellate and add the roofs if necessary:
                if ( rooflines.valid() )
                {
                    osgUtil::Tessellator tess;
                    tess.setTessellationType( osgUtil::Tessellator::TESS_TYPE_GEOMETRY );
                    tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_ODD );
                    tess.retessellatePolygons( *(rooflines.get()) );

                    // generate default normals (no crease angle necessary; they are all pointing up)
                    // TODO do this manually; probably faster
                    if ( !_makeStencilVolume )
                        osgUtil::SmoothingVisitor::smooth( *rooflines.get() );

                    if ( roofSkin )
                    {
                        context.resourceCache()->getOrCreateStateSet( roofSkin, roofStateSet );
                    }
                }

                if ( baselines.valid() )
                {
                    osgUtil::Tessellator tess;
                    tess.setTessellationType( osgUtil::Tessellator::TESS_TYPE_GEOMETRY );
                    tess.setWindingType( osgUtil::Tessellator::TESS_WINDING_ODD );
                    tess.retessellatePolygons( *(baselines.get()) );
                }

                std::string name;
                if ( !_featureNameExpr.empty() )
                    name = input->eval( _featureNameExpr, &context );

                FeatureSourceIndex* index = context.featureIndex();

                addDrawable( walls.get(), wallStateSet.get(), name, input, index );

                if ( rooflines.valid() )
                {
                    addDrawable( rooflines.get(), roofStateSet.get(), name, input, index );
                }

                if ( baselines.valid() )
                {
                    addDrawable( baselines.get(), 0L, name, input, index );
                }

                if ( outlines.valid() )
                {
                    addDrawable( outlines.get(), 0L, name, input, index );
                }
            }   
        }
    }

    return true;
}
Action::ResultE GeometryMergeGraphOp::traverseLeave(
        Node * const node, Action::ResultE res)
{
    if(isInExcludeList(node))
        return Action::Skip;

    NodeCore *core = node->getCore();
    
    // skip cores with a dependency on the children number/order
    // TODO: find a way to make this extendable
    if(core == NULL                                               ||
       core->getType().isDerivedFrom(DistanceLOD::getClassType()) ||
       core->getType().isDerivedFrom(ScreenLOD  ::getClassType()) ||
       core->getType().isDerivedFrom(Switch     ::getClassType()) ||
       core->getType().isDerivedFrom(MultiCore  ::getClassType())   )
    {
        return Action::Continue;
    }
    
    typedef std::vector<NodeUnrecPtr> NodeStore;
    NodeStore addStore;     // nodes to add as children to current one
    NodeStore subStore;     // nodes (children) to remove from current one
    
    typedef std::vector<Node *    > MergeGroup; // geometries that can be merged
    typedef std::vector<MergeGroup> MergeList;  // list of merge groups
    
    MergeList                            ml;
    Node::MFChildrenType::const_iterator childIt  =
            node->getMFChildren()->begin();
    Node::MFChildrenType::const_iterator childEnd =
            node->getMFChildren()->end  ();
    
    // group geometry children that are mergeable
    for(; childIt != childEnd; ++childIt)
    {
        if((*childIt)->getCore()->getType() != Geometry::getClassType())
            continue;
        
        if(isInExcludeList(*childIt) || isInPreserveList(*childIt))
            continue;
        
        Geometry *geo = dynamic_cast<Geometry *>((*childIt)->getCore());
        Material *mat = geo->getMaterial();
        
        MergeList::iterator mlIt  = ml.begin();
        MergeList::iterator mlEnd = ml.end  ();
        
        bool done = false;
        
        for(; mlIt != mlEnd && !done; ++mlIt)
        {
            Geometry *mlGeo =
                    dynamic_cast<Geometry *>(mlIt->front()->getCore());
            Material *mlMat = mlGeo->getMaterial();
            
            if(compareContainerEqual(mlMat, mat) &&
               mergeableGeo         (mlGeo, geo)   )
            {
                mlIt->push_back(*childIt);
                done = true;
            }
        }
        
        if(!done)
        {
            ml       .push_back(MergeGroup());
            ml.back().push_back(*childIt    );
        }
    }
    
    // merge geometry in the same group and replace obsolete children with
    // new geometry
    MergeList::iterator mlIt  = ml.begin();
    MergeList::iterator mlEnd = ml.end  ();
    
    for(; mlIt != mlEnd; ++mlIt)
    {
        // only one geometry in merge group -> nothing to do
        if(mlIt->size() <= 1)
            continue;
        
        FINFO(("GeometryMergeGraphOp::traverseLeave: Merging [%" PRISize "] "
               "Geometries.\n", mlIt->size()));
        
        GeometryUnrecPtr     geo1;
        GeometryUnrecPtr     geo2;
        NodeUnrecPtr         newNode = Node::create();
        MergeGroup::iterator mgIt    = mlIt->begin();
        MergeGroup::iterator mgEnd   = mlIt->end  ();
        
        geo1 = dynamic_cast<Geometry *>((*mgIt)->getCore());

        // remove the first geo as well
        subStore.push_back(*mgIt);

        ++mgIt;
        
        for(UInt32 i = 0; mgIt != mgEnd; ++mgIt, ++i)
        {
            geo2 = dynamic_cast<Geometry *>((*mgIt)->getCore());
            
            if(i > _mergeThreshold && (mgIt + 1) != mgEnd)
            {
                newNode->setCore(geo1);
                addStore.push_back(newNode);
                
                i       = 0;
                newNode = Node::create();
                geo1    = dynamic_cast<Geometry *>((*mgIt)->getCore());
                ++mgIt;
            }
            
            geo1 = mergeGeo(geo1, geo2);
            geo1->setMaterial(geo2->getMaterial());
            
            subStore.push_back(*mgIt);
        }
        
       newNode->setCore(geo1);
       addStore.push_back(newNode);
    }
    
    // add newly created geometries to current node
    NodeStore::const_iterator storeIt  = subStore.begin();
    NodeStore::const_iterator storeEnd = subStore.end  ();
    
    for(; storeIt != storeEnd; ++storeIt)
       node->subChild(*storeIt);
    
    storeIt  = addStore.begin();
    storeEnd = addStore.end  ();
    
    for(; storeIt != storeEnd; ++storeIt)
       node->addChild(*storeIt);
    
    return Action::Continue;
}
Пример #14
0
void main_main ()
{
    // What time is it now?  We'll use this to compute total run time.
    Real strt_time = ParallelDescriptor::second();

    // AMREX_SPACEDIM: number of dimensions
    int n_cell, max_grid_size;
    Vector<int> bc_lo(AMREX_SPACEDIM,0);
    Vector<int> bc_hi(AMREX_SPACEDIM,0);

    // inputs parameters
    {
        // ParmParse is way of reading inputs from the inputs file
        ParmParse pp;

        // We need to get n_cell from the inputs file - this is the
        // number of cells on each side of a square (or cubic) domain.
        pp.get("n_cell", n_cell);

        // The domain is broken into boxes of size max_grid_size
        max_grid_size = 32;
        pp.query("max_grid_size", max_grid_size);

    }

    Vector<int> is_periodic(AMREX_SPACEDIM,0);
    for (int idim=0; idim < AMREX_SPACEDIM; ++idim) {
      is_periodic[idim] = 1;
    }

    // make BoxArray and Geometry
    BoxArray ba;
    Geometry geom;
    {
        IntVect dom_lo(AMREX_D_DECL(       0,        0,        0));
        IntVect dom_hi(AMREX_D_DECL(n_cell-1, n_cell-1, n_cell-1));
        Box domain(dom_lo, dom_hi);

        // Initialize the boxarray "ba" from the single box "bx"
        ba.define(domain);

        // Break up boxarray "ba" into chunks no larger than
        // "max_grid_size" along a direction
        ba.maxSize(max_grid_size);

        // This defines the physical box, [0, 1] in each direction.
        RealBox real_box({AMREX_D_DECL(0.0, 0.0, 0.0)},
                         {AMREX_D_DECL(1.0, 1.0, 1.0)});

        // This defines a Geometry object
        geom.define(domain, &real_box,
                    CoordSys::cartesian, is_periodic.data());
    }

    // Nghost = number of ghost cells for each array
    int Nghost = 0;

    // do the runtime parameter initializations and microphysics inits
    if (ParallelDescriptor::IOProcessor()) {
      std::cout << "reading extern runtime parameters ..." << std::endl;
    }

    ParmParse ppa("amr");

    std::string probin_file = "probin";

    ppa.query("probin_file", probin_file);

    const int probin_file_length = probin_file.length();
    Vector<int> probin_file_name(probin_file_length);

    for (int i = 0; i < probin_file_length; i++)
      probin_file_name[i] = probin_file[i];

    init_unit_test(probin_file_name.dataPtr(), &probin_file_length);

    // Ncomp = number of components for each array
    int Ncomp = -1;
    init_variables();
    get_ncomp(&Ncomp);

    int name_len = -1;
    get_name_len(&name_len);

    // get the variable names
    Vector<std::string> varnames;

    for (int i=0; i<Ncomp; i++) {
      char* cstring[name_len+1];
      get_var_name(cstring, &i);
      std::string name(*cstring);
      varnames.push_back(name);
    }

    // time = starting time in the simulation
    Real time = 0.0;

    // How Boxes are distrubuted among MPI processes
    DistributionMapping dm(ba);

    // we allocate our main multifabs
    MultiFab state(ba, dm, Ncomp, Nghost);

    // Initialize the state and compute the different thermodynamics
    // by inverting the EOS
    for ( MFIter mfi(state); mfi.isValid(); ++mfi )
    {
        const Box& bx = mfi.validbox();

#pragma gpu
        do_eos(AMREX_INT_ANYD(bx.loVect()), AMREX_INT_ANYD(bx.hiVect()),
               BL_TO_FORTRAN_ANYD(state[mfi]), n_cell);

    }


    std::string name = "test_eos.";

    // get the name of the EOS
    int eos_len = -1;
    get_eos_len(&eos_len);

    char* eos_string[eos_len+1];
    get_eos_name(eos_string);
    std::string eos(*eos_string);

    // Write a plotfile
    WriteSingleLevelPlotfile(name + eos, state, varnames, geom, time, 0);


    // Call the timer again and compute the maximum difference between
    // the start time and stop time over all processors
    Real stop_time = ParallelDescriptor::second() - strt_time;
    const int IOProc = ParallelDescriptor::IOProcessorNumber();
    ParallelDescriptor::ReduceRealMax(stop_time, IOProc);

    // Tell the I/O Processor to write out the "run time"
    amrex::Print() << "Run time = " << stop_time << std::endl;
}
Пример #15
0
Geometry*
GeometryFactory::createArc(const osg::Vec3d& center,
                           const Distance&   radius,
                           const Angle&      start,
                           const Angle&      end,
                           unsigned          numSegments,
                           Geometry*         geomToUse) const
{
    Geometry* geom = geomToUse? geomToUse : new LineString();

    if ( numSegments == 0 )
    {
        // automatically calculate
        double segLen = radius.as(Units::METERS) / 8.0;
        double circumference = 2*osg::PI*radius.as(Units::METERS);
        numSegments = (unsigned)::ceil(circumference / segLen);
    }

    double startRad = std::min( start.as(Units::RADIANS), end.as(Units::RADIANS) );
    double endRad   = std::max( start.as(Units::RADIANS), end.as(Units::RADIANS) );

    if ( endRad == startRad )
        endRad += 2*osg::PI;

    double span     = endRad - startRad;    
    double step     = span/(double)numSegments;

    if ( _srs.valid() && _srs->isGeographic() )
    {
        double earthRadius = _srs->getEllipsoid()->getRadiusEquator();
        double lat = osg::DegreesToRadians(center.y());
        double lon = osg::DegreesToRadians(center.x());
        double rM  = radius.as(Units::METERS);

        for( int i=numSegments-1; i >= 0; --i )
        {
            double angle = startRad + step*(double)i;
            double clat, clon;
            GeoMath::destination( lat, lon, angle, rM, clat, clon, earthRadius );
            geom->push_back( osg::Vec3d(osg::RadiansToDegrees(clon), osg::RadiansToDegrees(clat), center.z()) );
        }
    }

    else
    {
        double rM = radius.as(Units::METERS);

        for( int i=numSegments-1; i >= 0; --i )
        {
            double angle = startRad + step*(double)i;
            double x, y;
            x = center.x() + sin(angle)*rM;
            y = center.y() + cos(angle)*rM;
            geom->push_back( osg::Vec3d(x, y, center.z()) );
        }
    }

    geom->rewind(Geometry::ORIENTATION_CCW);

    return geom;
}
Пример #16
0
void
OSBGeometryElement::postReadV100(void)
{
    OSG_OSB_LOG(("OSBGeometryElement::postReadV100\n"));

    OSBRootElement  *root             = editRoot();
    Geometry        *geo              =
        dynamic_cast<Geometry*>(getContainer());
    UInt32           indexMappingSize = UInt32(_indexMapping.size());

    if(indexMappingSize <= 1)
    {
        OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
                "Converting single index.\n"          ));

        if(_indicesPacked)
        {
            OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
                    "Converting packed indices.\n"        ));
            geo->setIndices(_indices);
        }
        else
        {
            OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
                    "Converting non-packed indices.\n"    ));

            // indices stored in container with id _indicesId
            // create PtrFieldInfo structure to set all entries of field
            // "propIndices" to the container with id _indicesId

            FieldDescriptionBase *indFieldDesc =
                geo->getFieldDescription("propIndices");
            UInt32                indFieldId   = indFieldDesc->getFieldId();

            root->editPtrFieldList().push_back(PtrFieldInfo(geo, indFieldId));
            PtrFieldInfo &indFieldPFI = root->editPtrFieldList().back();

            for(UInt32 i = 0; i < Geometry::MaxAttribs; ++i)
            {
                indFieldPFI.editIdStore().push_back(_indicesId);
            }
        }
    }
    else
    {
        OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
                "Converting multi index.\n"          ));

        OSBGeometryHelper gh;

        if(_indicesPacked)
        {
            OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
                    "Converting packed indices.\n"        ));

            // create 16 bit or 32 bit indices
            if(_indices16Bit)
            {
                GeoUInt16Property *ui16Indices =
                    dynamic_pointer_cast<GeoUInt16Property>(_indices);

                gh.splitMultiIndex<GeoUInt16Property *>(
                    _indexMapping, ui16Indices, geo);
            }
            else
            {
                GeoUInt32Property *ui32Indices =
                    dynamic_pointer_cast<GeoUInt32Property>(_indices);

                gh.splitMultiIndex<GeoUInt32Property *>(
                    _indexMapping, ui32Indices, geo);
            }
        }
        else
        {
            OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
                         "Converting non-packed indices.\n"    ));

            FieldContainerIdMapConstIt mapIt =
                root->getIdMap().find(_indicesId);

            if(mapIt != root->getIdMap().end())
            {
                _indices = dynamic_cast<GeoIntegralProperty *>(
                    FieldContainerFactory::the()->getContainer(mapIt->second));
            }
            else
            {
                FWARNING(("OSBGeometryElement::postReadV100: "
                          "Could not find indices property.\n"));
                return;
            }

            if(_indices->getFormatSize() == sizeof(UInt16))
            {
                GeoUInt16Property *ui16Indices =
                    dynamic_pointer_cast<GeoUInt16Property>(_indices);

                gh.splitMultiIndex<GeoUInt16Property *>(
                    _indexMapping, ui16Indices, geo);
            }
            else if(_indices->getFormatSize() == sizeof(UInt32))
            {
                GeoUInt32Property *ui32Indices =
                    dynamic_pointer_cast<GeoUInt32Property>(_indices);

                gh.splitMultiIndex<GeoUInt32Property *>(
                    _indexMapping, ui32Indices, geo);
            }
        }
    }
}
/***************************************************************
* Function: createFloorplanGeometry()
***************************************************************/
void VirtualScenicHandler::createFloorplanGeometry(const int numPages, 
    CAVEAnimationModeler::ANIMPageEntry **pageEntryArray)
{
    if (numPages <= 0)
    {
        return;
    }

    for (int i = 0; i < numPages; i++)
    {
        // create floorplan geometry
        float length = pageEntryArray[i]->mLength;
        float width = pageEntryArray[i]->mWidth;
        float altitude = pageEntryArray[i]->mAlti;

        Geode *floorplanGeode = new Geode;
        Geometry *floorplanGeometry = new Geometry;

        Vec3Array* vertices = new Vec3Array;
        Vec3Array* normals = new Vec3Array;
        Vec2Array* texcoords = new Vec2Array(4);

        vertices->push_back(Vec3(-length / 2,  width / 2, altitude));	(*texcoords)[0].set(0, 1);
        vertices->push_back(Vec3(-length / 2, -width / 2, altitude));	(*texcoords)[1].set(0, 0);
        vertices->push_back(Vec3( length / 2, -width / 2, altitude));	(*texcoords)[2].set(1, 0);
        vertices->push_back(Vec3( length / 2,  width / 2, altitude));	(*texcoords)[3].set(1, 1);

        for (int k = 0; k < 4; k++) 
        { 
            normals->push_back(Vec3(0, 0, 1));
        }

        DrawElementsUInt* rectangle = new DrawElementsUInt(PrimitiveSet::POLYGON, 0);
        rectangle->push_back(0);	rectangle->push_back(1);
        rectangle->push_back(2);	rectangle->push_back(3);

        floorplanGeometry->addPrimitiveSet(rectangle);
        floorplanGeometry->setVertexArray(vertices);
        floorplanGeometry->setNormalArray(normals);
        floorplanGeometry->setTexCoordArray(0, texcoords);
        floorplanGeometry->setNormalBinding(Geometry::BIND_PER_VERTEX);

        floorplanGeode->addDrawable(floorplanGeometry);
        mFloorplanSwitch->addChild(floorplanGeode);

        /* load floorplan images */
        Material *transmaterial = new Material;
        transmaterial->setDiffuse(Material::FRONT_AND_BACK, Vec4(1, 1, 1, 1));
        transmaterial->setAlpha(Material::FRONT_AND_BACK, 1.0f);

        Image* imgFloorplan = osgDB::readImageFile(pageEntryArray[i]->mTexFilename);

        Texture2D* texFloorplan = new Texture2D(imgFloorplan); 

        StateSet *floorplanStateSet = floorplanGeode->getOrCreateStateSet();
        floorplanStateSet->setTextureAttributeAndModes(0, texFloorplan, StateAttribute::ON);
        floorplanStateSet->setMode(GL_BLEND, StateAttribute::OVERRIDE | StateAttribute::ON );
        floorplanStateSet->setRenderingHint(StateSet::TRANSPARENT_BIN);
        floorplanStateSet->setAttributeAndModes(transmaterial, StateAttribute::OVERRIDE | StateAttribute::ON);
    }
}
Пример #18
0
Geometry* RawncFile::loadFile(const string& fileName)
{
	bool zeroSeen = false, maxSeen = false;
	//QFileInfo fileInfo(fileName);

	//if (!fileInfo.exists()) {
	//	qDebug("File does not exist");
	//	return 0;
	//}
	struct stat fst;
	if (stat(fileName.c_str(), &fst) == -1) {
		printf("File does not exist\n");
		return 0;
	}

	//QString absFilePath = fileInfo.absFilePath();

	//FILE* fp = fopen(absFilePath, "r");
	FILE* fp = fopen(fileName.c_str(), "r");
	if (!fp) {
		//qDebug("Error opening file");
		printf("Error opening file\n");
		return 0;
	}

	// get the number of verts and triangles
	int numverts, numtris;
	if (2!=fscanf(fp, "%d %d", &numverts, &numtris)) {
		//qDebug("Error reading in number of verts and tris");
		printf("Error reading in number of verts and tris\n");
		fclose(fp);
		return 0;
	}
	// make sure the number of verts & tris are positive
	if (numverts<0 || numtris<0) {
		//qDebug("Negative number of verts or tris");
		printf("Negative number of verts or tris\n");
		fclose(fp);
		return 0;
	}

	// initialize the geometry
	Geometry* geometry = new Geometry();
	geometry->AllocateTris(numverts, numtris);
	geometry->AllocateTriVertColors();


	int c;
	// read in the verts
	for (c=0; c<numverts; c++) {
		// read in a single vert, which includes 
		// position and normal
		if (9!=fscanf(fp, "%f %f %f %f %f %f %f %f %f", 
			&(geometry->m_TriVerts[c*3+0]),
			&(geometry->m_TriVerts[c*3+1]),
			&(geometry->m_TriVerts[c*3+2]),
			&(geometry->m_TriVertNormals[c*3+0]),
			&(geometry->m_TriVertNormals[c*3+1]),
			&(geometry->m_TriVertNormals[c*3+2]),
			&(geometry->m_TriVertColors[c*3+0]),
			&(geometry->m_TriVertColors[c*3+1]),
			&(geometry->m_TriVertColors[c*3+2]))) {
			//qDebug("Error reading in vert # %d", c);
			printf("Error reading in vert # %d\n", c);
			delete geometry;
			fclose(fp);
			return 0;
		}
	}
	// read in the triangles
	for (c=0; c<numtris; c++) {
		// read in 3 integers for each triangle
		if (3!=fscanf(fp, "%u %u %u", 
			&(geometry->m_Tris[c*3+0]),
			&(geometry->m_Tris[c*3+1]),
			&(geometry->m_Tris[c*3+2]))) {
			//qDebug("Error reading in tri # %d", c);
			printf("Error reading in tri # %d\n", c);
			delete geometry;
			fclose(fp);
			return 0;
		}
		// the file might start indexing verts from 1 or 0
		// check if indexes go up to the num of verts or if they
		// start from 0
		if (geometry->m_Tris[c*3+0]==0 || geometry->m_Tris[c*3+1]==0 || geometry->m_Tris[c*3+2]==0 ) {
			zeroSeen = true;
		}
		if (geometry->m_Tris[c*3+0]==(unsigned int)numverts || geometry->m_Tris[c*3+1]==(unsigned int)numverts || geometry->m_Tris[c*3+2]==(unsigned int)numverts ) {
			maxSeen = true;
		}
		// cant have both!
		if (maxSeen && zeroSeen) {
			//qDebug("Found 0 & max in tri # %d", c);
			printf("Found 0 & max in tri # %d\n", c);
			delete geometry;
			fclose(fp);
			return 0;
		}

		// check the bounds on each vert
		if (geometry->m_Tris[c*3+0]>(unsigned int)numverts || geometry->m_Tris[c*3+1]>(unsigned int)numverts || geometry->m_Tris[c*3+2]>(unsigned int)numverts ) {
			//qDebug("Bounds error reading in tri # %d", c);
			printf("Bounds error reading in tri # %d\n", c);
			delete geometry;
			fclose(fp);
			return 0;
		}
	}

	// if the file starts from 1, we have to subtract 1 from each vert index
	if (maxSeen) {
		for (c=0; c<numtris; c++) {
			geometry->m_Tris[c*3+0]--;
			geometry->m_Tris[c*3+1]--;
			geometry->m_Tris[c*3+2]--;
		}
	}

	fclose(fp);
	geometry->SetTriNormalsReady();
	return geometry;
}
osg::Geode*
BuildGeometryFilter::processPolygons(FeatureList& features, FilterContext& context)
{
    osg::Geode* geode = new osg::Geode();

    bool makeECEF = false;
    const SpatialReference* featureSRS = 0L;
    const SpatialReference* mapSRS = 0L;

    // set up the reference system info:
    if ( context.isGeoreferenced() )
    {
        makeECEF   = context.getSession()->getMapInfo().isGeocentric();
        featureSRS = context.extent()->getSRS();
        mapSRS     = context.getSession()->getMapInfo().getProfile()->getSRS();
    }

    for( FeatureList::iterator f = features.begin(); f != features.end(); ++f )
    {
        Feature* input = f->get();

        // access the polygon symbol, and bail out if there isn't one
        const PolygonSymbol* poly =
            input->style().isSet() && input->style()->has<PolygonSymbol>() ? input->style()->get<PolygonSymbol>() :
            _style.get<PolygonSymbol>();

        if ( !poly )
            continue;

        // run a symbol script if present.
        if ( poly->script().isSet() )
        {
            StringExpression temp( poly->script().get() );
            input->eval( temp, &context );
        }

        GeometryIterator parts( input->getGeometry(), false );
        while( parts.hasMore() )
        {
            Geometry* part = parts.next();

            part->removeDuplicates();

            // skip geometry that is invalid for a polygon
            if ( part->size() < 3 )
                continue;

            // resolve the color:
            osg::Vec4f primaryColor = poly->fill()->color();
            
            osg::ref_ptr<osg::Geometry> osgGeom = new osg::Geometry();
            //osgGeom->setUseVertexBufferObjects( true );
            //osgGeom->setUseDisplayList( false );

            // are we embedding a feature name?
            if ( _featureNameExpr.isSet() )
            {
                const std::string& name = input->eval( _featureNameExpr.mutable_value(), &context );
                osgGeom->setName( name );
            }


            // compute localizing matrices or use globals
            osg::Matrixd w2l, l2w;
            if (makeECEF)
            {
                osgEarth::GeoExtent featureExtent(featureSRS);
                featureExtent.expandToInclude(part->getBounds());

                computeLocalizers(context, featureExtent, w2l, l2w);
            }
            else
            {
                w2l = _world2local;
                l2w = _local2world;
            }


            // build the geometry:
            tileAndBuildPolygon(part, featureSRS, mapSRS, makeECEF, true, osgGeom, w2l);
            //buildPolygon(part, featureSRS, mapSRS, makeECEF, true, osgGeom, w2l);

            osg::Vec3Array* allPoints = static_cast<osg::Vec3Array*>(osgGeom->getVertexArray());
            if (allPoints && allPoints->size() > 0)
            {
                // subdivide the mesh if necessary to conform to an ECEF globe:
                if ( makeECEF )
                {
                    //convert back to world coords
                    for( osg::Vec3Array::iterator i = allPoints->begin(); i != allPoints->end(); ++i )
                    {
                        osg::Vec3d v(*i);
                        v = v * l2w;
                        v = v * _world2local;

                        (*i)._v[0] = v[0];
                        (*i)._v[1] = v[1];
                        (*i)._v[2] = v[2];
                    }

                    double threshold = osg::DegreesToRadians( *_maxAngle_deg );
                    OE_DEBUG << "Running mesh subdivider with threshold " << *_maxAngle_deg << std::endl;

                    MeshSubdivider ms( _world2local, _local2world );
                    if ( input->geoInterp().isSet() )
                        ms.run( *osgGeom, threshold, *input->geoInterp() );
                    else
                        ms.run( *osgGeom, threshold, *_geoInterp );
                }

                // assign the primary color array. PER_VERTEX required in order to support
                // vertex optimization later
                unsigned count = osgGeom->getVertexArray()->getNumElements();
                osg::Vec4Array* colors = new osg::Vec4Array;
                colors->assign( count, primaryColor );
                osgGeom->setColorArray( colors );
                osgGeom->setColorBinding( osg::Geometry::BIND_PER_VERTEX );

                geode->addDrawable( osgGeom );

                // record the geometry's primitive set(s) in the index:
                if ( context.featureIndex() )
                    context.featureIndex()->tagDrawable( osgGeom, input );
        
                // install clamping attributes if necessary
                if (_style.has<AltitudeSymbol>() &&
                    _style.get<AltitudeSymbol>()->technique() == AltitudeSymbol::TECHNIQUE_GPU)
                {            
                    Clamping::applyDefaultClampingAttrs( osgGeom, input->getDouble("__oe_verticalOffset", 0.0) );
                }
            }
        }
    }
    
    return geode;
}
Пример #20
0
void Terrain::CreatePatchGeometry(TerrainPatch* patch)
{
    URHO3D_PROFILE(CreatePatchGeometry);

    unsigned row = (unsigned)(patchSize_ + 1);
    VertexBuffer* vertexBuffer = patch->GetVertexBuffer();
    Geometry* geometry = patch->GetGeometry();
    Geometry* maxLodGeometry = patch->GetMaxLodGeometry();
    Geometry* occlusionGeometry = patch->GetOcclusionGeometry();

    if (vertexBuffer->GetVertexCount() != row * row)
        vertexBuffer->SetSize(row * row, MASK_POSITION | MASK_NORMAL | MASK_TEXCOORD1 | MASK_TANGENT);

    SharedArrayPtr<unsigned char> cpuVertexData(new unsigned char[row * row * sizeof(Vector3)]);
    SharedArrayPtr<unsigned char> occlusionCpuVertexData(new unsigned char[row * row * sizeof(Vector3)]);

    float* vertexData = (float*)vertexBuffer->Lock(0, vertexBuffer->GetVertexCount());
    float* positionData = (float*)cpuVertexData.Get();
    float* occlusionData = (float*)occlusionCpuVertexData.Get();
    BoundingBox box;

    unsigned occlusionLevel = occlusionLodLevel_;
    if (occlusionLevel > numLodLevels_ - 1)
        occlusionLevel = numLodLevels_ - 1;

    if (vertexData)
    {
        const IntVector2& coords = patch->GetCoordinates();
        int lodExpand = (1 << (occlusionLevel)) - 1;
        int halfLodExpand = (1 << (occlusionLevel)) / 2;

        for (int z = 0; z <= patchSize_; ++z)
        {
            for (int x = 0; x <= patchSize_; ++x)
            {
                int xPos = coords.x_ * patchSize_ + x;
                int zPos = coords.y_ * patchSize_ + z;

                // Position
                Vector3 position((float)x * spacing_.x_, GetRawHeight(xPos, zPos), (float)z * spacing_.z_);
                *vertexData++ = position.x_;
                *vertexData++ = position.y_;
                *vertexData++ = position.z_;
                *positionData++ = position.x_;
                *positionData++ = position.y_;
                *positionData++ = position.z_;

                box.Merge(position);

                // For vertices that are part of the occlusion LOD, calculate the minimum height in the neighborhood
                // to prevent false positive occlusion due to inaccuracy between occlusion LOD & visible LOD
                float minHeight = position.y_;
                if (halfLodExpand > 0 && (x & lodExpand) == 0 && (z & lodExpand) == 0)
                {
                    int minX = Max(xPos - halfLodExpand, 0);
                    int maxX = Min(xPos + halfLodExpand, numVertices_.x_ - 1);
                    int minZ = Max(zPos - halfLodExpand, 0);
                    int maxZ = Min(zPos + halfLodExpand, numVertices_.y_ - 1);
                    for (int nZ = minZ; nZ <= maxZ; ++nZ)
                    {
                        for (int nX = minX; nX <= maxX; ++nX)
                            minHeight = Min(minHeight, GetRawHeight(nX, nZ));
                    }
                }
                *occlusionData++ = position.x_;
                *occlusionData++ = minHeight;
                *occlusionData++ = position.z_;

                // Normal
                Vector3 normal = GetRawNormal(xPos, zPos);
                *vertexData++ = normal.x_;
                *vertexData++ = normal.y_;
                *vertexData++ = normal.z_;

                // Texture coordinate
                Vector2 texCoord((float)xPos / (float)numVertices_.x_, 1.0f - (float)zPos / (float)numVertices_.y_);
                *vertexData++ = texCoord.x_;
                *vertexData++ = texCoord.y_;

                // Tangent
                Vector3 xyz = (Vector3::RIGHT - normal * normal.DotProduct(Vector3::RIGHT)).Normalized();
                *vertexData++ = xyz.x_;
                *vertexData++ = xyz.y_;
                *vertexData++ = xyz.z_;
                *vertexData++ = 1.0f;
            }
        }

        vertexBuffer->Unlock();
        vertexBuffer->ClearDataLost();
    }

    patch->SetBoundingBox(box);

    if (drawRanges_.Size())
    {
        unsigned occlusionDrawRange = occlusionLevel << 4;

        geometry->SetIndexBuffer(indexBuffer_);
        geometry->SetDrawRange(TRIANGLE_LIST, drawRanges_[0].first_, drawRanges_[0].second_, false);
        geometry->SetRawVertexData(cpuVertexData, MASK_POSITION);
        maxLodGeometry->SetIndexBuffer(indexBuffer_);
        maxLodGeometry->SetDrawRange(TRIANGLE_LIST, drawRanges_[0].first_, drawRanges_[0].second_, false);
        maxLodGeometry->SetRawVertexData(cpuVertexData, MASK_POSITION);
        occlusionGeometry->SetIndexBuffer(indexBuffer_);
        occlusionGeometry->SetDrawRange(TRIANGLE_LIST, drawRanges_[occlusionDrawRange].first_, drawRanges_[occlusionDrawRange].second_, false);
        occlusionGeometry->SetRawVertexData(occlusionCpuVertexData, MASK_POSITION);
    }

    patch->ResetLod();
}
osg::Geode*
BuildGeometryFilter::processLines(FeatureList& features, FilterContext& context)
{
    osg::Geode* geode = new osg::Geode();

    bool makeECEF = false;
    const SpatialReference* featureSRS = 0L;
    const SpatialReference* mapSRS = 0L;

    // set up referencing information:
    if ( context.isGeoreferenced() )
    {
        makeECEF   = context.getSession()->getMapInfo().isGeocentric();
        featureSRS = context.extent()->getSRS();
        mapSRS     = context.getSession()->getMapInfo().getProfile()->getSRS();
    }

    for( FeatureList::iterator f = features.begin(); f != features.end(); ++f )
    {
        Feature* input = f->get();

        // extract the required line symbol; bail out if not found.
        const LineSymbol* line = 
            input->style().isSet() && input->style()->has<LineSymbol>() ? input->style()->get<LineSymbol>() :
            _style.get<LineSymbol>();

        if ( !line )
            continue;

        // run a symbol script if present.
        if ( line->script().isSet() )
        {
            StringExpression temp( line->script().get() );
            input->eval( temp, &context );
        }

        GeometryIterator parts( input->getGeometry(), true );
        while( parts.hasMore() )
        {
            Geometry* part = parts.next();

            // skip invalid geometry for lines.
            if ( part->size() < 2 )
                continue;

            // if the underlying geometry is a ring (or a polygon), use a line loop; otherwise
            // use a line strip.
            GLenum primMode = dynamic_cast<Ring*>(part) ? GL_LINE_LOOP : GL_LINE_STRIP;

            // resolve the color:
            osg::Vec4f primaryColor = line->stroke()->color();
            
            osg::ref_ptr<osg::Geometry> osgGeom = new osg::Geometry();
            //osgGeom->setUseVertexBufferObjects( true );
            //osgGeom->setUseDisplayList( false );

            // embed the feature name if requested. Warning: blocks geometry merge optimization!
            if ( _featureNameExpr.isSet() )
            {
                const std::string& name = input->eval( _featureNameExpr.mutable_value(), &context );
                osgGeom->setName( name );
            }

            // build the geometry:
            osg::Vec3Array* allPoints = new osg::Vec3Array();

            transformAndLocalize( part->asVector(), featureSRS, allPoints, mapSRS, _world2local, makeECEF );

            osgGeom->addPrimitiveSet( new osg::DrawArrays(primMode, 0, allPoints->getNumElements()) );
            osgGeom->setVertexArray( allPoints );

            if ( input->style().isSet() )
            {
                //TODO: re-evaluate this. does it hinder geometry merging?
                applyLineSymbology( osgGeom->getOrCreateStateSet(), line );
            }
            
            // subdivide the mesh if necessary to conform to an ECEF globe;
            // but if the tessellation is set to zero, or if the style specifies a
            // tessellation size, skip this step.
            if ( makeECEF && !line->tessellation().isSetTo(0) && !line->tessellationSize().isSet() )
            {
                double threshold = osg::DegreesToRadians( *_maxAngle_deg );
                OE_DEBUG << "Running mesh subdivider with threshold " << *_maxAngle_deg << std::endl;

                MeshSubdivider ms( _world2local, _local2world );
                //ms.setMaxElementsPerEBO( INT_MAX );
                if ( input->geoInterp().isSet() )
                    ms.run( *osgGeom, threshold, *input->geoInterp() );
                else
                    ms.run( *osgGeom, threshold, *_geoInterp );
            }

            // assign the primary color (PER_VERTEX required for later optimization)
            osg::Vec4Array* colors = new osg::Vec4Array;
            colors->assign( osgGeom->getVertexArray()->getNumElements(), primaryColor );
            osgGeom->setColorArray( colors );
            osgGeom->setColorBinding( osg::Geometry::BIND_PER_VERTEX );

            geode->addDrawable( osgGeom );

            // record the geometry's primitive set(s) in the index:
            if ( context.featureIndex() )
                context.featureIndex()->tagDrawable( osgGeom, input );
        
            // install clamping attributes if necessary
            if (_style.has<AltitudeSymbol>() &&
                _style.get<AltitudeSymbol>()->technique() == AltitudeSymbol::TECHNIQUE_GPU)
            {
                Clamping::applyDefaultClampingAttrs( osgGeom, input->getDouble("__oe_verticalOffset", 0.0) );
            }
        }
    }
    
    return geode;
}
Пример #22
0
void writeSpatialSBML() {
  
/*
  // SBMLNamespaces of SBML Level 3 Version 1 with Spatial Version 1
  SBMLNamespaces sbmlns(3,1,"spatial",1);
  // SpatialPkgNamespaces spatialns(3,1,1);

  // add Required Elements package namespace
  sbmlns.addPkgNamespace("req", 1);
*/

  // SBMLNamespaces of SBML Level 3 Version 1 with 'req' Version 1
  // then add 'spatial' package namespace.
  RequiredElementsPkgNamespaces sbmlns(3,1,1);
  sbmlns.addPkgNamespace("spatial",1);

  // create the L3V1 document with spatial package
  SBMLDocument document(&sbmlns);	


  // set 'required' attribute on document for 'spatial' and 'req' packages to 'T'??
  SBMLDocumentPlugin* dplugin;
  dplugin = static_cast<SBMLDocumentPlugin*>(document.getPlugin("spatial"));
  dplugin->setRequired(true);
  dplugin = static_cast<SBMLDocumentPlugin*>(document.getPlugin("req"));
  dplugin->setRequired(true);

  // create the Model 
  Model *model = document.createModel();
  model-> setId("trial_spatial");
  model-> setName("trial_spatial");

  // create the Compartments
  Compartment* compartment = model->createCompartment();
  compartment->setId("cytosol");
  compartment->setConstant(true);

  // create the Species
  Species* species1 = model->createSpecies();
  species1->setId("ATPc");
  species1->setCompartment("cytosol");
  species1->setInitialConcentration(1.0);
  species1->setHasOnlySubstanceUnits(false);
  species1->setBoundaryCondition(false);
  species1->setConstant(false);
  // spatial package extension to species.
  // required elements package extention to parameter
  RequiredElementsSBasePlugin* reqplugin;
  reqplugin = static_cast<RequiredElementsSBasePlugin*>(species1->getPlugin("req"));
  reqplugin->setMathOverridden("spatial");
  reqplugin->setCoreHasAlternateMath(true);
  SpatialSpeciesRxnPlugin* srplugin;
  srplugin = static_cast<SpatialSpeciesRxnPlugin*>(species1->getPlugin("spatial"));
  srplugin->setIsSpatial(true);

  // add parameter for diff coeff of species1
  Parameter* paramSp = model->createParameter();
  paramSp->setId(species1->getId()+"_dc");
  paramSp->setValue(1.0);
  // required elements package extention to parameter
  reqplugin = static_cast<RequiredElementsSBasePlugin*>(paramSp->getPlugin("req"));
  reqplugin->setMathOverridden("spatial");
  reqplugin->setCoreHasAlternateMath(true);
  // spatial package extension to parameter.
  SpatialParameterPlugin* pplugin;
  pplugin = static_cast<SpatialParameterPlugin*>(paramSp->getPlugin("spatial"));
  DiffusionCoefficient* diffCoeff = pplugin->getDiffusionCoefficient();
  diffCoeff->setVariable(species1->getId());
  diffCoeff->setCoordinateIndex(0);
  // add parameter for adv coeff of species1
  paramSp = model->createParameter();
  paramSp->setId(species1->getId()+"_ac");
  paramSp->setValue(1.5);
  // required elements package extention to parameter
  reqplugin = static_cast<RequiredElementsSBasePlugin*>(paramSp->getPlugin("req"));
  reqplugin->setMathOverridden("spatial");
  reqplugin->setCoreHasAlternateMath(true);
  // spatial package extension to parameter.
  pplugin = static_cast<SpatialParameterPlugin*>(paramSp->getPlugin("spatial"));
  AdvectionCoefficient* advCoeff = pplugin->getAdvectionCoefficient();
  advCoeff->setVariable(species1->getId());
  advCoeff->setCoordinateIndex(0);
  // add parameter for boundary condition of species1
  paramSp = model->createParameter();
  paramSp->setId(species1->getId()+"_bc");
  paramSp->setValue(2.0);
  // required elements package extention to parameter
  reqplugin = static_cast<RequiredElementsSBasePlugin*>(paramSp->getPlugin("req"));
  reqplugin->setMathOverridden("spatial");
  reqplugin->setCoreHasAlternateMath(true);
  // spatial package extension to parameter.
  pplugin = static_cast<SpatialParameterPlugin*>(paramSp->getPlugin("spatial"));
  BoundaryCondition* boundCon = pplugin->getBoundaryCondition();
  boundCon->setVariable(species1->getId());
  boundCon->setType("value");
  boundCon->setCoordinateBoundary("Xmin");

  Species* species2 = model->createSpecies();
  species2->setId("ADPc");
  species2->setCompartment("cytosol");
  species2->setInitialConcentration(1);
  species2->setHasOnlySubstanceUnits(false);
  species2->setBoundaryCondition(false);
  species2->setConstant(false);
  srplugin = static_cast<SpatialSpeciesRxnPlugin*>(species2->getPlugin("spatial"));
  srplugin->setIsSpatial(true);

/*  // create a parameter
  Parameter* param = model->createParameter();
  param->setId("k_1");
  param->setValue(0.24);
  param->setConstant(true);

  // create an assignment rule
  AssignmentRule* assignRule = model->createAssignmentRule();
  assignRule->setVariable(species1->getId());
  assignRule->setFormula("species2+k_1");
*/
  /*
  reqplugin = static_cast<RequiredElementsSBasePlugin*>(assignRule->getPlugin("req"));
  reqplugin->setMathOverridden("spatial");
  reqplugin->setCoreHasAlternateMath(false);
  */

  Reaction* reaction = model->createReaction();
  reaction->setId("rxn1");
  reaction->setReversible(false);
  reaction->setFast(false);
  reaction->setCompartment("cytosol");
  srplugin = static_cast<SpatialSpeciesRxnPlugin*>(reaction->getPlugin("spatial"));
  srplugin->setIsLocal(true);

  //
  // Get a SpatialModelPlugin object plugged in the model object.
  //
  // The type of the returned value of SBase::getPlugin() function is 
  // SBasePlugin*, and thus the value needs to be casted for the 
  // corresponding derived class.
  //
  SpatialModelPlugin* mplugin;
  mplugin = static_cast<SpatialModelPlugin*>(model->getPlugin("spatial"));

  //
  // Creates a geometry object via SpatialModelPlugin object.
  //
  Geometry* geometry = mplugin->getGeometry();
  geometry->setCoordinateSystem("XYZ");

  CoordinateComponent* coordX = geometry->createCoordinateComponent();
  coordX->setSpatialId("coordComp1");
  coordX->setComponentType("cartesian");
  coordX->setSbmlUnit("umeter");
  coordX->setIndex(1);
  BoundaryMin* minX = coordX->createBoundaryMin();
  minX->setSpatialId("Xmin");
  minX->setValue(0.0);
  BoundaryMax* maxX = coordX->createBoundaryMax();
  maxX->setSpatialId("Xmax");
  maxX->setValue(10.0);

  Parameter* paramX = model->createParameter();
  paramX->setId("x");
  paramX->setValue(8.0);
  // required elements package extention to parameter
  // RequiredElementsSBasePlugin* reqplugin;
  reqplugin = static_cast<RequiredElementsSBasePlugin*>(paramX->getPlugin("req"));
  reqplugin->setMathOverridden("spatial");
  reqplugin->setCoreHasAlternateMath(true);
  // spatial package extension to parameter.
  // SpatialParameterPlugin* pplugin;
  pplugin = static_cast<SpatialParameterPlugin*>(paramX->getPlugin("spatial"));
  SpatialSymbolReference* spSymRef = pplugin->getSpatialSymbolReference();
  spSymRef->setSpatialId(coordX->getSpatialId());
  spSymRef->setType(coordX->getElementName());

  DomainType* domainType = geometry->createDomainType();
  domainType->setSpatialId("dtype1");
  domainType->setSpatialDimensions(3);

  // Spatial package extension to compartment (mapping compartment with domainType)
  // required elements package extention to compartment
  reqplugin = static_cast<RequiredElementsSBasePlugin*>(compartment->getPlugin("req"));
  reqplugin->setMathOverridden("spatial");
  reqplugin->setCoreHasAlternateMath(true);
  SpatialCompartmentPlugin* cplugin;
  cplugin = static_cast<SpatialCompartmentPlugin*>(compartment->getPlugin("spatial"));
  CompartmentMapping* compMapping = cplugin->getCompartmentMapping();
  compMapping->setSpatialId("compMap1");
  compMapping->setCompartment(compartment->getId());
  compMapping->setDomainType(domainType->getSpatialId());
  compMapping->setUnitSize(1.0);
  
  Domain* domain = geometry->createDomain();
  domain->setSpatialId("domain1");
  domain->setDomainType("dtype1");
  domain->setImplicit(false);
  domain->setShapeId("circle");
  InteriorPoint* internalPt1 = domain->createInteriorPoint();
  internalPt1->setCoord1(1.0);

  domain = geometry->createDomain();
  domain->setSpatialId("domain2");
  domain->setDomainType("dtype1");
  domain->setImplicit(false);
  domain->setShapeId("square");
  InteriorPoint* internalPt2 = domain->createInteriorPoint();
  internalPt2->setCoord1(5.0);

  AdjacentDomains* adjDomain = geometry->createAdjacentDomains();
  adjDomain->setSpatialId("adjDomain1");
  adjDomain->setDomain1("domain1");
  adjDomain->setDomain2("domain2");

  AnalyticGeometry* analyticGeom = geometry->createAnalyticGeometry();
  analyticGeom->setSpatialId("analyticGeom1");
  AnalyticVolume* analyticVol = analyticGeom->createAnalyticVolume();
  analyticVol->setSpatialId("analyticVol1");
  analyticVol->setDomainType(domainType->getSpatialId());
  analyticVol->setFunctionType("squareFn");
  analyticVol->setOrdinal(1);
  const char* mathMLStr = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><apply xmlns=\"\"><plus /><apply><times /><ci>x</ci><ci>x</ci></apply><apply><minus /><cn>1.0</cn></apply></apply></math>";
  ASTNode* mathNode = readMathMLFromString(mathMLStr);
  analyticVol->setMath(mathNode);

  SampledFieldGeometry* sfg = geometry->createSampledFieldGeometry();
  sfg->setSpatialId("sampledFieldGeom1");
  SampledField* sampledField = sfg->createSampledField();
  sampledField->setSpatialId("sampledField1");
  sampledField->setNumSamples1(4);
  sampledField->setNumSamples2(4);
  sampledField->setNumSamples3(2);
  sampledField->setDataType("double");
  sampledField->setInterpolationType("linear");
  sampledField->setEncoding("encoding1");
  //int samples[5] = {1, 2, 3, 4, 5};
  int samples[32] = {
	                 // z=0
	                 0,0,0,0,
	                 0,1,1,0,
					 0,1,1,0,
					 0,0,0,0,
					 // z=1
					 0,0,0,0,
					 0,1,1,0,
					 0,1,1,0,
					 0,0,0,0
  };
  ImageData* id = sampledField->createImageData();
  id->setDataType("compressed");
  id->setSamples(samples, 32);
  SampledVolume* sampledVol = sfg->createSampledVolume();
  sampledVol->setSpatialId("sv_1");
  sampledVol->setDomainType(domainType->getSpatialId());
  sampledVol->setSampledValue(128.0);
  sampledVol->setMinValue(0.0);
  sampledVol->setMaxValue(255.0);
  
  ParametricGeometry* pg = geometry->createParametricGeometry();
  pg->setSpatialId("parametricGeom1");
  ParametricObject* paramObj = pg->createParametricObject();
  paramObj->setSpatialId("po_1");
  paramObj->setDomain(domain->getSpatialId());
  paramObj->setPolygonType("hexagon");
  int ptIndices[5] = {1, 2, 3, 4, 5};
  PolygonObject* po = paramObj->createPolygonObject();
  po->setPointIndices(ptIndices, 5);
  SpatialPoint* spPt = pg->createSpatialPoint();
  spPt->setSpatialId("sp_1");
  spPt->setDomain(domain->getSpatialId());
  spPt->setCoord1(1);
  spPt->setCoord2(2);
  spPt->setCoord3(3);

  CSGeometry* csg = geometry->createCSGeometry();
  csg->setSpatialId("csGeom1");
  CSGObject* csgObj = csg->createCSGObject();
  csgObj->setSpatialId("csg_csgo_1");
  csgObj->setDomainType(domainType->getSpatialId());
  csgObj->setOrdinal(1);
  CSGScale* scale = csgObj->createCSGScale();
  scale->setScaleX(2.0);
  scale->setScaleY(3.0);
  scale->setScaleZ(4.0);
  CSGPrimitive* prim1 = scale->createCSGPrimitive();
  prim1->setPrimitiveType("SOLID_SPHERE");

  csgObj = csg->createCSGObject();
  csgObj->setSpatialId("csg_csgo_2");
  csgObj->setDomainType(domainType->getSpatialId());
  CSGSetOperator* setUnion = csgObj->createCSGSetOperator();
  setUnion->setOperationType("UNION");
/*  CSGPrimitive* prim = setUnion->createCSGPrimitive();
  prim->setPrimitiveType("SOLID_SPHERE");
  CSGPrimitive* prim2 = setUnion->createCSGPrimitive();
  prim2->setPrimitiveType("SOLID_CONE");
*/
  CSGPrimitive* prim2 = new CSGPrimitive(3,1,1);
  prim2->setSpatialId("cone0");
  prim2->setPrimitiveType("SOLID_CONE");
  CSGTranslation* translatedCone = new CSGTranslation(3,1,1);
  translatedCone->setSpatialId("translation0");
  translatedCone->setTranslateX(2.0);
  translatedCone->setTranslateY(2.0);
  translatedCone->setTranslateZ(2.0);
  translatedCone->setChild(prim2);
  int n = setUnion->addCSGNodeChild(translatedCone);
  CSGPrimitive* prim3 = new CSGPrimitive(3,1,1);
  prim3->setSpatialId("sphere0");
  prim3->setPrimitiveType("SOLID_SPHERE");
  n = setUnion->addCSGNodeChild(prim3);

  writeSBML(&document, "spatial_example0.xml");

}
// builds and tessellates a polygon (with or without holes)
void
BuildGeometryFilter::buildPolygon(Geometry*               ring,
                                  const SpatialReference* featureSRS,
                                  const SpatialReference* mapSRS,
                                  bool                    makeECEF,
                                  bool                    tessellate,
                                  osg::Geometry*          osgGeom,
                                  const osg::Matrixd      &world2local)
{
    if ( !ring->isValid() )
        return;

    ring->rewind(osgEarth::Symbology::Geometry::ORIENTATION_CCW);

    osg::ref_ptr<osg::Vec3Array> allPoints = new osg::Vec3Array();
    transformAndLocalize( ring->asVector(), featureSRS, allPoints.get(), mapSRS, world2local, makeECEF );

    Polygon* poly = dynamic_cast<Polygon*>(ring);
    if ( poly )
    {
        RingCollection ordered(poly->getHoles().begin(), poly->getHoles().end());
        std::sort(ordered.begin(), ordered.end(), holeCompare);

        for( RingCollection::const_iterator h = ordered.begin(); h != ordered.end(); ++h )
        {
            Geometry* hole = h->get();
            if ( hole->isValid() )
            {
                hole->rewind(osgEarth::Symbology::Geometry::ORIENTATION_CW);

                osg::ref_ptr<osg::Vec3Array> holePoints = new osg::Vec3Array();
                transformAndLocalize( hole->asVector(), featureSRS, holePoints.get(), mapSRS, world2local, makeECEF );

                // find the point with the highest x value
                unsigned int hCursor = 0;
                for (unsigned int i=1; i < holePoints->size(); i++)
                {
                    if ((*holePoints)[i].x() > (*holePoints)[hCursor].x())
                      hCursor = i;
                }

                double x1 = (*holePoints)[hCursor].x();
                double y1 = (*holePoints)[hCursor].y();
                double y2 = (*holePoints)[hCursor].y();

                unsigned int edgeCursor = UINT_MAX;
                double edgeDistance = DBL_MAX;
                unsigned int foundPointCursor = UINT_MAX;
                for (unsigned int i=0; i < allPoints->size(); i++)
                {
                    unsigned int next = i == allPoints->size() - 1 ? 0 : i + 1;
                    double xMax = osg::maximum((*allPoints)[i].x(), (*allPoints)[next].x());

                    if (xMax > (*holePoints)[hCursor].x())
                    {
                        double x2 = xMax + 1.0;
                        double x3 = (*allPoints)[i].x();
                        double y3 = (*allPoints)[i].y();
                        double x4 = (*allPoints)[next].x();
                        double y4 = (*allPoints)[next].y();

                        double xi=0.0, yi=0.0;
                        bool intersects = false;
                        unsigned int hitPointCursor = UINT_MAX;
                        if (y1 == y3 && x3 > x1)
                        {
                            xi = x3;
                            hitPointCursor = i;
                            intersects = true;
                        }
                        else if (y1 == y4 && x4 > x1)
                        {
                            xi = x4;
                            hitPointCursor = next;
                            intersects = true;
                        }
                        else if (segmentsIntersect(x1, y1, x2, y2, x3, y3, x4, y4, xi, yi))
                        {
                            intersects = true;
                        }

                        double dist = (osg::Vec2d(xi, yi) - osg::Vec2d(x1, y1)).length();
                        if (intersects && dist < edgeDistance)
                        {
                            foundPointCursor = hitPointCursor;
                            edgeCursor = hitPointCursor != UINT_MAX ? hitPointCursor : (x3 >= x4 ? i : next);
                            edgeDistance = dist;
                        }
                    }
                }

                if (foundPointCursor == UINT_MAX && edgeCursor != UINT_MAX)
                {
                    // test for intersecting edges between x1 and x2
                    // (skipping the two segments for which edgeCursor is a vert)

                    double x2 = (*allPoints)[edgeCursor].x();
                    y2 = (*allPoints)[edgeCursor].y();

                    bool foundIntersection = false;
                    for (unsigned int i=0; i < allPoints->size(); i++)
                    {
                        unsigned int next = i == allPoints->size() - 1 ? 0 : i + 1;

                        if (i == edgeCursor || next == edgeCursor)
                          continue;

                        double x3 = (*allPoints)[i].x();
                        double y3 = (*allPoints)[i].y();
                        double x4 = (*allPoints)[next].x();
                        double y4 = (*allPoints)[next].y();

                        foundIntersection = foundIntersection || segmentsIntersect(x1, y1, x2, y2, x3, y3, x4, y4);

                        if (foundIntersection)
                        {
                            unsigned int prev = i == 0 ? allPoints->size() - 1 : i - 1;

                            if (!isCCW((*allPoints)[prev].x(), (*allPoints)[prev].y(), x3, y3, x4, y4))
                            {
                                edgeCursor = i;
                                x2 = (*allPoints)[edgeCursor].x();
                                y2 = (*allPoints)[edgeCursor].y();
                                foundIntersection = false;
                            }
                        }

                    }
                }

                if (edgeCursor != UINT_MAX)
                {
                    // build array of correctly ordered new points to add to the outer loop
                    osg::ref_ptr<osg::Vec3Array> insertPoints = new osg::Vec3Array();
                    insertPoints->reserve(holePoints->size() + 2);

                    unsigned int p = hCursor;
                    do
                    {
                        insertPoints->push_back((*holePoints)[p]);
                        p = p == holePoints->size() - 1 ? 0 : p + 1;
                    } while(p != hCursor);

                    insertPoints->push_back((*holePoints)[hCursor]);
                    insertPoints->push_back((*allPoints)[edgeCursor]);
                    
                    // insert new points into outer loop
                    osg::Vec3Array::iterator it = edgeCursor == allPoints->size() - 1 ? allPoints->end() : allPoints->begin() + (edgeCursor + 1);
                    allPoints->insert(it, insertPoints->begin(), insertPoints->end());
                }
            }
        }
    }
    
    GLenum mode = GL_LINE_LOOP;
    if ( osgGeom->getVertexArray() == 0L )
    {
        osgGeom->addPrimitiveSet( new osg::DrawArrays( mode, 0, allPoints->size() ) );
        osgGeom->setVertexArray( allPoints.get() );
    }
    else
    {
        osg::Vec3Array* v = static_cast<osg::Vec3Array*>(osgGeom->getVertexArray());
        osgGeom->addPrimitiveSet( new osg::DrawArrays( mode, v->size(), allPoints->size() ) );
        //v->reserve(v->size() + allPoints->size());
        std::copy(allPoints->begin(), allPoints->end(), std::back_inserter(*v));
    }

    //// Normal computation.
    //// Not completely correct, but better than no normals at all. TODO: update this
    //// to generate a proper normal vector in ECEF mode.
    ////
    //// We cannot accurately rely on triangles from the tessellation, since we could have
    //// very "degraded" triangles (close to a line), and the normal computation would be bad.
    //// In this case, we would have to average the normal vector over each triangle of the polygon.
    //// The Newell's formula is simpler and more direct here.
    //osg::Vec3 normal( 0.0, 0.0, 0.0 );
    //for ( size_t i = 0; i < poly->size(); ++i )
    //{
    //    osg::Vec3 pi = (*poly)[i];
    //    osg::Vec3 pj = (*poly)[ (i+1) % poly->size() ];
    //    normal[0] += ( pi[1] - pj[1] ) * ( pi[2] + pj[2] );
    //    normal[1] += ( pi[2] - pj[2] ) * ( pi[0] + pj[0] );
    //    normal[2] += ( pi[0] - pj[0] ) * ( pi[1] + pj[1] );
    //}
    //normal.normalize();

    //osg::Vec3Array* normals = new osg::Vec3Array();
    //normals->push_back( normal );
    //osgGeom->setNormalArray( normals );
    //osgGeom->setNormalBinding( osg::Geometry::BIND_OVERALL );
}
Пример #24
0
void minkowskiSumCollection( const Geometry& gA, const Polygon_2& gB, Polygon_set_2& polygonSet )
{
    for ( size_t i = 0; i < gA.numGeometries(); i++ ) {
        minkowskiSum( gA.geometryN( i ), gB, polygonSet );
    }
}
Пример #25
0
    void assemble_HM(const Geometry& geo, SymMatrix& mat, const unsigned gauss_order) 
    {
        mat = SymMatrix((geo.size()-geo.outermost_interface().nb_triangles()));
        mat.set(0.0);
        double K = 1.0 / (4.0 * M_PI);

        // We iterate over the meshes (or pair of domains) to fill the lower half of the HeadMat (since its symmetry)
        for ( Geometry::const_iterator mit1 = geo.begin(); mit1 != geo.end(); ++mit1) {

            for ( Geometry::const_iterator mit2 = geo.begin(); (mit2 != (mit1+1)); ++mit2) {

                // if mit1 and mit2 communicate, i.e they are used for the definition of a common domain
                const int orientation = geo.oriented(*mit1, *mit2); // equals  0, if they don't have any domains in common
                                                                       // equals  1, if they are both oriented toward the same domain
                                                                       // equals -1, if they are not

                if ( orientation != 0 ) {

                    double Scoeff =   orientation * geo.sigma_inv(*mit1, *mit2) * K;
                    double Dcoeff = - orientation * geo.indicator(*mit1, *mit2) * K;
                    double Ncoeff;

                    if ( !(mit1->outermost() || mit2->outermost()) ) {
                        // Computing S block first because it's needed for the corresponding N block
                        operatorS(*mit1, *mit2, mat, Scoeff, gauss_order);
                        Ncoeff = geo.sigma(*mit1, *mit2)/geo.sigma_inv(*mit1, *mit2);
                    } else {
                        Ncoeff = orientation * geo.sigma(*mit1, *mit2) * K;
                    }

                    if ( !mit1->outermost() ) {
                        // Computing D block
                        operatorD(*mit1, *mit2, mat, Dcoeff, gauss_order);
                    }
                    if ( ( *mit1 != *mit2 ) && ( !mit2->outermost() ) ) {
                        // Computing D* block
                        operatorD(*mit1, *mit2, mat, Dcoeff, gauss_order, true);
                    }

                    // Computing N block
                    operatorN(*mit1, *mit2, mat, Ncoeff, gauss_order);
                }
            }
        }

        // Deflate the diagonal block (N33) of 'mat' : (in order to have a zero-mean potential for the outermost interface)
        const Interface i = geo.outermost_interface();
        unsigned i_first = (*i.begin()->mesh().vertex_begin())->index();
        deflat(mat, i, mat(i_first, i_first) / (geo.outermost_interface().nb_vertices()));
    }
Пример #26
0
bool
FeatureTileSource::queryAndRenderFeaturesForStyle(const Style&     style,
                                                  const Query&     query,
                                                  osg::Referenced* data,
                                                  const GeoExtent& imageExtent,
                                                  osg::Image*      out_image)
{   
    // first we need the overall extent of the layer:
    const GeoExtent& featuresExtent = getFeatureSource()->getFeatureProfile()->getExtent();
    
    // convert them both to WGS84, intersect the extents, and convert back.
    GeoExtent featuresExtentWGS84 = featuresExtent.transform( featuresExtent.getSRS()->getGeographicSRS() );
    GeoExtent imageExtentWGS84 = imageExtent.transform( featuresExtent.getSRS()->getGeographicSRS() );
    GeoExtent queryExtentWGS84 = featuresExtentWGS84.intersectionSameSRS( imageExtentWGS84 );
    if ( queryExtentWGS84.isValid() )
    {
        GeoExtent queryExtent = queryExtentWGS84.transform( featuresExtent.getSRS() );

        // incorporate the image extent into the feature query for this style:
        Query localQuery = query;
        localQuery.bounds() = 
            query.bounds().isSet() ? query.bounds()->unionWith( queryExtent.bounds() ) :
            queryExtent.bounds();

        // query the feature source:
        osg::ref_ptr<FeatureCursor> cursor = _features->createFeatureCursor( localQuery );

        // now copy the resulting feature set into a list, converting the data
        // types along the way if a geometry override is in place:
        FeatureList cellFeatures;
        while( cursor.valid() && cursor->hasMore() )
        {
            Feature* feature = cursor->nextFeature();
            Geometry* geom = feature->getGeometry();
            if ( geom )
            {
                // apply a type override if requested:
                if (_options.geometryTypeOverride().isSet() &&
                    _options.geometryTypeOverride() != geom->getComponentType() )
                {
                    geom = geom->cloneAs( _options.geometryTypeOverride().value() );
                    if ( geom )
                        feature->setGeometry( geom );
                }
            }
            if ( geom )
            {
                cellFeatures.push_back( feature );
            }
        }

        //OE_NOTICE
        //    << "Rendering "
        //    << cellFeatures.size()
        //    << " features in ("
        //    << queryExtent.toString() << ")"
        //    << std::endl;

        return renderFeaturesForStyle( style, cellFeatures, data, imageExtent, out_image );
    }
    else
    {
        return false;
    }
}
Пример #27
0
Texture* RayIntersector::Intersection::getTextureLookUp(Vec3& tc) const
{
    Geometry* geometry = drawable.valid() ? drawable->asGeometry() : 0;
    Vec3Array* vertices = geometry ? dynamic_cast<Vec3Array*>(geometry->getVertexArray()) : 0;

    if (vertices)
    {
        if (indexList.size()==3 && ratioList.size()==3)
        {
            unsigned int i1 = indexList[0];
            unsigned int i2 = indexList[1];
            unsigned int i3 = indexList[2];

            float r1 = ratioList[0];
            float r2 = ratioList[1];
            float r3 = ratioList[2];

            Array* texcoords = (geometry->getNumTexCoordArrays()>0) ? geometry->getTexCoordArray(0) : 0;
            FloatArray* texcoords_FloatArray = dynamic_cast<FloatArray*>(texcoords);
            Vec2Array* texcoords_Vec2Array = dynamic_cast<Vec2Array*>(texcoords);
            Vec3Array* texcoords_Vec3Array = dynamic_cast<Vec3Array*>(texcoords);
            if (texcoords_FloatArray)
            {
                // we have tex coord array so now we can compute the final tex coord at the point of intersection.
                float tc1 = (*texcoords_FloatArray)[i1];
                float tc2 = (*texcoords_FloatArray)[i2];
                float tc3 = (*texcoords_FloatArray)[i3];
                tc.x() = tc1*r1 + tc2*r2 + tc3*r3;
            }
            else if (texcoords_Vec2Array)
            {
                // we have tex coord array so now we can compute the final tex coord at the point of intersection.
                const Vec2& tc1 = (*texcoords_Vec2Array)[i1];
                const Vec2& tc2 = (*texcoords_Vec2Array)[i2];
                const Vec2& tc3 = (*texcoords_Vec2Array)[i3];
                tc.x() = tc1.x()*r1 + tc2.x()*r2 + tc3.x()*r3;
                tc.y() = tc1.y()*r1 + tc2.y()*r2 + tc3.y()*r3;
            }
            else if (texcoords_Vec3Array)
            {
                // we have tex coord array so now we can compute the final tex coord at the point of intersection.
                const Vec3& tc1 = (*texcoords_Vec3Array)[i1];
                const Vec3& tc2 = (*texcoords_Vec3Array)[i2];
                const Vec3& tc3 = (*texcoords_Vec3Array)[i3];
                tc.x() = tc1.x()*r1 + tc2.x()*r2 + tc3.x()*r3;
                tc.y() = tc1.y()*r1 + tc2.y()*r2 + tc3.y()*r3;
                tc.z() = tc1.z()*r1 + tc2.z()*r2 + tc3.z()*r3;
            }
            else
            {
                return 0;
            }
        }

        const TexMat* activeTexMat = 0;
        const Texture* activeTexture = 0;

        if (drawable->getStateSet())
        {
            const TexMat* texMat = dynamic_cast<TexMat*>(drawable->getStateSet()->getTextureAttribute(0,StateAttribute::TEXMAT));
            if (texMat) activeTexMat = texMat;

            const Texture* texture = dynamic_cast<Texture*>(drawable->getStateSet()->getTextureAttribute(0,StateAttribute::TEXTURE));
            if (texture) activeTexture = texture;
        }

        for(NodePath::const_reverse_iterator itr = nodePath.rbegin();
            itr != nodePath.rend() && (!activeTexMat || !activeTexture);
            ++itr)
            {
                const Node* node = *itr;
                if (node->getStateSet())
                {
                    if (!activeTexMat)
                    {
                        const TexMat* texMat = dynamic_cast<const TexMat*>(node->getStateSet()->getTextureAttribute(0,StateAttribute::TEXMAT));
                        if (texMat) activeTexMat = texMat;
                    }

                    if (!activeTexture)
                    {
                        const Texture* texture = dynamic_cast<const Texture*>(node->getStateSet()->getTextureAttribute(0,StateAttribute::TEXTURE));
                        if (texture) activeTexture = texture;
                    }
                }
            }

            if (activeTexMat)
            {
                Vec4 tc_transformed = Vec4(tc.x(), tc.y(), tc.z() ,0.0f) * activeTexMat->getMatrix();
                tc.x() = tc_transformed.x();
                tc.y() = tc_transformed.y();
                tc.z() = tc_transformed.z();

                if (activeTexture && activeTexMat->getScaleByTextureRectangleSize())
                {
                    tc.x() *= static_cast<float>(activeTexture->getTextureWidth());
                    tc.y() *= static_cast<float>(activeTexture->getTextureHeight());
                    tc.z() *= static_cast<float>(activeTexture->getTextureDepth());
                }
            }

            return const_cast<Texture*>(activeTexture);

    }
    return 0;
}
Пример #28
0
Geometry*
GeometryFactory::createEllipse(const osg::Vec3d& center,
                               const Distance&   radiusMajor,
                               const Distance&   radiusMinor,
                               const Angle&      rotationAngle,
                               unsigned          numSegments,
                               Geometry*         geomToUse) const
{
    Geometry* geom = geomToUse ? geomToUse : new Polygon();

    if ( numSegments == 0 )
    {
        // automatically calculate
        double ravgM = 0.5*(radiusMajor.as(Units::METERS) + radiusMinor.as(Units::METERS));
        double segLen = ravgM / 8.0;
        double circumference = 2*osg::PI*ravgM;
        numSegments = (unsigned)::ceil(circumference / segLen);
    }
    
    double segAngle = 2.0*osg::PI/(double)numSegments;

    if ( _srs.valid() && _srs->isGeographic() )
    {
        double earthRadius = _srs->getEllipsoid()->getRadiusEquator();
        double lat = osg::DegreesToRadians(center.y());
        double lon = osg::DegreesToRadians(center.x());
        double a = radiusMajor.as(Units::METERS);
        double b = radiusMinor.as(Units::METERS);
        double g = rotationAngle.as(Units::RADIANS) - osg::PI_2;

        for( unsigned i=0; i<numSegments; ++i )
        {
            double angle = segAngle * (double)i;
            double t = angle - osg::PI_2;
            double clat, clon;

            double rA = (b*b-a*a)*cos(2*t - 2*g) + a*a + b*b;
            double q = sqrt(2.0)*a*b*sqrt(rA);
            double r = q/rA;

            GeoMath::destination( lat, lon, angle, r, clat, clon, earthRadius );
            geom->push_back( osg::Vec3d(osg::RadiansToDegrees(clon), osg::RadiansToDegrees(clat), center.z()) );
        }
    }
    else
    {
        double a = radiusMajor.as(Units::METERS);
        double b = radiusMinor.as(Units::METERS);
        double g = rotationAngle.as(Units::RADIANS) - osg::PI_2;
        double sing = sin(g), cosg = cos(g);

        for( unsigned i=0; i<numSegments; ++i )
        {
            double angle = segAngle * (double)i;
            double t = angle - osg::PI_2;
            double cost = cos(t), sint = sin(t);
            double x = center.x() + a*cost*cosg - b*sint*sing;
            double y = center.y() + a*cost*sing + b*sint*cosg;

            geom->push_back( osg::Vec3d(x, y, center.z()) );
        }
    }

    return geom;
}
Пример #29
0
osg::Node*
PolygonizeLinesFilter::push(FeatureList& input, FilterContext& cx)
{
    // compute the coordinate localization matrices.
    computeLocalizers( cx );

    // establish some things
    bool                    makeECEF   = false;
    const SpatialReference* featureSRS = 0L;
    const SpatialReference* mapSRS     = 0L;

    if ( cx.isGeoreferenced() )
    {
        makeECEF   = cx.getSession()->getMapInfo().isGeocentric();
        featureSRS = cx.extent()->getSRS();
        mapSRS     = cx.getSession()->getMapInfo().getProfile()->getSRS();
    }

    // The operator we'll use to make lines into polygons.
    const LineSymbol* line = _style.get<LineSymbol>();
    PolygonizeLinesOperator polygonize( line ? (*line->stroke()) : Stroke() );

    // Geode to hold all the geometries.
    osg::Geode* geode = new osg::Geode();

    // iterate over all features.
    for( FeatureList::iterator i = input.begin(); i != input.end(); ++i )
    {
        Feature* f = i->get();

        // iterate over all the feature's geometry parts. We will treat
        // them as lines strings.
        GeometryIterator parts( f->getGeometry(), false );
        while( parts.hasMore() )
        {
            Geometry* part = parts.next();

            // skip empty geometry
            if ( part->size() == 0 )
                continue;

            // transform the geometry into the target SRS and localize it about 
            // a local reference point.
            osg::Vec3Array* verts   = new osg::Vec3Array();
            osg::Vec3Array* normals = new osg::Vec3Array();
            transformAndLocalize( part->asVector(), featureSRS, verts, normals, mapSRS, _world2local, makeECEF );

            // turn the lines into polygons.
            osg::Geometry* geom = polygonize( verts, normals );
            geode->addDrawable( geom );

            // record the geometry's primitive set(s) in the index:
            if ( cx.featureIndex() )
                cx.featureIndex()->tagPrimitiveSets( geom, f );
        }
    }

    // attempt to combine geometries for better performance
    MeshConsolidator::run( *geode );

    // GPU performance optimization:
    VertexCacheOptimizer vco;
    geode->accept( vco );

    // If we're auto-scaling, we need a shader
    float minPixels = line ? line->stroke()->minPixels().getOrUse( 0.0f ) : 0.0f;
    if ( minPixels > 0.0f )
    {
        osg::StateSet* stateSet = geode->getOrCreateStateSet();

        VirtualProgram* vp = VirtualProgram::getOrCreate(stateSet);
        vp->setName( "osgEarth::PolygonizeLines" );

        const char* vs =
            "#version " GLSL_VERSION_STR "\n"
            GLSL_DEFAULT_PRECISION_FLOAT "\n"
            "attribute vec3   oe_polyline_center; \n"
            "uniform   float  oe_polyline_scale;  \n"
            "uniform   float  oe_polyline_min_pixels; \n"
            "uniform   mat3   oe_WindowScaleMatrix; \n"

            "void oe_polyline_scalelines(inout vec4 VertexMODEL) \n"
            "{ \n"
            "   if ( oe_polyline_scale != 1.0 || oe_polyline_min_pixels > 0.0 ) \n"
            "   { \n"
            "       vec4  center_model = vec4(oe_polyline_center*VertexMODEL.w, VertexMODEL.w); \n"
            "       vec4  vector_model = VertexMODEL - center_model; \n"
            "       if ( length(vector_model.xyz) > 0.0 ) \n"
            "       { \n"
            "           float scale = oe_polyline_scale; \n"

            "           vec4 vertex_clip = gl_ModelViewProjectionMatrix * VertexMODEL; \n"
            "           vec4 center_clip = gl_ModelViewProjectionMatrix * center_model; \n"
            "           vec4 vector_clip = vertex_clip - center_clip; \n"

            "           if ( oe_polyline_min_pixels > 0.0 ) \n"
            "           { \n"
            "               vec3 vector_win = oe_WindowScaleMatrix * (vertex_clip.xyz/vertex_clip.w - center_clip.xyz/center_clip.w); \n"
            "               float min_scale = max( (0.5*oe_polyline_min_pixels)/length(vector_win.xy), 1.0 ); \n"
            "               scale = max( scale, min_scale ); \n"
            "           } \n"

            "           VertexMODEL = center_model + vector_model*scale; \n"
            "        } \n"
            "    } \n"
            "} \n";

        vp->setFunction( "oe_polyline_scalelines", vs, ShaderComp::LOCATION_VERTEX_MODEL );
        vp->addBindAttribLocation( "oe_polyline_center", osg::Drawable::ATTRIBUTE_6 );

        // add the default scaling uniform.
        // good way to test:
        //    osgearth_viewer earthfile --uniform oe_polyline_scale 1.0 10.0
        osg::Uniform* scaleU = new osg::Uniform(osg::Uniform::FLOAT, "oe_polyline_scale");
        scaleU->set( 1.0f );
        stateSet->addUniform( scaleU, 1 );

        // the default "min pixels" uniform.
        osg::Uniform* minPixelsU = new osg::Uniform(osg::Uniform::FLOAT, "oe_polyline_min_pixels");
        minPixelsU->set( minPixels );
        stateSet->addUniform( minPixelsU, 1 );
    }

    return delocalize( geode );
}
Пример #30
0
void
MovementSolute::divide_top_incomming (const Geometry& geo, 
                                      const SoilWater& soil_water, 
                                      const double J_above, // [g/cm^2/h]
                                      std::map<size_t, double>& J_primary,
                                      std::map<size_t, double>& J_secondary,
                                      std::map<size_t, double>& J_tertiary)
{
  daisy_assert (J_above < 0.0); // Negative upward flux.
  const std::vector<size_t>& edge_above 
    = geo.cell_edges (Geometry::cell_above);
  const size_t edge_above_size = edge_above.size ();
  double total_water_in = 0.0;  // [cm^3 W/h]
  double total_area = 0.0;      // [cm^2 S]

  // Find incomming water in all domain.
  for (size_t i = 0; i < edge_above_size; i++)
    {
      const size_t edge = edge_above[i];
      const int cell = geo.edge_other (edge, Geometry::cell_above);
      daisy_assert (geo.cell_is_internal (cell));
      const double area = geo.edge_area (edge); // [cm^2 S]
      total_area += area;
      const double in_sign 
        = geo.cell_is_internal (geo.edge_to (edge)) 
        ? 1.0
        : -1.0;
      daisy_assert (in_sign < 0);

      // Tertiary domain.
      const double q_tertiary = soil_water.q_tertiary (edge);
      daisy_assert (std::isfinite (q_tertiary));
      const double tertiary_in = q_tertiary * in_sign; // [cm^3 W/cm^2 S/h]
      if (tertiary_in > 0)
        {
          total_water_in += tertiary_in * area;
          J_tertiary[edge] = q_tertiary; // [cm^3 W/cm^2 S/h]
        }
      else
        J_tertiary[edge] = 0.0;

      // Secondary domain.
      const double q_secondary = soil_water.q_secondary (edge);
      const double secondary_in = q_secondary * in_sign; // [cm^3 W/cm^2 S/h]
      if (secondary_in > 0)
        {
          total_water_in += secondary_in * area;
          J_secondary[edge] = q_secondary; // [cm^3 W/cm^2 S/h]
          
        }
      else
        J_secondary[edge] = 0.0;

      // Primary domain.
      const double q_primary = soil_water.q_primary (edge);
      const double primary_in = q_primary * in_sign; // [cm^3 W/cm^2 S/h]
      if (primary_in > 0)
        {
          total_water_in += primary_in * area;
          J_primary[edge] = q_primary; // [cm^3 W/cm^2 S/h]
        }
      else
        J_primary[edge] = 0.0;
    }
  daisy_approximate (total_area, geo.surface_area ());

  if (total_water_in > 1e-9 * total_area)
    // Scale with incomming solute.
    {
      // [g/cm^3 W] = [g/cm^2 S/h] * [cm^2 S] / [cm^3 W/h] 
      const double C_above = -J_above * total_area / total_water_in;
      daisy_assert (std::isfinite (C_above));
      for (size_t i = 0; i < edge_above_size; i++)
        {
          const size_t edge = edge_above[i];
          // [g/cm^2 S/h] = [cm^3 W/cm^2 S/h] * [g/cm^3 W]
          J_tertiary[edge] *= C_above;
          J_secondary[edge] *= C_above;
          J_primary[edge] *= C_above;
        }
    }
  else
    {
      daisy_assert (total_water_in >= 0.0);
      for (size_t i = 0; i < edge_above_size; i++)
        {
          const size_t edge = edge_above[i];
          const double in_sign 
            = geo.cell_is_internal (geo.edge_to (edge)) ? 1.0 : -1.0;
          J_tertiary[edge] = 0.0;
          J_secondary[edge] = 0.0;
          J_primary[edge] = -J_above * in_sign;
        }
    }
}