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; } } }
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; }
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; }
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; }
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; }
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(); }
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 ); }
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; } }
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; }
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; }
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; }
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; }
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); } }
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; }
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; }
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 ); }
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 ); } }
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())); }
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; } }
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; }
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; }
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 ); }
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; } } }