Stronger typing of triangles and triangulation
This commit is contained in:
@@ -68,7 +68,9 @@ ol.reproj.renderTriangles = function(context,
|
|||||||
image.width + 1, image.height + 1);
|
image.width + 1, image.height + 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
goog.array.forEach(triangulation, function(tri, i, arr) {
|
var shiftDistance = triangulation.shiftDistance;
|
||||||
|
|
||||||
|
goog.array.forEach(triangulation.triangles, function(tri, i, arr) {
|
||||||
context.save();
|
context.save();
|
||||||
|
|
||||||
var targetTL = ol.extent.getTopLeft(targetExtent);
|
var targetTL = ol.extent.getTopLeft(targetExtent);
|
||||||
@@ -93,16 +95,17 @@ ol.reproj.renderTriangles = function(context,
|
|||||||
* | 0 0 0 x1 y1 1 | |a11| |v1|
|
* | 0 0 0 x1 y1 1 | |a11| |v1|
|
||||||
* | 0 0 0 x2 y2 1 | |a12| |v2|
|
* | 0 0 0 x2 y2 1 | |a12| |v2|
|
||||||
*/
|
*/
|
||||||
var x0 = tri[0][0][0], y0 = tri[0][0][1],
|
var src = tri.source, tgt = tri.target;
|
||||||
x1 = tri[1][0][0], y1 = tri[1][0][1],
|
var x0 = src[0][0], y0 = src[0][1],
|
||||||
x2 = tri[2][0][0], y2 = tri[2][0][1];
|
x1 = src[1][0], y1 = src[1][1],
|
||||||
var u0 = tri[0][1][0] - targetTL[0], v0 = -(tri[0][1][1] - targetTL[1]),
|
x2 = src[2][0], y2 = src[2][1];
|
||||||
u1 = tri[1][1][0] - targetTL[0], v1 = -(tri[1][1][1] - targetTL[1]),
|
var u0 = tgt[0][0] - targetTL[0], v0 = -(tgt[0][1] - targetTL[1]),
|
||||||
u2 = tri[2][1][0] - targetTL[0], v2 = -(tri[2][1][1] - targetTL[1]);
|
u1 = tgt[1][0] - targetTL[0], v1 = -(tgt[1][1] - targetTL[1]),
|
||||||
if (tri.shiftDistance) {
|
u2 = tgt[2][0] - targetTL[0], v2 = -(tgt[2][1] - targetTL[1]);
|
||||||
x0 = goog.math.modulo(x0 + tri.shiftDistance, tri.shiftDistance);
|
if (tri.needsShift) {
|
||||||
x1 = goog.math.modulo(x1 + tri.shiftDistance, tri.shiftDistance);
|
x0 = goog.math.modulo(x0 + shiftDistance, shiftDistance);
|
||||||
x2 = goog.math.modulo(x2 + tri.shiftDistance, tri.shiftDistance);
|
x1 = goog.math.modulo(x1 + shiftDistance, shiftDistance);
|
||||||
|
x2 = goog.math.modulo(x2 + shiftDistance, shiftDistance);
|
||||||
}
|
}
|
||||||
var augmentedMatrix = [
|
var augmentedMatrix = [
|
||||||
[x0, y0, 1, 0, 0, 0, u0 / targetResolution],
|
[x0, y0, 1, 0, 0, 0, u0 / targetResolution],
|
||||||
@@ -149,9 +152,9 @@ ol.reproj.renderTriangles = function(context,
|
|||||||
context.save();
|
context.save();
|
||||||
var tlSrcFromData = ol.extent.getTopLeft(src.extent);
|
var tlSrcFromData = ol.extent.getTopLeft(src.extent);
|
||||||
context.translate(tlSrcFromData[0], tlSrcFromData[1]);
|
context.translate(tlSrcFromData[0], tlSrcFromData[1]);
|
||||||
if (tri.shiftDistance) {
|
if (tri.needsShift) {
|
||||||
context.save();
|
context.save();
|
||||||
context.translate(tri.shiftDistance, 0);
|
context.translate(shiftDistance, 0);
|
||||||
renderImage(src.image);
|
renderImage(src.image);
|
||||||
context.restore();
|
context.restore();
|
||||||
renderImage(src.image);
|
renderImage(src.image);
|
||||||
|
|||||||
@@ -3,16 +3,27 @@ goog.provide('ol.reproj.triangulation');
|
|||||||
|
|
||||||
goog.require('goog.array');
|
goog.require('goog.array');
|
||||||
goog.require('goog.math');
|
goog.require('goog.math');
|
||||||
|
goog.require('ol.coordinate');
|
||||||
goog.require('ol.extent');
|
goog.require('ol.extent');
|
||||||
goog.require('ol.proj');
|
goog.require('ol.proj');
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array of triangles,
|
* Single triangle; consists of 3 source points and 3 target points.
|
||||||
* each triangles is Array (length=3) of
|
* `needsShift` can be used to indicate that the whole triangle has to be
|
||||||
* projected point pairs (length=2; [src, dst]),
|
* shifted during reprojection. This is needed for triangles crossing edges
|
||||||
* each point is ol.Coordinate.
|
* of the source projection (dateline).
|
||||||
* @typedef {Array.<Array.<Array.<ol.Coordinate>>>}
|
*
|
||||||
|
* @typedef {{source: Array.<ol.Coordinate>,
|
||||||
|
* target: Array.<ol.Coordinate>,
|
||||||
|
* needsShift: boolean}}
|
||||||
|
*/
|
||||||
|
ol.reproj.Triangle;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {{triangles: Array.<ol.reproj.Triangle>,
|
||||||
|
* shiftDistance: number}}
|
||||||
*/
|
*/
|
||||||
ol.reproj.Triangulation;
|
ol.reproj.Triangulation;
|
||||||
|
|
||||||
@@ -69,50 +80,30 @@ ol.reproj.triangulation.addTriangleIfValid_ = function(triangulation, a, b, c,
|
|||||||
c = transformFwd(cSrc);
|
c = transformFwd(cSrc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var shiftDistance = 0;
|
var needsShift = false;
|
||||||
if (sourceProj.isGlobal()) {
|
if (sourceProj.canWrapX()) {
|
||||||
// determine if the triangle crosses the dateline here
|
// determine if the triangle crosses the dateline here
|
||||||
// This can be detected by transforming centroid of the target triangle.
|
// This can be detected by transforming centroid of the target triangle.
|
||||||
// If the transformed centroid is outside the transformed triangle,
|
// If the transformed centroid is outside the transformed triangle,
|
||||||
// the triangle wraps around projection extent.
|
// the triangle wraps around projection extent.
|
||||||
// In such case, the
|
|
||||||
|
|
||||||
var srcExtent = ol.extent.createEmpty();
|
|
||||||
ol.extent.extendCoordinate(srcExtent, aSrc);
|
|
||||||
ol.extent.extendCoordinate(srcExtent, bSrc);
|
|
||||||
ol.extent.extendCoordinate(srcExtent, cSrc);
|
|
||||||
|
|
||||||
var centroid = [(a[0] + b[0] + c[0]) / 3,
|
var centroid = [(a[0] + b[0] + c[0]) / 3,
|
||||||
(a[1] + b[1] + c[1]) / 3];
|
(a[1] + b[1] + c[1]) / 3];
|
||||||
var centroidSrc = transformInv(centroid);
|
var centroidSrc = transformInv(centroid);
|
||||||
|
|
||||||
var pInTriangle = function(p, p0, p1, p2) {
|
if (!ol.coordinate.isInTriangle(centroidSrc, aSrc, bSrc, cSrc)) {
|
||||||
//TODO: move somewhere else
|
needsShift = true;
|
||||||
var A = (-p1[1] * p2[0] + p0[1] * (-p1[0] + p2[0]) +
|
|
||||||
p0[0] * (p1[1] - p2[1]) + p1[0] * p2[1]) / 2;
|
|
||||||
var sign = A < 0 ? -1 : 1;
|
|
||||||
var s = (p0[1] * p2[0] - p0[0] * p2[1] +
|
|
||||||
(p2[1] - p0[1]) * p[0] +
|
|
||||||
(p0[0] - p2[0]) * p[1]) * sign;
|
|
||||||
var t = (p0[0] * p1[1] - p0[1] * p1[0] +
|
|
||||||
(p0[1] - p1[1]) * p[0] +
|
|
||||||
(p1[0] - p0[0]) * p[1]) * sign;
|
|
||||||
|
|
||||||
return s > 0 && t > 0 && (s + t) < 2 * A * sign;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!pInTriangle(centroidSrc, aSrc, bSrc, cSrc)) {
|
|
||||||
var sourceProjExtent = sourceProj.getExtent();
|
|
||||||
shiftDistance = ol.extent.getWidth(sourceProjExtent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var tri = [[aSrc, a], [bSrc, b], [cSrc, c]];
|
triangulation.triangles.push({
|
||||||
// TODO: typing ! do not add properties to arrays !
|
source: [aSrc, bSrc, cSrc],
|
||||||
tri.shiftDistance = shiftDistance;
|
target: [a, b, c],
|
||||||
if (shiftDistance) {
|
needsShift: needsShift
|
||||||
triangulation.shiftDistance = shiftDistance;
|
});
|
||||||
|
if (needsShift) {
|
||||||
|
var sourceProjExtent = sourceProj.getExtent();
|
||||||
|
triangulation.shiftDistance = ol.extent.getWidth(sourceProjExtent);
|
||||||
}
|
}
|
||||||
triangulation.push(tri);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -130,7 +121,10 @@ ol.reproj.triangulation.addTriangleIfValid_ = function(triangulation, a, b, c,
|
|||||||
ol.reproj.triangulation.createForExtent = function(extent, sourceProj,
|
ol.reproj.triangulation.createForExtent = function(extent, sourceProj,
|
||||||
targetProj, opt_maxTargetExtent, opt_maxSourceExtent, opt_subdiv) {
|
targetProj, opt_maxTargetExtent, opt_maxSourceExtent, opt_subdiv) {
|
||||||
|
|
||||||
var triangulation = [];
|
var triangulation = {
|
||||||
|
triangles: [],
|
||||||
|
shiftDistance: 0
|
||||||
|
};
|
||||||
|
|
||||||
var tlDst = ol.extent.getTopLeft(extent);
|
var tlDst = ol.extent.getTopLeft(extent);
|
||||||
var brDst = ol.extent.getBottomRight(extent);
|
var brDst = ol.extent.getBottomRight(extent);
|
||||||
@@ -178,26 +172,25 @@ ol.reproj.triangulation.createForExtent = function(extent, sourceProj,
|
|||||||
ol.reproj.triangulation.getSourceExtent = function(triangulation) {
|
ol.reproj.triangulation.getSourceExtent = function(triangulation) {
|
||||||
var extent = ol.extent.createEmpty();
|
var extent = ol.extent.createEmpty();
|
||||||
|
|
||||||
if (triangulation.shiftDistance) {
|
var distance = triangulation.shiftDistance;
|
||||||
var shiftDistance = triangulation.shiftDistance;
|
if (distance > 0) {
|
||||||
goog.array.forEach(triangulation, function(triangle, i, arr) {
|
goog.array.forEach(triangulation.triangles, function(triangle, i, arr) {
|
||||||
|
var src = triangle.source;
|
||||||
ol.extent.extendCoordinate(extent,
|
ol.extent.extendCoordinate(extent,
|
||||||
[goog.math.modulo(triangle[0][0][0] + shiftDistance, shiftDistance),
|
[goog.math.modulo(src[0][0] + distance, distance), src[0][1]]);
|
||||||
triangle[0][0][1]]);
|
|
||||||
ol.extent.extendCoordinate(extent,
|
ol.extent.extendCoordinate(extent,
|
||||||
[goog.math.modulo(triangle[1][0][0] + shiftDistance, shiftDistance),
|
[goog.math.modulo(src[1][0] + distance, distance), src[1][1]]);
|
||||||
triangle[1][0][1]]);
|
|
||||||
ol.extent.extendCoordinate(extent,
|
ol.extent.extendCoordinate(extent,
|
||||||
[goog.math.modulo(triangle[2][0][0] + shiftDistance, shiftDistance),
|
[goog.math.modulo(src[2][0] + distance, distance), src[2][1]]);
|
||||||
triangle[2][0][1]]);
|
|
||||||
});
|
});
|
||||||
if (extent[0] > shiftDistance / 2) extent[0] -= shiftDistance;
|
if (extent[0] > distance / 2) extent[0] -= distance;
|
||||||
if (extent[2] > shiftDistance / 2) extent[2] -= shiftDistance;
|
if (extent[2] > distance / 2) extent[2] -= distance;
|
||||||
} else {
|
} else {
|
||||||
goog.array.forEach(triangulation, function(triangle, i, arr) {
|
goog.array.forEach(triangulation.triangles, function(triangle, i, arr) {
|
||||||
ol.extent.extendCoordinate(extent, triangle[0][0]);
|
var src = triangle.source;
|
||||||
ol.extent.extendCoordinate(extent, triangle[1][0]);
|
ol.extent.extendCoordinate(extent, src[0]);
|
||||||
ol.extent.extendCoordinate(extent, triangle[2][0]);
|
ol.extent.extendCoordinate(extent, src[1]);
|
||||||
|
ol.extent.extendCoordinate(extent, src[2]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user