d3.geom.voronoi - trimming edge polygons

590 views
Skip to first unread message

Francis Hemsher

unread,
May 12, 2012, 3:03:05 PM5/12/12
to d3-js
The edge polygons generated via d3.geom.voronoi extend far beyond the
container SVG element's width and height. I can visually 'trim' these
edge polygons by applying the attribute overflow="hidden" for the SVG
container.

However, I would like to actually trim these edge polygons where they
intersect the x=0, y=0 and the x=width, y=height axis. I need this to
compute the centroid of these edge polygons.

I have attempted to accomplish this by computing line intersects, then
rewriting the points values of the individual polygons. ..This works
after fashion, but is currently beyond my ability:)

I'm hoping someone has previously accomplished this, and can point me
in the right direction.

Thanks,
Francis

jerome cukier

unread,
May 12, 2012, 7:54:36 PM5/12/12
to d3-js
how about using clipPath?

ie

var defs=svg.append("defs");
defs.append("clipPath").attr("id","myclip")
.append("rect").attr("x",x(0)).attr("y",y(0)).attr("height",height).attr("width",width) //
well this is the rectangle you want your voronois to be inscribed in

[...]

then at some point

svg.append("g").attr('clip-path", "url(#myclip)") // what's after
url(# is the id of the clipPath you've specified above.
.append(...) // and that's where you'd append whatever you want to see
clipped.

note that clip path isn't restricted to rectangles, you can use paths.
I'm using voronois + clipping paths to make maps.
hth
jerome

Francis Hemsher

unread,
May 12, 2012, 8:46:28 PM5/12/12
to d3-js
Hi Jerome,
The clipPath functions similar to overflow="hidden": The edge polygons
still maintain their original points. Since I need to compute the
centroid of the visible portion of each edge polygon, I must
recalculate new points so the polygon points are modified so they do
not fall outside of the visible space.

I probably can do this by a somewhat complex method of segmenting the
polygon into individual lines and computing their intersects with the
axis. Then re-assemble the polygon with the resultant intersect data.
I was hoping that someone had successfully used a similar method.
Still hoping...

Thanks,
Francis

On May 12, 7:54 pm, jerome cukier <jeromecuk...@gmail.com> wrote:
> how about using clipPath?
>
> ie
>
> var defs=svg.append("defs");
> defs.append("clipPath").attr("id","myclip")
>         .append("rect").attr("x",x(0)).attr("y",y(0)).attr("height",height).attr("w­idth",width) //

Mike Bostock

unread,
May 12, 2012, 8:50:23 PM5/12/12
to d3...@googlegroups.com
Try d3.geom.polygon's clip method.

Mike

Francis Hemsher

unread,
May 13, 2012, 8:56:16 PM5/13/12
to d3-js
Hi Mike,
Yes, that works.
Following is the application which uses the view space
polygon(rectangle)
to trim each edge polygon(subject):
//====trim each edge polygons======
EdgeId.forEach(function(d)//---array with each edge polygon id---
{
var edgePolygon=newG.select("#"+d)
var edgePoints=edgePolygon.attr("points")
//--points format: x0,y0 x1,y1 x2,y2 x3,y3 ....
var pntArray=[]
var splitEdge=edgePoints.split(" ")
for(var k=0;k<splitEdge.length;k++)
{
var xy=splitEdge[k].split(",")
pntArray.push([parseFloat(xy[0]),parseFloat(xy[1])])
}
//--view space(polygon): left to right ---
var trimMe=d3.geom.polygon([[0,0],[0,h],[w,h],[w,0]])
.clip(pntArray)//---subject(polygon)---
edgePolygon.attr("points",trimMe.join())
})
}

Thanks,
Francis
Reply all
Reply to author
Forward
0 new messages