/* * Copyright 2012 Hannes Janetzek * * This program is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU Lesser General License for more details. * * You should have received a copy of the GNU Lesser General License along with * this program. If not, see . */ /* ported from Polymaps: Layer.js Copyright (c) 2010, SimpleGeo and Stamen Design */ package org.oscim.view.renderer; import org.oscim.view.renderer.MapRenderer.TilesData; import android.util.FloatMath; public class ScanBox { interface Callback { void call(MapTile tile); } class SetVisible implements Callback { @Override public void call(MapTile tile) { tile.isVisible = true; } } static class Edge { float x0, y0, x1, y1, dx, dy; void set(float x0, float y0, float x1, float y1) { if (y0 <= y1) { this.x0 = x0; this.y0 = y0; this.x1 = x1; this.y1 = y1; this.dx = x1 - x0; this.dy = y1 - y0; } else { this.x0 = x1; this.y0 = y1; this.x1 = x0; this.y1 = y0; this.dx = x0 - x1; this.dy = y0 - y1; } } } static Edge ab = new Edge(); static Edge bc = new Edge(); static Edge ca = new Edge(); static void scanSpans(Edge e0, Edge e1) { // sort edge by x-coordinate if (e0.x0 == e1.x0 && e0.y0 == e1.y0) { if (e0.x0 + e1.dy / e0.dy * e0.dx < e1.x1) { Edge t = e0; e0 = e1; e1 = t; } } else { if (e0.x1 - e1.dy / e0.dy * e0.dx < e1.x0) { Edge t = e0; e0 = e1; e1 = t; } } float m0 = e0.dx / e0.dy; float m1 = e1.dx / e1.dy; int d0 = e0.dx > 0 ? 1 : 0;// use y + 1 to compute x0 int d1 = e1.dx < 0 ? 1 : 0; // use y + 1 to compute x1 float x0, x1; int y = (int) Math.max(0, FloatMath.floor(e1.y0)); int bottom = (int) Math.min(mMax, FloatMath.ceil(e1.y1)); for (; y < bottom; y++) { // float x0 = (m0 * Math.min(e0.dy, y + d0 - e0.y0) + e0.x0); // float x1 = (m1 * Math.min(e1.dy, y + d1 - e1.y0) + e1.x0); x0 = y + d0 - e0.y0; if (e0.dy < x0) x0 = e0.dy; x0 = e0.x0 + m0 * x0; if (x0 < 0) x0 = 0; else x0 = FloatMath.ceil(x0); x1 = y + d1 - e1.y0; if (e1.dy < x1) x1 = e1.dy; x1 = e1.x0 + m1 * x1; if (x1 < 0) x1 = 0; else x1 = FloatMath.floor(x1); setVisible(y, (int) x1, (int) x0); // setVisible(y, (int) (x1 - 0.5f), (int) (x0 + 0.5f)); } } static void scanTriangle() { if (ab.dy > bc.dy) { Edge t = ab; ab = bc; bc = t; } if (ab.dy > ca.dy) { Edge t = ab; ab = ca; ca = t; } if (bc.dy > ca.dy) { Edge t = bc; bc = ca; ca = t; } if (ab.dy != 0) scanSpans(ca, ab); if (bc.dy != 0) scanSpans(ca, bc); } private static int mMax; public static void scan(float[] coords, TilesData tiles, int max) { sTiles = tiles; cntDoubles = 0; mMax = max; ab.set(coords[0], coords[1], coords[2], coords[3]); bc.set(coords[2], coords[3], coords[4], coords[5]); ca.set(coords[4], coords[5], coords[0], coords[1]); scanTriangle(); ab.set(coords[4], coords[5], coords[6], coords[7]); bc.set(coords[6], coords[7], coords[0], coords[1]); ca.set(coords[0], coords[1], coords[4], coords[5]); scanTriangle(); // Log.d("..", "= x1 && tiles[i].tileX < x2) { // if (tiles[i].isVisible) { // Log.d("..", ">>>" + y + " " + tiles[i].tileX); // cntDoubles++; // } tiles[i].isVisible = true; } } } } }