osgEarth 2.1.1
|
00001 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph 00002 * Copyright 2010 Pelican Ventures, Inc. 00003 * http://osgearth.org 00004 * 00005 * osgEarth is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU Lesser General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public License 00016 * along with this program. If not, see <http://www.gnu.org/licenses/> 00017 */ 00018 00019 #include "GeoPatch" 00020 00021 #include <algorithm> 00022 00023 #include "Geographic" 00024 #include "Euler" 00025 #include "PatchSet" 00026 00027 namespace seamless 00028 { 00029 using namespace osg; 00030 using namespace osgEarth; 00031 00032 GeoPatch::GeoPatch() 00033 { 00034 _face = -1; 00035 std::fill(&_edgeLengths[0], &_edgeLengths[4], 0.0); 00036 00037 } 00038 00039 GeoPatch::GeoPatch(const TileKey& key) 00040 { 00041 // When an arc on the cube grid is subdivided, this is the largest 00042 // ratio of the lengths of the parent arc and its longest 00043 // child. The ratio goes to .5 as the arcs are further subdivided 00044 // at higher LODs. The error threshold is set to this value to 00045 // insure that the triles that share an edge will display the same 00046 // LOD when the enclosing patches are from different LODs. 00047 setErrorThreshold(.5371); 00048 const GeoExtent& extent = key.getExtent(); 00049 double xMin = extent.xMin(), yMin = extent.yMin(), 00050 xMax = extent.xMax(), yMax = extent.yMax(); 00051 euler::cubeToFace(xMin, yMin, xMax, yMax, _face); 00052 Vec2d faceCoords[4]; 00053 _faceCoords[0][0] = xMin; _faceCoords[0][1] = yMin; 00054 _faceCoords[1][0] = xMax; _faceCoords[1][1] = yMin; 00055 _faceCoords[2][0] = xMax; _faceCoords[2][1] = yMax; 00056 _faceCoords[3][0] = xMin; _faceCoords[3][1] = yMax; 00057 for (int i = 0; i < 4; ++i) 00058 _edgeLengths[i] = euler::arcLength(_faceCoords[i], 00059 _faceCoords[(i + 1) % 4], _face); 00060 } 00061 00062 GeoPatch::GeoPatch(const GeoPatch& rhs, const CopyOp& copyop) 00063 : Patch(rhs, copyop), _face(rhs._face) 00064 { 00065 std::copy(&rhs._edgeLengths[0], &rhs._edgeLengths[4], &_edgeLengths[0]); 00066 std::copy(&rhs._faceCoords[0], &rhs._faceCoords[4], &_faceCoords[0]); 00067 } 00068 00069 float GeoPatch::getEdgeError(const osg::Vec3& eye, int edge) 00070 { 00071 // Hack to get back to face parameters and world coordinates. 00072 Transform* parent = static_cast<Transform*>(getParent(0)); 00073 PatchGroup* pgroup = static_cast<PatchGroup*>(parent->getParent(0)); 00074 Matrix worldMat; 00075 parent->computeLocalToWorldMatrix(worldMat, 0); 00076 Vec3d worldEye = Vec3d(eye) * worldMat; 00077 double d = euler::distanceToSegment(worldEye, _faceCoords[edge], 00078 _faceCoords[(edge + 1) % 4], _face); 00079 return _patchSet->getPrecisionFactor() * _edgeLengths[edge] / d; 00080 } 00081 00082 void GeoPatch::setGeographic(Geographic* geo) 00083 { 00084 _patchSet = geo; 00085 } 00086 00087 Geographic* GeoPatch::getGeographic() const 00088 { 00089 return static_cast<Geographic*>(_patchSet.get()); 00090 } 00091 }