X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=dev%2Fgraphviz%2Fgraphviz-support.lisp;h=eda1187d94071cd8aa7bd2253ddaa6833a2963f0;hb=a3062aaed0bb42f1bbbc7cf6d1a2cf14c277a712;hp=4b3bbd33384642ec7ac61d57249cc94d4915375e;hpb=dfe1ca9987337cf9e8ad32aa44d6a55c0d8a7c75;p=cl-graph.git diff --git a/dev/graphviz/graphviz-support.lisp b/dev/graphviz/graphviz-support.lisp index 4b3bbd3..eda1187 100644 --- a/dev/graphviz/graphviz-support.lisp +++ b/dev/graphviz/graphviz-support.lisp @@ -2,20 +2,14 @@ #| simple-header -$Id: graphviz-support.lisp,v 1.7 2005/06/21 20:51:51 moody Exp $ - -Copyright 1992 - 2005 Experimental Knowledge Systems Lab, -University of Massachusetts Amherst MA, 01003-4610 -Professor Paul Cohen, Director - -Author: Gary King, Levente Mészáros, Attila Lendvai +Author: Gary King, Levente Mészáros, Attila Lendvai DISCUSSION This file contains the stuff that does not depend on cl-graphviz. |# -(in-package metabang.graph) +(in-package #:metabang.graph) ;;; --------------------------------------------------------------------------- ; @@ -24,15 +18,16 @@ This file contains the stuff that does not depend on cl-graphviz. ; "GRAPHVIZ". ; (defmethod graph->dot ((g basic-graph) (stream stream) - &key + &key (graph-formatter 'graph->dot-properties) (vertex-key 'vertex-id) (vertex-labeler nil) (vertex-formatter 'vertex->dot) - (edge-key nil) (edge-labeler 'princ) - (edge-formatter 'edge->dot)) - (format stream "~A G {~%graph " (if (contains-undirected-edge-p g) "graph" "digraph")) + (edge-formatter 'edge->dot) + &allow-other-keys) + (format stream "~A G {~%graph " + (if (contains-undirected-edge-p g) "graph" "digraph")) (format stream "[") (funcall graph-formatter g stream) (format stream "];") @@ -65,7 +60,7 @@ This file contains the stuff that does not depend on cl-graphviz. (princ " [" stream) (when (and directed? directed-edge-tag) (princ directed-edge-tag stream)) - (when edge-key + (when edge-labeler (princ "label=\"" stream) (funcall edge-labeler e stream) (princ "\"," stream)) @@ -87,9 +82,11 @@ This file contains the stuff that does not depend on cl-graphviz. (iterate-vertexes g (lambda (v) + ;(spy v) (iterate-edges v (lambda (e) + ;(spy e (undirected-edge-p e) (item-at-1 edges e)) (when (and (undirected-edge-p e) (not (item-at-1 edges e))) (setf (item-at-1 edges e) t) @@ -243,14 +240,16 @@ B--D [] |# (defparameter *dot-graph-attributes* - '((:size coord) + '((:size coordinate) (:bb bounding-box) (:page text) + (:dpi float) (:ratio (:fill :compress :auto)) ;; Could actually be a float number too (:margin float) (:nodesep float) (:ranksep float) (:ordering (:out)) + (:overlap text) (:rankdir ("LR" "RL" "BT")) (:pagedir text) (:rank (:same :min :max)) @@ -260,12 +259,14 @@ B--D [] (:mclimit float) (:layers text) (:color text) - (:bgcolor text))) + (:bgcolor text) + (:fontname text))) (defparameter *dot-vertex-attributes* '((:pos coordinate) (:height float) (:width float) + (:margin float) (:fixed-size boolean) (:label text) (:shape (:record :plaintext :ellipse :circle :egg :triangle :box @@ -273,10 +274,13 @@ B--D [] :doublecircle)) (:fontsize integer) (:fontname text) + (:fontcolor text) (:color text) (:fillcolor text) (:style (:filled :solid :dashed :dotted :bold :invis)) - (:layer text))) + (:layer text) + (:url text) + (:peripheries integer))) (defparameter *dot-edge-attributes* '((:pos spline) @@ -315,7 +319,11 @@ B--D [] (:export-p t)) (defclass* dot-graph-mixin (dot-attributes-mixin) () - (:export-p t)) + (:export-p t) + (:default-initargs + :vertex-class 'dot-vertex + :directed-edge-class 'dot-directed-edge + :undirected-edge-class 'dot-edge)) (defclass* dot-vertex-mixin (dot-attributes-mixin) () (:export-p t)) (defclass* dot-edge-mixin (dot-attributes-mixin) () @@ -323,10 +331,6 @@ B--D [] (defclass* dot-graph (dot-graph-mixin graph-container) () - (:default-initargs - :vertex-class 'dot-vertex - :directed-edge-class 'dot-directed-edge - :undirected-edge-class 'dot-edge) (:export-p t)) (defclass* dot-vertex (dot-vertex-mixin graph-container-vertex) () @@ -338,6 +342,7 @@ B--D [] (defmethod (setf dot-attribute-value) :before (value (attr symbol) (thing dot-attributes-mixin)) + (declare (ignore value)) (ensure-valid-dot-attribute attr thing)) (defmethod (setf dot-attribute-value) (value (attr symbol) (thing dot-attributes-mixin)) @@ -346,11 +351,27 @@ B--D [] (defmethod dot-attribute-value ((attr symbol) (thing dot-attributes-mixin)) (getf (dot-attributes thing) attr)) +(defmacro defpixel-inch-accessors (name attr type) + (bind ((actual-name (form-symbol name "-IN-PIXELS"))) + `(progn + (eval-always (export ',actual-name)) + (defmethod ,actual-name ((thing ,type)) + "Return the attribute in pixels assuming 72 dpi" + (when (dot-attribute-value ,attr thing) + (* 72 (dot-attribute-value ,attr thing)))) + (defmethod (setf ,actual-name) (value (thing ,type)) + "Set the attribute in pixels assuming 72 dpi" + (setf (dot-attribute-value ,attr thing) + (coerce (/ value 72) 'double-float)))))) + +(defpixel-inch-accessors width :width dot-vertex-mixin) +(defpixel-inch-accessors height :height dot-vertex-mixin) + + (defmethod graph->dot-properties ((graph dot-graph-mixin) (stream t)) (loop for (name value) on (dot-attributes graph) by #'cddr do - (print-dot-key-value name value *dot-graph-attributes* stream) - (format stream " ;~%"))) + (print-dot-key-value name value *dot-graph-attributes* stream))) (defmethod vertex->dot ((vertex dot-vertex-mixin) (stream t)) (format-dot-attributes vertex *dot-vertex-attributes* stream)) @@ -380,7 +401,8 @@ B--D [] (destructuring-bind (key value-type) (or (assoc key dot-attributes) (error "Invalid attribute ~S" key)) - (format stream "~a=~a" (string-downcase key) + (write-name-for-dot key stream) + (format stream "=~a" (etypecase value-type ((member coordinate) (with-output-to-string (str) @@ -428,7 +450,9 @@ B--D [] ((member text) (textify value)) ((member float) - (coerce value 'single-float)) + ;; graphviz does not support the 1.2e-3 format + (with-output-to-string (str) + (format str "~,f" (coerce value 'single-float)))) (list (unless (member value value-type :test 'equal) (error "Invalid value for ~S: ~S is not one of ~S" @@ -437,6 +461,12 @@ B--D [] (string-downcase value) value)))))) +(defmethod write-name-for-dot (attribute stream) + (format stream "~(~A~)" attribute)) + +(defmethod write-name-for-dot ((attribute (eql :url)) stream) + (format stream "URL")) + (defun textify (object) (let ((string (princ-to-string object))) (with-output-to-string (stream) @@ -467,8 +497,10 @@ B--D [] (defmethod graph->dot-external ((g basic-graph) file-name &key (type :ps)) "Generate an external represenation of a graph to a file, by running the program in *dot-path*." + (declare (ignorable file-name)) (let ((dot-string (graph->dot g nil)) (dot-type (concatenate 'string "-T" (string-downcase (symbol-name type))))) + (declare (ignorable dot-string dot-type)) #+lispworks (with-open-stream (s (sys:open-pipe (concatenate 'string *dot-path* " -Tpng -o" file-name) :direction :input))