summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/circular/Tantau2012.lua
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2014-02-27 00:01:50 +0000
committerKarl Berry <karl@freefriends.org>2014-02-27 00:01:50 +0000
commit90ae413a94da014dbf7a6a8ab584f7c668483a5a (patch)
tree4e0528a2b2fb2004988e7fc804ea2f1354f1f5d5 /Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/circular/Tantau2012.lua
parent800cc56380d1edfe567a6a66bef13e8950eb2b0c (diff)
pgf 3.0.0
git-svn-id: svn://tug.org/texlive/trunk@33057 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/circular/Tantau2012.lua')
-rw-r--r--Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/circular/Tantau2012.lua144
1 files changed, 144 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/circular/Tantau2012.lua b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/circular/Tantau2012.lua
new file mode 100644
index 00000000000..774bdc907be
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/pgf/graphdrawing/lua/pgf/gd/circular/Tantau2012.lua
@@ -0,0 +1,144 @@
+-- Copyright 2012 by Till Tantau
+--
+-- This file may be distributed an/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
+
+-- @release $Header: /cvsroot/pgf/pgf/generic/pgf/graphdrawing/lua/pgf/gd/circular/Tantau2012.lua,v 1.7 2013/05/23 20:01:25 tantau Exp $
+
+
+-- Imports
+local declare = require("pgf.gd.interface.InterfaceToAlgorithms").declare
+
+-- The algorithm class
+local Tantau2012 = {}
+
+---
+declare {
+ key = "simple necklace layout",
+ algorithm = Tantau2012,
+
+ postconditions = {
+ upward_oriented = true
+ },
+
+ documentation_in = "pgf.gd.doc.circular.Tantau2012"
+}
+
+
+
+-- Imports
+
+local Coordinate = require "pgf.gd.model.Coordinate"
+
+local lib = require "pgf.gd.lib"
+
+
+-- The implementation
+
+function Tantau2012:run()
+ local g = self.digraph
+ local vertices = g.vertices
+ local n = #vertices
+
+ local sib_dists = self:computeNodeDistances ()
+ local radii = self:computeNodeRadii()
+ local diam, adjusted_radii = self:adjustNodeRadii(sib_dists, radii)
+
+ -- Compute total necessary length. For this, iterate over all
+ -- consecutive pairs and keep track of the necessary space for
+ -- this node. We imagine the nodes to be aligned from left to
+ -- right in a line.
+ local carry = 0
+ local positions = {}
+ local function wrap(i) return (i-1)%n + 1 end
+ local ideal_pos = 0
+ for i = 1,n do
+ positions[i] = ideal_pos + carry
+ ideal_pos = ideal_pos + sib_dists[i]
+ local node_sep =
+ lib.lookup_option('node post sep', vertices[i], g) +
+ lib.lookup_option('node pre sep', vertices[wrap(i+1)], g)
+ local arc = node_sep + adjusted_radii[i] + adjusted_radii[wrap(i+1)]
+ local needed = carry + arc
+ local dist = math.sin( arc/diam ) * diam
+ needed = needed + math.max ((radii[i] + radii[wrap(i+1)]+node_sep)-dist, 0)
+ carry = math.max(needed-sib_dists[i],0)
+ end
+ local length = ideal_pos + carry
+
+ local radius = length / (2 * math.pi)
+ for i,vertex in ipairs(vertices) do
+ vertex.pos.x = radius * math.cos(2 * math.pi * (positions[i] / length + 1/4))
+ vertex.pos.y = -radius * math.sin(2 * math.pi * (positions[i] / length + 1/4))
+ end
+end
+
+
+function Tantau2012:computeNodeDistances()
+ local sib_dists = {}
+ local sum_length = 0
+ local vertices = self.digraph.vertices
+ for i=1,#vertices do
+ sib_dists[i] = lib.lookup_option('node distance', vertices[i], self.digraph)
+ sum_length = sum_length + sib_dists[i]
+ end
+
+ local missing_length = self.digraph.options['radius'] * 2 * math.pi - sum_length
+ if missing_length > 0 then
+ -- Ok, the sib_dists to not add up to the desired minimum value.
+ -- What should we do? Hmm... We increase all by the missing amount:
+ for i=1,#vertices do
+ sib_dists[i] = sib_dists[i] + missing_length/#vertices
+ end
+ end
+
+ sib_dists.total = math.max(self.digraph.options['radius'] * 2 * math.pi, sum_length)
+
+ return sib_dists
+end
+
+
+function Tantau2012:computeNodeRadii()
+ local radii = {}
+ for i,v in ipairs(self.digraph.vertices) do
+ local min_x, min_y, max_x, max_y = v:boundingBox()
+ local w, h = max_x-min_x, max_y-min_y
+ if v.shape == "circle" or v.shape == "ellipse" then
+ radii[i] = math.max(w,h)/2
+ else
+ radii[i] = math.sqrt(w*w + h*h)/2
+ end
+ end
+ return radii
+end
+
+
+function Tantau2012:adjustNodeRadii(sib_dists,radii)
+ local total = 0
+ local max_rad = 0
+ for i=1,#radii do
+ total = total + 2*radii[i]
+ + lib.lookup_option('node post sep', self.digraph.vertices[i], self.digraph)
+ + lib.lookup_option('node pre sep', self.digraph.vertices[i], self.digraph)
+ max_rad = math.max(max_rad, radii[i])
+ end
+ total = math.max(total, sib_dists.total, max_rad*math.pi)
+ local diam = total/(math.pi)
+
+ -- Now, adjust the radii:
+ local adjusted_radii = {}
+ for i=1,#radii do
+ adjusted_radii[i] = (math.pi - 2*math.acos(radii[i]/diam))*diam/2
+ end
+
+ return diam, adjusted_radii
+end
+
+
+-- done
+
+return Tantau2012 \ No newline at end of file