diff options
Diffstat (limited to 'graphics/pgf/base/tex/generic/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForceCanvasDistance.lua')
-rw-r--r-- | graphics/pgf/base/tex/generic/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForceCanvasDistance.lua | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/graphics/pgf/base/tex/generic/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForceCanvasDistance.lua b/graphics/pgf/base/tex/generic/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForceCanvasDistance.lua new file mode 100644 index 0000000000..8cea1aec6a --- /dev/null +++ b/graphics/pgf/base/tex/generic/graphdrawing/lua/pgf/gd/force/jedi/forcetypes/ForceCanvasDistance.lua @@ -0,0 +1,201 @@ +-- 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 between +-- vertex pairs. The forces depend on the canvas distance of the vertices in +-- the pair. This class is e.~g.~ used for electric forces. + +-- 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 ForceCanvasDistance = lib.class { base_class = ForceTemplate } + +function ForceCanvasDistance:constructor () + ForceTemplate.constructor(self) + self.p = {} +end + + +-- This force class works on all pairwise disjoint vertex pairs. This +-- function generates a new graph object containing all vertices from the +-- original graph and arcs between all pairwise disjoint vertex pairs. The +-- arcs-table of this new object will be saved in the variable |p|. +-- +-- @param v The vertices of the graph we are trying to find a layout for. + +function ForceCanvasDistance:preprocess(v) + self.p = Preprocessing.allPairs(v) +end + + +-- Applying the force to the vertices and adding the effect to the passed net +-- force array +-- +-- @param data The parameters needed to apply the force: The options table, +-- the current time stamp, an array containing the summed up net +-- forces + +function ForceCanvasDistance:applyTo(data) + -- locals for speed + local cap = self.force.cap + local fun_u = self.force.fun_u + local fun_v = self.force.fun_v + local net_forces = data.net_forces + local t_max = self.options["maximum time"] + local t_now = data.t_now + local k = data.k + local p = self.p + local time_fun = self.force.time_fun + local fw_attributes = self.fw_attributes + + -- Evaluate time function + local time_factor = time_fun(t_max, t_now) + if time_factor == 0 then + return + end + + if not fun_v then + local data = { k = k, attributes = fw_attributes } + for _, i in ipairs(p) do + -- dereference + local p2 = i.head + local p1 = i.tail + local p2_pos = p2.pos + local p1_pos = p1.pos + + -- calculate distance between two points + local x = p2_pos.x - p1_pos.x + local y = p2_pos.y - p1_pos.y + local d = max(sqrt(x*x+y*y),0.1) + + -- apply force function + data.u = p2 + data.v = p1 + data.d = d + local e = fun_u(data) + + -- Include time function + local f = e * time_factor / d + + -- calculate effect on x/y + local g = x * f + local h = y * f + + -- cap effect if necessary + if cap then + if g <= 0 then + x = max(-cap, g) + else + x = min(cap, g) + end + + if h <= 0 then + y = max(-cap, h) + else + y = min(cap, h) + end + else + x = g + y = h + end + + -- add calculated effect to net forces + local c1 = net_forces[p1] + c1.x = c1.x - x + c1.y = c1.y - y + local c2 = net_forces[p2] + c2.x = c2.x + x + c2.y = c2.y + y + end + else + -- There are different functions for head and tail vertex + local data = { k = k, attributes = fw_attributes } + for _, i in ipairs(p) do + -- dereference + local p2 = i.head + local p1 = i.tail + local p2_pos = p2.pos + local p1_pos = p1.pos + + -- calculate distance between two points + local x = p2_pos.x - p1_pos.x + local y = p2_pos.y - p1_pos.y + local d = max(sqrt(x*x+y*y),0.1) + + -- apply force function to distance and k (natural spring length + data.u = p2 + data.v = p1 + data.d = d + local e_head = fun_u(data) + local e_tail = fun_v(data) + + -- Include time function + local f_head = time_factor * e_head / d + local f_tail = time_factor * e_tail / d + + -- calculate effect on x/y + local g_head = x * f_head + local g_tail = x * f_tail + local h_head = y * f_head + local h_tail = y * f_tail + + -- cap effect if necessary + local x_head, x_tail, y_head, y_tail + if cap then + if g_head <= 0 then + x_head = max(-cap, g_head) + else + x_head = min(cap, g_head) + end + + if g_tail <= 0 then + x_tail = max(-cap, g_tail) + else + x_tail = min(cap, g_tail) + end + + if h_head <= 0 then + y_head = max(-cap, h_head) + else + y_head = min(cap, h_head) + end + + if h_tail <= 0 then + y_tail = max(-cap, h_tail) + else + y_tail = min(cap, h_tail) + end + else + x_head = g_head + x_tail = g_tail + y_head = h_head + y_tail = h_tail + end + + -- add calculated effect to net forces + local c1 = net_forces[p1] + c1.x = c1.x - x_tail + c1.y = c1.y - y_tail + local c2 = net_forces[p2] + c2.x = c2.x + x_head + c2.y = c2.y + y_head + end + end +end + +return ForceCanvasDistance
\ No newline at end of file |