Масштабирование длин в диаграмме AutoCAD - PullRequest
0 голосов
/ 09 февраля 2020

Это продолжение моего предыдущего поста здесь

У меня 2D-геометрия, созданная с использованием следующего кода, ref .

(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)
        )
    )
)

Ввод:

(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)
)

Результирующее изображение

enter image description here

Из координат, которые даны в качестве входных данных, выше 2D диаграмма создана. Я хочу масштабировать длины в изображении, т.е. длины должны быть кратны скаляру x (x может быть любым значением). скажем, х = 10, длины должны быть масштабированы до 20,0, 30,0, 50,0, 70,0 и так далее. Это приведет к смещению координат точек на стыках.

Любые предложения о том, как реализовать масштабирование в AutoLisp, будут действительно полезны.

1 Ответ

2 голосов
/ 11 февраля 2020

В общем, для этой проблемы просто недостаточно ограничений: для произвольного заданного набора связанных узлов и весов может быть бесконечно много конфигураций, которые удовлетворяли бы входным данным, или вообще не было бы, в зависимости от весов (расстояний)

Например, если вы хотите уменьшить проблему до 2 соединенных узлов с заданным весом:

(graph '(1) '(2) '(10.0))

Исправление положения одного из узлов будет означать, что второй узел может быть расположен в одной из бесконечно многих точек на окружности радиуса 10.0 с центром в первом узле.

Предполагается, что вы выбрали произвольную позицию на этом круге для второй ноты, добавив третий связанный узел затем к первым двум относится решение вопроса о пересечении двух окружностей, радиусы которых равны весам между узлами (то есть, если они даже пересекаются).

Для каждого добавленного последующего узла вам нужно будет найти общее пересечение в наборе кругов с центром в каждом нет de, к которому подключен новый узел, радиусы которого равны весу между узлами.


Конечно, есть чит-решение:

(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 (* 10.0 (atof (rtos (/ (distance p q) 10.0) 2 0))) 2 0)
                        (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)
        )
    )
)

enter image description here

Здесь строка:

(rtos (* 10.0 (atof (rtos (/ (distance p q) 10.0) 2 0))) 2 0)

Округляет расстояние до ближайшего кратного 10, а затем преобразует результат в строку с точностью до нуля после запятой. .

Если вы хотите продолжить использовать этот метод в целом, вы можете определить общую функцию округления, такую ​​как следующая, которая будет округляться до любого предоставленного кратного:

(defun roundto ( x m / d r )
    (setq d (getvar 'dimzin))
    (setvar 'dimzin 8)
    (setq r (rtos (* m (atof (rtos (/ x (float m)) 2 0))) 2 16))
    (setvar 'dimzin d)
    r
)

И Затем вы должны заменить:

(rtos (* 10.0 (atof (rtos (/ (distance p q) 10.0) 2 0))) 2 0)

на:

(roundto (distance p q) 10.0)

Где 10.0 представляет кратное округления.


Следуя вашему вопросу в комментариях, Вы можете использовать следующую функцию для округления до до следующего кратного (с точностью до 1e-8):

(defun roundupto ( x m / d r )
    (setq d (getvar 'dimzin))
    (setvar 'dimzin 8)
    (setq r (rtos (* m (fix (+ 1 -1e-8 (/ x (float m))))) 2 8))
    (setvar 'dimzin d)
    r
)

Например:

_$ (roundupto 12.4 12.4)
"12.4"
_$ (roundupto 12.41 12.4)
"24.8"
_$ (roundupto 29.15 12.4)
"37.2"
...