limit maximum scanlines to bbox

This commit is contained in:
Hannes Janetzek 2013-03-01 22:53:01 +01:00
parent e53179eb7b
commit b82cfbb95e

View File

@ -15,9 +15,11 @@
package org.oscim.renderer;
import android.util.FloatMath;
public abstract class ScanBox {
/*
* ported from Polymaps: Layer.js
*/
static class Edge {
float x0, y0, x1, y1, dx, dy;
@ -42,12 +44,28 @@ public abstract class ScanBox {
private Edge ab = new Edge();
private Edge bc = new Edge();
private Edge ca = new Edge();
private float minX, maxX;
protected byte mZoom;
abstract void setVisible(int y, int x1, int x2);
public void scan(float[] coords, byte zoom) {
mZoom = zoom;
maxX = Float.MIN_VALUE;
minX = Float.MAX_VALUE;
for(int i = 0; i < 8; i += 2){
float x = coords[i];
if (x > maxX)
maxX = x;
if (x < minX)
minX = x;
}
maxX = (float)Math.ceil(maxX);
minX = (float)Math.floor(minX);
// top-left -> top-right
ab.set(coords[0], coords[1], coords[2], coords[3]);
// top-right -> bottom-right
@ -100,8 +118,8 @@ public abstract class ScanBox {
private void scanSpans(Edge e0, Edge e1) {
// scan the y-range of the edge with less dy
int y0 = (int) Math.max(0, FloatMath.floor(e1.y0));
int y1 = (int) Math.min((1 << mZoom), FloatMath.ceil(e1.y1));
int y0 = (int) Math.max(0, Math.floor(e1.y0));
int y1 = (int) Math.min((1 << mZoom), Math.ceil(e1.y1));
// sort edge by x-coordinate
if (e0.x0 == e1.x0 && e0.y0 == e1.y0) {
@ -123,19 +141,6 @@ public abstract class ScanBox {
float m0 = e0.dx / e0.dy;
float m1 = e1.dx / e1.dy;
// FIXME, something is wrong here, with a steep angle
// 'fill' can shoot far over the area in one direction
int maxSlope = 8;
if (m0 > maxSlope)
m0 = maxSlope;
else if (m0 < -maxSlope)
m0 = -maxSlope;
if (m1 > maxSlope)
m1 = maxSlope;
else if (m1 < -maxSlope)
m1 = -maxSlope;
// e0 goes to the right, e1 to the left
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
@ -147,75 +152,22 @@ public abstract class ScanBox {
if (dy > e0.dy)
dy = e0.dy;
float x0 = FloatMath.ceil(e0.x0 + m0 * dy);
float x0 = (float)Math.ceil(e0.x0 + m0 * dy);
dy = d1 + y - e1.y0;
if (dy > e1.dy)
dy = e1.dy;
float x1 = FloatMath.floor(e1.x0 + m1 * dy);
float x1 = (float)Math.floor(e1.x0 + m1 * dy);
if (x1 < minX)
x1 = minX;
if (x0 > maxX)
x0 = maxX;
if (x1 < x0)
setVisible(y, (int) x1, (int) x0);
}
}
/*
* ported from Polymaps: Layer.js Copyright (c) 2010, SimpleGeo and Stamen
* Design
*/
// // scan-line conversion
// function edge(a, b) {
// if (a.row > b.row) { var t = a; a = b; b = t; }
// return {
// x0: a.column,
// y0: a.row,
// x1: b.column,
// y1: b.row,
// dx: b.column - a.column,
// dy: b.row - a.row
// };
// }
//
// // scan-line conversion
// function scanSpans(e0, e1, ymin, ymax, scanLine) {
// var y0 = Math.max(ymin, Math.floor(e1.y0)),
// y1 = Math.min(ymax, Math.ceil(e1.y1));
//
// // sort edges by x-coordinate
// if ((e0.x0 == e1.x0 && e0.y0 == e1.y0)
// ? (e0.x0 + e1.dy / e0.dy * e0.dx < e1.x1)
// : (e0.x1 - e1.dy / e0.dy * e0.dx < e1.x0)) {
// var t = e0; e0 = e1; e1 = t;
// }
//
// // scan lines!
// var m0 = e0.dx / e0.dy,
// m1 = e1.dx / e1.dy,
// d0 = e0.dx > 0, // use y + 1 to compute x0
// d1 = e1.dx < 0; // use y + 1 to compute x1
// for (var y = y0; y < y1; y++) {
// var x0 = m0 * Math.max(0, Math.min(e0.dy, y + d0 - e0.y0)) + e0.x0,
// x1 = m1 * Math.max(0, Math.min(e1.dy, y + d1 - e1.y0)) + e1.x0;
// scanLine(Math.floor(x1), Math.ceil(x0), y);
// }
// }
//
// // scan-line conversion
// function scanTriangle(a, b, c, ymin, ymax, scanLine) {
// var ab = edge(a, b),
// bc = edge(b, c),
// ca = edge(c, a);
//
// // sort edges by y-length
// if (ab.dy > bc.dy) { var t = ab; ab = bc; bc = t; }
// if (ab.dy > ca.dy) { var t = ab; ab = ca; ca = t; }
// if (bc.dy > ca.dy) { var t = bc; bc = ca; ca = t; }
//
// // scan span! scan span!
// if (ab.dy) scanSpans(ca, ab, ymin, ymax, scanLine);
// if (bc.dy) scanSpans(ca, bc, ymin, ymax, scanLine);
// }
}