Russell Asher
Russell Asher

Reputation: 195

Cannot clip polygon using d3.js

I am trying to take a polygon and cut another polygon with its intersecting area. I thought d3.geom.polygon 's method clip would work but I seem to get all sorts of weird problems when I try it in the below fiddle.

http://jsfiddle.net/RussellAsher/335089x2/8/

If anyone knows how I would do this with or without d3.js I would be eternally thankful.

d3 methods I am trying to use:

var p1 = d3.geom.polygon(arrayOfPolygons[0].points);
var p2 = d3.geom.polygon(arrayOfPolygons[1].points);
p2.clip(p1);

Upvotes: 1

Views: 902

Answers (1)

Ruben Kazumov
Ruben Kazumov

Reputation: 3872

The d3.js source:

https://github.com/mbostock/d3/blob/master/src/geom/polygon.js#L49-L86

at line 49 you can read:

// The Sutherland-Hodgman clipping algorithm.
// Note: requires the clip polygon to be counterclockwise and convex.
d3_geom_polygonPrototype.clip = function(subject) {
...
}

You SHOULD make polygons counter-directed like this:

enter image description here

In your case:

var vis = d3.select("body").append("svg").attr({
    width: 1000,
    height: 667
}),

// I deleted scales there to make the code smaller

arrayOfPolygons = [{
    name: "polygon 1",
    points: []
}, {
    name: "polygon 2 ",
    points: []
}];

// clockwise polygon
arrayOfPolygons[0].points = [
    [5.5, 15.5],
    [24.0, 15.5],
    [20.5, 20],
    [12.0, 45.5],
    [4.0, 20]
];
// counterclockwise polygon
arrayOfPolygons[1].points = [
    [4.5, 24.5],
    [14.0, 24.5],
    [18.5, 20],
    [0.0, 20]
];

var p1 = d3.geom.polygon(arrayOfPolygons[0].points);
var p2 = d3.geom.polygon(arrayOfPolygons[1].points);
var p_x = p1.slice();// cloned polygon
p2.clip(p_x);// cloned polygon clipped

// the first polygon
vis.append("svg:polygon").attr({
    points: p1,
    stroke: "black",
    fill: "none"
});

// the second polygon
vis.append("svg:polygon").attr({
    points: p2,
    stroke: "black",
    fill: "none"
});

// clipped part
vis.append("svg:polygon").attr({
    points: p_x,
    stroke: "red",
    fill: "yellow"
});

finally the result:

DEMO: http://jsfiddle.net/335089x2/12/

Now you can add the data() function and scales.

Upvotes: 3

Related Questions