Always draw midpoint handles within viewport (like #1840)

This commit is contained in:
Bryan Housel
2014-06-14 01:33:20 -04:00
parent 203381694b
commit b07cf7c1c1
3 changed files with 71 additions and 13 deletions

View File

@@ -87,6 +87,39 @@ iD.geo.chooseEdge = function(nodes, point, projection) {
};
};
// Return the intersection point of 2 line segments.
// From https://github.com/pgkelley4/line-segments-intersect
// This uses the vector cross product approach described below:
// http://stackoverflow.com/a/565282/786339
iD.geo.lineIntersection = function(a, b) {
function subtractPoints(point1, point2) {
return [point1[0] - point2[0], point1[1] - point2[1]];
}
function crossProduct(point1, point2) {
return point1[0] * point2[1] - point1[1] * point2[0];
}
var p = [a[0][0], a[0][1]],
p2 = [a[1][0], a[1][1]],
q = [b[0][0], b[0][1]],
q2 = [b[1][0], b[1][1]],
r = subtractPoints(p2, p),
s = subtractPoints(q2, q),
uNumerator = crossProduct(subtractPoints(q, p), r),
denominator = crossProduct(r, s);
if (uNumerator && denominator) {
var u = uNumerator / denominator,
t = crossProduct(subtractPoints(q, p), s) / denominator;
if ((t >= 0) && (t <= 1) && (u >= 0) && (u <= 1)) {
return iD.geo.interp(p, p2, t);
}
}
return null;
}
// Return whether point is contained in polygon.
//
// `point` should be a 2-item array of coordinates.

View File

@@ -76,10 +76,9 @@ iD.Map = function(context) {
if (map.editable() && !transformed) {
var all = context.intersects(map.extent()),
filter = d3.functor(true),
extent = map.extent(),
graph = context.graph();
surface.call(vertices, graph, all, filter, extent, map.zoom());
surface.call(midpoints, graph, all, filter, extent);
surface.call(vertices, graph, all, filter, map.extent(), map.zoom());
surface.call(midpoints, graph, all, filter, map.trimmedExtent());
dispatch.drawn({full: false});
}
});
@@ -114,7 +113,7 @@ iD.Map = function(context) {
.call(vertices, graph, all, filter, map.extent(), map.zoom())
.call(lines, graph, all, filter)
.call(areas, graph, all, filter)
.call(midpoints, graph, all, filter, map.extent())
.call(midpoints, graph, all, filter, map.trimmedExtent())
.call(labels, graph, all, filter, dimensions, !difference && !extent);
if (points.points(context.intersects(map.extent()), 100).length >= 100) {
@@ -366,6 +365,11 @@ iD.Map = function(context) {
}
};
map.trimmedExtent = function() {
return new iD.geo.Extent(projection.invert([10, dimensions[1] - 40]),
projection.invert([dimensions[0] - 10, 70]));
};
map.extentZoom = function(_) {
var extent = iD.geo.Extent(_),
tl = projection([extent[0][0], extent[1][1]]),

View File

@@ -22,15 +22,36 @@ iD.svg.Midpoints = function(projection, context) {
if (midpoints[id]) {
midpoints[id].parents.push(entity);
} else {
var loc = iD.geo.interp(a.loc, b.loc, 0.5);
if (extent.intersects(loc) && iD.geo.euclideanDistance(projection(a.loc), projection(b.loc)) > 40) {
midpoints[id] = {
type: 'midpoint',
id: id,
loc: loc,
edge: [a.id, b.id],
parents: [entity]
};
if (iD.geo.euclideanDistance(projection(a.loc), projection(b.loc)) > 40) {
var point = iD.geo.interp(a.loc, b.loc, 0.5),
loc;
if (extent.intersects(point)) {
loc = point;
} else {
var poly = extent.polygon();
for (var k = 0; k < 4; k++) {
point = iD.geo.lineIntersection([a.loc, b.loc], [poly[k], poly[k+1]]);
if (point &&
iD.geo.euclideanDistance(projection(a.loc), projection(point)) > 20 &&
iD.geo.euclideanDistance(projection(b.loc), projection(point)) > 20)
{
loc = point;
break;
}
}
}
if (loc) {
midpoints[id] = {
type: 'midpoint',
id: id,
loc: loc,
edge: [a.id, b.id],
parents: [entity]
};
}
}
}
}