当在径向树中执行鱼眼畸变时的变换问题 [英] transformation issues when implementing fisheye distortion in a radial tree

查看:173
本文介绍了当在径向树中执行鱼眼畸变时的变换问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上,我试图应用d3鱼眼失真算法到径向树。我相信我遇到的问题围绕着这样的事实,即馈送到鱼眼变形的坐标是由d3.layout.tree计算的坐标。但实际坐标已经通过g变换调整。因此,由鱼眼畸变产生的坐标需要调整回g变换。



例如:

  //根据鱼眼坐标重新设置投影
diagonal.projection(function(d){d.fisheye = fisheye(d); return [d.fisheye。 y,d.fisheye.x / 180 * Math.PI];})

这...这里是小提琴


解决方案

按照我在建议的意见,是结果:



http://fiddle.jshell.net/ 7TPhq / 7 /



我创建了两个基于三角函数的函数来计算数据的水平和垂直位置,而不是使用旋转和平移来定位节点(x,y)值,它们被当作极坐标。



然后我必须设置鱼眼函数才能使用我的定位函数作为accessor dx dy 。不幸的是,你用于鱼眼的基本插件没有包括一个方法来获取和设置x / y访问器函数,所以我不得不修改它。我很惊讶它不是已经在代码中;它是大多数d3布局对象的标准功能。



(当我得到github设置,我将需要一个pull请求添加它。我需要为了弄清楚鱼眼缩放/缩放功能是如何工作的,虽然 - 我从这个例子中,因为你没有使用它。)



定位功能如下所示:

  function getHPosition(d){
//计算转换的(笛卡尔)位置)
//(无鱼眼效果)
//极坐标(x,y)其中
// x是角度
// y是距离半径,半径)
//参见http://www.engineeringtoolbox.com/converting-cartesian-polar-coordinates-d_1347.html

return(dy)* Math.cos(dx );
}
function getVPosition(d){
return(d.y)* Math.sin(d.x);
};

函数用于设置节点和链接的原始位置,然后一旦鱼眼踢它在内部使用这些函数,返回结果(如果适当,失真) d.fisheye.x d.fisheye.y



例如,对于意味着投影的链接,设置 d3.svg.diagonal

  var diagonal = d3.svg.diagonal()
.projection(function(d){
return [getHPosition(d),getVPosition(d)];
});

但是像这样更新:

  diagonal.projection(function(d){
d.fisheye = fisheye(d);
return [d.fisheye.x,d.fisheye.y];
});

还有其他一些变化:



我添加了一个带有 pointer-events:all; ,以便鱼眼不会打开和关闭,因为鼠标在节点和空白背景之间移动。



没有打扰旋转文本(因为节点组不再旋转,默认情况下不会发生),但您可以轻松地在单个文本元素上添加旋转变换。



最后,这个问题比我想承认的时间长,对于Javascript trig函数,角度必须在弧度。无法找出为什么我的布局是这么丑陋,重叠线。我认为这是在切换 d3.svg.diagonal() d3.svg.diagonal.radial()并花了很多时间试图做反向触发和各种各样的东西...


Basically, I am attempting to apply the d3 fisheye distortion algorithm to a radial tree. I believe the issues I am encountering revolve around the fact that the coords being fed to the fisheye distortion are the coords computed by the d3.layout.tree. But the actual coords have been adjusted by the g transform. So, the coords resulting from the fisheye distortion need to be adjusted back to the g transform.

For example:

// re-setting the projection according to fisheye coords
diagonal.projection(function(d) { d.fisheye = fisheye(d); return [d.fisheye.y, d.fisheye.x / 180 * Math.PI]; })

I have been attempting this...here is the fiddle.

I am somewhat close...help is appreciated.

解决方案

Following the direction I'd suggested in the comments, this is the result:

http://fiddle.jshell.net/7TPhq/7/

Instead of using rotations and translations to position the nodes, I created two trigonometry-based functions to calculate horizontal and vertical position from the data (x,y) values, which are treated as polar coordinates.

Then I had to set the fisheye function to use my positioning functions as "accessor" functions instead of reading d.x and d.y directly. Unfortunately, the basic plug-in you were using for the fisheye didn't include a way to get and set x/y accessor functions, so I had to modify that too. I was surprised it wasn't already in the code; it's a standard functionality on most d3 layout objects.

(When I get github set up, I will have to make a pull request to add it in. I'll need to figure out how the fisheye scale/zoom function works, though -- I took that out of this example since you weren't using it.)

The positioning functions were as follows:

function getHPosition(d){
    //calculate the transformed (Cartesian) position (H, V)
    //(without fisheye effect)
    //from the polar coordinates (x,y) where 
    //x is the angle
    //y is the distance from (radius,radius)
    //See http://www.engineeringtoolbox.com/converting-cartesian-polar-coordinates-d_1347.html

    return (d.y)*Math.cos(d.x);
}
function getVPosition(d){
    return (d.y)*Math.sin(d.x);
};

The functions are used to set the original position of the nodes and links, and then once the fisheye kicks in it uses these functions internally, returning the results (with distortion if appropriate) as d.fisheye.x and d.fisheye.y.

For example, for links that means the projection setting the d3.svg.diagonal function like this for initialization:

var diagonal = d3.svg.diagonal()
    .projection(function(d) { 
        return [getHPosition(d), getVPosition(d)]; 
});

But like this for update:

diagonal.projection(function(d) { 
    d.fisheye = fisheye(d); 
    return [d.fisheye.x, d.fisheye.y]; 
});

There are a couple other little changes:

I simplified the dimensions of the plotting area a bit.

I added a background rectangle with pointer-events:all; so that the fisheye doesn't turn on and off as the mouse moves between nodes and empty background.

I didn't bother rotating the text (since the node groups are no longer rotating, it doesn't happen by default), but you could easily add in a rotate transformation on the individual text elements.

Finally, and this one stumped me for longer than I'd like to admit, the angles have to be in radians for the Javascript trig functions. Couldn't figure out why my layouts were so ugly, with overlapping lines. I thought it was something to do with switching between d3.svg.diagonal() and d3.svg.diagonal.radial() and spent a lot of time trying to do inverse-trig and all sorts of things...

这篇关于当在径向树中执行鱼眼畸变时的变换问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆