⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ebsrectangulartessellator.java

📁 world wind java sdk 源码
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
			for (EdgeBoundedSector sij : si)			{				// We further subdivide the tiles in the polar regions one more time. We derive				// no benefit at the poles until we do that.  This will make the initial polar tiles				// much smaller (roughly 1/2 x 1/2), but to compensate, we will make the size of				// the actual triangles comparable by halving the triangle resolution in these two				// polar regions.				int[] result = analyzeEdgeBoundedSector(sij);				if ((result == null) || !forceExtraInitialSubdivisionInPolarRegion)					// lateral sector - add as is					tops.add(this.createTile(dc, sij, 0, this.density));				else // polar region sector. Force one more initial subdivision				{					EdgeBoundedSector[] sijSubDiv = (EdgeBoundedSector[])sij.subdivide();					for (EdgeBoundedSector sijSubDiv_k : sijSubDiv)						// note we halve the density here to compensate for the smaller polar sectors						tops.add(this.createTile(dc, sijSubDiv_k, 0, this.density/2));				}			}		}		return tops;    }    private RectTile createTile(DrawContext dc, EdgeBoundedSector tileSector, int level, int triangleDensity)    {        Cylinder cylinder = dc.getGlobe().computeBoundingCylinder(dc.getVerticalExaggeration(), tileSector);        double cellSize = tileSector.getDeltaLatRadians() * dc.getGlobe().getRadius() / triangleDensity;        return new RectTile(this, cylinder, level, triangleDensity, tileSector, cellSize);    }	public static double getLatitudeCutoffInDegrees() { return latitudeCutoffInDegrees; }	public static void setLatitudeCutoffInDegrees(double d)	{		if (d < 0.0) d = -d;		if ( (d >= 5.0) && (d <= 85.0) )			latitudeCutoffInDegrees = d;	}    public boolean isMakeTileSkirts()    {        return makeTileSkirts;    }    public void setMakeTileSkirts(boolean makeTileSkirts)    {        this.makeTileSkirts = makeTileSkirts;    }    private void selectVisibleTiles(DrawContext dc, RectTile tile)    {        Extent extent = tile.getExtent();        if (extent != null && !extent.intersects(this.currentFrustum))            return;        if (this.currentLevel < this.maxLevel - 1 && this.needToSplit(dc, tile))        {            ++this.currentLevel;            RectTile[] subtiles = this.split(dc, tile);            for (RectTile child : subtiles)            {                this.selectVisibleTiles(dc, child);            }            --this.currentLevel;            return;        }        this.currentCoverage = tile.getSector().union(this.currentCoverage);        this.currentTiles.add(tile);    }    private boolean needToSplit(DrawContext dc, RectTile tile)    {        Vec4[] corners = tile.sector.computeCornerPoints(dc.getGlobe(), dc.getVerticalExaggeration());        Vec4 centerPoint = tile.sector.computeCenterPoint(dc.getGlobe(), dc.getVerticalExaggeration());        View view = dc.getView();        double d1 = view.getEyePoint().distanceTo3(corners[0]);        double d2 = view.getEyePoint().distanceTo3(corners[1]);        double d3 = view.getEyePoint().distanceTo3(corners[2]);        double d4 = view.getEyePoint().distanceTo3(corners[3]);        double d5 = view.getEyePoint().distanceTo3(centerPoint);        double minDistance = d1;        if (d2 < minDistance)            minDistance = d2;        if (d3 < minDistance)            minDistance = d3;        if (d4 < minDistance)            minDistance = d4;        if (d5 < minDistance)            minDistance = d5;        double logDist = Math.log10(minDistance);        boolean useTile = tile.log10CellSize <= (logDist - DEFAULT_LOG10_RESOLUTION_TARGET);        return !useTile;    }    private RectTile[] split(DrawContext dc, RectTile tile)    {        EdgeBoundedSector[] sectors = (EdgeBoundedSector[])tile.sector.subdivide();        RectTile[] subTiles = new RectTile[4];        subTiles[0] = this.createTile(dc, sectors[0], tile.level + 1, tile.density);        subTiles[1] = this.createTile(dc, sectors[1], tile.level + 1, tile.density);        subTiles[2] = this.createTile(dc, sectors[2], tile.level + 1, tile.density);        subTiles[3] = this.createTile(dc, sectors[3], tile.level + 1, tile.density);        return subTiles;    }    private EBSRectangularTessellator.CacheKey createCacheKey(DrawContext dc, RectTile tile)    {        return new CacheKey(dc, tile.sector, tile.density);    }    private void makeVerts(DrawContext dc, RectTile tile)    {        // First see if the vertices have been previously computed and are in the cache. Since the elevation model        // can change between frames, regenerate and re-cache vertices every second.        MemoryCache cache = WorldWind.getMemoryCache(CACHE_ID);        CacheKey cacheKey = this.createCacheKey(dc, tile);        tile.ri = (RenderInfo) cache.getObject(cacheKey);        if (tile.ri != null && tile.ri.time >= System.currentTimeMillis() - 1000) // Regenerate cache after one second            return;        tile.ri = this.buildVerts(dc, tile, this.makeTileSkirts);        if (tile.ri != null)        {            cacheKey = this.createCacheKey(dc, tile);            cache.add(cacheKey, tile.ri, tile.ri.getSizeInBytes());        }    }	private int[] analyzeEdgeBoundedSector(EdgeBoundedSector s)	{		// This routine is critical to the functioning of sector vertex generation, hence we		// document much of the overall process here.		/* There are nine different types of edge-bounded sectors that can arise. These are		   characterized by the types of edges that appear and their ordering around the sector.		   Using a notation that starts with the first latitude encountered in a CCW traversal		   (or the first longitude, if there are no latitudes involved, or finally the first		   Great Ellipse edge otherwise), we can list the nine options as shown below. The first		   (LatLonLatLon) appears on the lateral sides of the globe between the +/- latitude		   limit lines; all the others appear only in latitudes above (below) the latitude limit		   corresponding to the top (bottom) four vertices of the cube (i.e., appear only in the		   polar regions).		LatLonLatLon: A lateral sector which can be handled in the conventional way.		LatLatLonLon: Only appears at the coarsest subdivision level. There will be exactly 4 around each pole.		LatGEGELon:   Appears immediately adjacent to one of the original 8 cube vertices (mirror image of next)		LatLonGEGE:   Appears immediately adjacent to one of the original 8 cube vertices (mirror image of previous)		LatLatGEGE:   Appears immediately adjacent to a midpoint of one of the original 8 cube vertices. ("Remnant"		              of LatLatLonLon at subsequent levels of subdivision.)		LonLonGEGE:   Appears immediately adjacent to the north (south) pole.		LatGEGEGE:    Appears along the edges of quadrants in the two polar regions.		LonGEGEGE:    Appears along the edges of quadrants in the two polar regions.		GEGEGEGE:     Appears in the interior of quadrants in the two polar regions.		The first (LatLonLatLon) case can be handled exactly as in the original RectangularTessellator.buildVerts.		For the other 8 cases, we generate vertices along transverse arcs between pairs of "rail edges". Outside of		this routine, it is not relevant which of the 8 cases we are dealing with. Detecting the eight cases is		only necessary here in order to determine (i) which pair of edges are used as the "rails", and (ii) to		determine the nature of the transverse arc. Relevant details:		(i) rail edges: The higher level code assumes vertices are generated in rows with increasing longitude		across a row and with latitudes increasing from row to row. Hence we return the rail edge indices		ordered "min longitude" to "max longitude" (quotes because an edge does not, in general, have constant		latitude or longitude), and successive rows with "increasing latitude" are generated as the "rail_t"		parameter used in buildVertsBetweenRailEdges varies from 0 to 1.		(ii) transverse arc: Ideally, transverse vertices would always be generated along great ellipse arcs.		However, the tessellation must smoothly meet the top latitude limit line corresponding to the top four		and bottom four cube vertices. This line is a curve of constant latitude, not a great ellipse. This is		only relevant for edge-bounded sectors that have at least one edge which is a line of constant latitude.		METHOD RETURN VALUE:			(*) null if the edge bounded sector is LatLonLatLon (i.e., a transverse sector away from the polar region)		-OR-			(*) an array of length three: the first two positions hold the edge indices specifying			    rail edge 1 and rail edge 2, respectively, ordered as indicated above.  The third position				holds the number of constant latitude edges.		*/		// We start by counting the number of edges of each type and remembering		// where the first two (if any) of each type are:		int nGE = 0,            // there will be 0, 2, 3, or 4 (can't be just 1)		    nLat = 0, nLon = 0; // there will be 0, 1, or 2 (can't be more than 2)		int firstGE = -1, firstLat = -1, firstLon = -1;		int secondGE = -1, secondLon = -1;		for (int i=0 ; i<4 ; i++)		{			Edge.EdgeType et = s.getEdge(i).getEdgeType();			if (et == Edge.EdgeType.ConstantLatitude)			{				if (++nLat == 1) firstLat = i;			}			else if (et == Edge.EdgeType.ConstantLongitude)			{				if (++nLon == 1) firstLon = i;				else secondLon = i;			}			else			{				if (++nGE == 1) firstGE = i;				else if (nGE == 2) secondGE = i;			}		}		// Next we determine which of the nine cases we have so that we can identify		// the two rail edges. (We will order them at the end.)		int[] edgeIndices = new int[3];		edgeIndices[2] = nLat;		if ((nLat == 2) && (nLon == 2))		{			// if the first latitude is both preceded and followed by a longitude edge,			// then the sector is a lateral one:			int n = (firstLat + 1) % 4;			if ((n == firstLon) || (n == secondLon))			{				n = firstLat - 1;				if (n < 0) n = 3;				if ((n == firstLon) || (n == secondLon))				{					/* FOR RAIL EDGE TEXTURE COORDINATE LOGGING:					curSectorPW=sectorPW[0]; */					// lateral sector:					return null;				}			}			// must be LatLatLonLon			/* FOR RAIL EDGE TEXTURE COORDINATE LOGGING:			curSectorPW=sectorPW[1]; */			edgeIndices[0] = firstLon; edgeIndices[1] = secondLon;		}		// There are at least two GE edges. (It is impossible to have a sector with 1 GE edge.)		else if (nLon == 1)		{			// either LatGEGELon, LatLonGEGE, or LonGEGEGE: go from longitude to opposite GE			/* FOR RAIL EDGE TEXTURE COORDINATE LOGGING:			if((firstLat+1)%4==firstLon) curSectorPW=sectorPW[3];			else if (nLat>0) curSectorPW=sectorPW[2]; else curSectorPW=sectorPW[7]; */			edgeIndices[0] = firstLon; edgeIndices[1] = (firstLon+2) % 4;		}		else if (nLat == 2) // LatLatGEGE: go between GEs:		{			/* FOR RAIL EDGE TEXTURE COORDINATE LOGGING:			curSectorPW=sectorPW[4]; */			edgeIndices[0] = firstGE; edgeIndices[1] = secondGE;		}		else if (nLat == 1) // LatGEGEGE; use preceding and following GEs:		{			/* FOR RAIL EDGE TEXTURE COORDINATE LOGGING:			curSectorPW=sectorPW[6]; */			if (firstLat == 0) edgeIndices[0] = 3; else edgeIndices[0] = firstLat - 1;			edgeIndices[1] = (firstLat + 1) % 4;		}		else if (nLon == 2) // LonLonGEGE: go from min Lon to opposite GE		{			/* FOR RAIL EDGE TEXTURE COORDINATE LOGGING:			curSectorPW=sectorPW[5]; */			if (s.getEdge(firstLon).maxLongitudeDegrees() > s.getEdge(secondLon).maxLongitudeDegrees())				edgeIndices[0] = secondLon;			else				edgeIndices[0] = firstLon;			edgeIndices[1] = (edgeIndices[0] + 2) % 4;		}		else // must be GEGEGEGE: go from arbitrary GE to opposite GE:		{			/* FOR RAIL EDGE TEXTURE COORDINATE LOGGING:			curSectorPW=sectorPW[8]; */			edgeIndices[0] = firstGE; edgeIndices[1] = (firstGE+2) % 4;		}		// finally, order the two rail edges before returning them		boolean northPolarRegion = (s.getEdge(0).getStartPoint().getLatitude().getDegrees() > 0.0);		if (northPolarRegion)		{			if (s.getEdge(edgeIndices[0]).maxLongitudeDegrees() >				s.getEdge(edgeIndices[1]).maxLongitudeDegrees())			{				int t = edgeIndices[0]; edgeIndices[0] = edgeIndices[1]; edgeIndices[1] = t;			}		}		else		{			if (s.getEdge(edgeIndices[0]).maxLongitudeDegrees() <				s.getEdge(edgeIndices[1]).maxLongitudeDegrees())			{				int t = edgeIndices[0]; edgeIndices[0] = edgeIndices[1]; edgeIndices[1] = t;			}		}		return edgeIndices;	}    public RenderInfo buildVerts(DrawContext dc, RectTile tile, boolean makeSkirts)    {		int[] oppEdges = analyzeEdgeBoundedSector(tile.getSector()); 		if (oppEdges == null)			// lateral sector; build vertices in standard way			return buildVertsOnLateralTile(dc,tile,makeSkirts);		return buildVertsBetweenRailEdges(dc,tile,makeSkirts,oppEdges);    }    private RenderInfo buildVertsBetweenRailEdges(DrawContext dc, RectTile tile, boolean makeSkirts,		int[] railEdges)    // Build vertices along GreatEllipseEdges between railEdges[0] and railEdges[1]    {        int density = tile.density;        int numVertices = (density + 3) * (density + 3);        DoubleBuffer verts = BufferUtil.newDoubleBuffer(numVertices * 3);        DoubleBuffer texCoords = BufferUtil.newDoubleBuffer(numVertices * 2);		double nominal_delta_t = 1.0 / density;        ArrayList<LatLon> latlons = this.computeLocationsBetweenRailEdges(tile,railEdges,nominal_delta_t,texCoords);        /* FOR RAIL EDGE TEXTURE COORDINATE LOGGING:		curSectorPW.print("density = " + tile.density + "; level = " + tile.level + "\n"); */        double[] elevations = new double[latlons.size()];        dc.getGlobe().getElevations(tile.sector, latlons,tile.getResolution(), elevations);        int iv = 0;        double verticalExaggeration = dc.getVerticalExaggeration();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -