blob: 908fdcf6b2e3d3e074a34184e4344f05ce7b6817 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
-- Copyright 2014 by Ida Bruhns
--
-- This file may be distributed and/or modified
--
-- 1. under the LaTeX Project Public License and/or
-- 2. under the GNU Public License
--
-- See the file doc/generic/pgf/licenses/LICENSE for more information
--- This is a subclass of ForceTemplate, which is used to implement forces
-- that work on individual vertices and pulls them to a specific point on the
-- canvas. This point is given by the |desired at| option. The forces depend
-- on the canvas position of the vertices relative to the canvas point it is
-- pulled to.
-- Imports
local ForceTemplate = require "pgf.gd.force.jedi.base.ForceTemplate"
local lib = require "pgf.gd.lib"
local Preprocessing = require "pgf.gd.force.jedi.base.Preprocessing"
-- Localize math functions
local max = math.max
local sqrt = math.sqrt
local min = math.min
-- Implementation starts here:
local ForcePullToPoint = lib.class { base_class = ForceTemplate }
function ForcePullToPoint:constructor ()
ForceTemplate.constructor(self)
self.p = {}
end
-- This force class works on individual vertices and depends on their
-- current position as well as the point it is desired at. Thus all vertices
-- where the |desired at| option is set are added to the table |p| together
-- with the point where they are wanted.
--
-- @param v The vertices of the graph we are trying to find a layout for.
function ForcePullToPoint:preprocess(v)
for _,vertex in ipairs(v) do
if vertex.options then
local da = vertex.options["desired at"]
if da then
self.p[vertex]= {da}
end
end
end
end
-- Applying the force to the vertices andadding the effect to the passed net
-- force array
--
-- @param data The parameters needed to aplly the force: The options table,
-- the current time stamp, an array containing the summed up net
-- forces
function ForcePullToPoint:applyTo(data)
-- locals for speed
local cap = self.force.cap
local net_forces = data.net_forces
local t_max = self.options["maximum time"]
local t_now = data.t_now
local p = self.p
local time_fun = self.force.time_fun
-- Evaluate time function
local time_factor = time_fun(t_max, t_now)
if time_factor == 0 then
return
end
for v, point in pairs(p) do
-- dereference
local p1 = v.pos
local p2 = point[1]
-- calculate distance between vertex and centroid
local x = p1.x - p2.x
local y = p1.y - p2.y
local d = max(sqrt(x*x+y*y),0.1)
-- Include time function
local h = d * time_factor
-- scale effect according to direction
local f = x * h
local g = y * h
-- cap effect if necessary
if cap then
if f <= 0 then
x = max(-cap, f)
else
x = min(cap, f)
end
if g <= 0 then
y = max(-cap, g)
else
y = min(cap, g)
end
else
x = f
y = g
end
-- add calculated effect to net forces
local c1 = net_forces[v]
c1.x = c1.x - x
c1.y = c1.y - y
end
end
return ForcePullToPoint
|