且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

将图形转换为二维图

更新时间:2023-02-27 07:48:02

Firstly, for your particular example it would not be possible to generate a graph for which the edge weights are the line lengths.

For example, if the distances between nodes 1, 2 and 3 are per your arrays:

  • 1 → 2 = 50
  • 1 → 3 = 10

Then the distance 2 → 3 must be between 40 & 60, else the triangle does not exist. Whereas your array specifies this distance as 90.

To demonstrate this visually, if you were to picture a line of length 50 spanning nodes 1 & 2, if you construct circles at either end of this line with radii equal to the distances between nodes 1 → 3 and 2 → 3, then such circles must intersect for the triangle to exist.

Currently, with the weights you have specified, there is no such intersection:


As such, assuming arbitrary positions for each of the nodes, with node coordinates supplied as an argument to the function, you could construct the desired graph using a function such as the following AutoLISP example:

(defun graph ( pts sls tls wgt )
    (   (lambda ( l )
            (foreach x l (text (cdr x) (itoa (car x)) 0.0 1))
            (mapcar
               '(lambda ( a b c / p q r )
                    (setq p (cdr (assoc a l))
                          q (cdr (assoc b l))
                          r (angle p q)
                    )
                    (entmake (list '(0 . "LINE") (cons 10 p) (cons 11 q) '(62 . 8)))
                    (text
                        (mapcar '(lambda ( x y ) (/ (+ x y) 2.0)) p q)
                        (itoa c)
                        (if (and (< (* pi 0.5) r) (<= r (* pi 1.5))) (+ r pi) r)
                        2
                    )
                )
                sls tls wgt
            )
        )
        (mapcar 'cons (vl-sort (append sls tls) '<) pts)
    )
)
(defun text ( p s a c )
    (entmake
        (list
           '(0 . "TEXT")
            (cons 10 p)
            (cons 11 p)
            (cons 50 a)
            (cons 01 s)
            (cons 62 c)
           '(40 . 2)
           '(72 . 1)
           '(73 . 2)
        )
    )
)

When the above function is evaluated with the following arguments (where the first argument indicates the coordinates for the seven nodes):

(graph
   '((75 25) (115 45) (90 60) (10 5) (45 0) (45 55) (0 25))
   '( 1  1  1  1  2  2  3  4   4  5  6)
   '( 2  3  4  5  3  6  6  5   7  7  7)
   '(50 10 20 80 90 90 30 20 100 40 60)
)

It will produce the following result in AutoCAD:


If however, you want the weights to be determined by the 2D distance between each of the supplied node coordinates, could might want to consider the following AutoLISP function:

(defun graph ( pts sls tls )
    (   (lambda ( l )
            (foreach x l (text (cdr x) (itoa (car x)) 0.0 1))
            (mapcar
               '(lambda ( a b / p q r )
                    (setq p (cdr (assoc a l))
                          q (cdr (assoc b l))
                          r (angle p q)
                    )
                    (entmake (list '(0 . "LINE") (cons 10 p) (cons 11 q) '(62 . 8)))
                    (text
                        (mapcar '(lambda ( x y ) (/ (+ x y) 2.0)) p q)
                        (rtos (distance p q) 2)
                        (if (and (< (* pi 0.5) r) (<= r (* pi 1.5))) (+ r pi) r)
                        2
                    )
                )
                sls tls
            )
        )
        (mapcar 'cons (vl-sort (append sls tls) '<) pts)
    )
)
(defun text ( p s a c )
    (entmake
        (list
           '(0 . "TEXT")
            (cons 10 p)
            (cons 11 p)
            (cons 50 a)
            (cons 01 s)
            (cons 62 c)
           '(40 . 2)
           '(72 . 1)
           '(73 . 2)
        )
    )
)

Supplied with a list of node coordinates and two lists of connected nodes:

(graph
   '((75 25) (115 45) (90 60) (10 5) (45 0) (45 55) (0 25))
   '(1 1 1 1 2 2 3 4 4 5 6)
   '(2 3 4 5 3 6 6 5 7 7 7)
)

This function will produce the following result:

Here, the accuracy of the weights will be determined by the value of the LUPREC system variable in AutoCAD (which was set to 4 in the above example). You can alternatively override this by supplying the precision argument to the rtos function in my code, e.g. for a precision of 3 decimal places, the expression would be:

(rtos (distance p q) 2 3)