Реклама i
Стань нашим партнером - зарабатывай с нами!
| Правила | Регистрация | Пользователи | Поиск | Сообщения за день | Все разделы прочитаны |  Справка по форуму | Файлообменник |

Вернуться   Форум DWG.RU > Программное обеспечение > AutoCAD > Окружности, касательные к прямой и другой окружности

Окружности, касательные к прямой и другой окружности

Ответ
Поиск в этой теме
Непрочитано 28.02.2007, 12:41 #1
Окружности, касательные к прямой и другой окружности
Хмурый
 
СПб
Регистрация: 29.10.2004
Сообщений: 16,327

Вот здесь
http://www.autocad.ru/cgi-bin/f1/board.cgi?t=33486RV#
Cube спрашивает про это:
Цитата:
Есть окружность R=200, вертикальная прямая на расстоянии 100 слева от центра окружности. Требуется построить окружности R=50, касательные к большой окружности и прямой.

Внешние касательные строятся более-менее ожидаемо, а вот чтобы построить, например, внутреннюю касательную к верхней полуокружности нужно почему-то одной из точек _ttr указывать правый нижний квадрант большой окружности... % — /

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

Где собака зарыта ? Есть какое-то правило для построения внутренних касательных с помощью _ttr кроме перебора ?
Выкладываю картинку, которая может помочь понять. Иначе я об'яснить не смог
[ATTACH]1172655700.jpg[/ATTACH]
Просмотров: 9193
 
Автор темы   Непрочитано 28.02.2007, 12:55
#2
Хмурый


 
Регистрация: 29.10.2004
СПб
Сообщений: 16,327


Забыл написать
Сопрягающие (касательные) окружности строятся командой _circle с опцией Ttr (tan tan radius)
Хмурый вне форума  
 
Непрочитано 28.02.2007, 12:57
#3
Zouss


 
Регистрация: 14.03.2006
Сообщений: 863


давным-давно один мой знакомый менял масло в КПП "Оки"... пробка там порядка 15 мм, расположена низко, а из тары только ведро... поднял он значит ведро повыше, чтоб струйка была потоньше и с расстояния 1,5 м пытался попасть струйкой масла из ведра в бутылочное горлышко, результат понятное дело 50/50

а здесь значит 25/25/25/25 - а почему бы просто не указывать привязки поближе к тому месту где собственно должна в итоге располагаться окружность?
Zouss вне форума  
 
Автор темы   Непрочитано 01.03.2007, 11:35
#4
Хмурый


 
Регистрация: 29.10.2004
СПб
Сообщений: 16,327


Вот ещё вариант в продолжении темы
http://www.autocad.ru/cgi-bin/f1/board.cgi?t=33486RV#
[ATTACH]1172738151.dwg[/ATTACH]
Хмурый вне форума  
 
Непрочитано 01.03.2007, 12:05
#5
Mikhail

инженер-технолог (ГИП)
 
Регистрация: 11.09.2003
Санкт-Петербург
Сообщений: 1,116


а в чем проблема?
В последнем примере три окружности касательные построенны...
Сам такое построил, плюс еще окружность меньшего диаметра в "третем квадранте".
Или просто не понятно как это построить?
просто нужно кликать в нужные части отрезков.
__________________
Большая беда науки в том, что при восхитительной теории можно получить отвратительные результаты.
Mikhail вне форума  
 
Автор темы   Непрочитано 01.03.2007, 12:10
#6
Хмурый


 
Регистрация: 29.10.2004
СПб
Сообщений: 16,327


Mikhail
Проблема в том, чтобы научить Сube'а строить касательные.
Пройди по ссылке

Cube считает, что сорягающие окружности в AutoCAD'е строятся случайным образом. Он не может понять принцип указания сопрягаемых об'ектов.
Хмурый вне форума  
 
Непрочитано 01.03.2007, 14:28
#7
Zouss


 
Регистрация: 14.03.2006
Сообщений: 863


с овалов надо начинать...
кажется сообразил я в чем затык
допустим как-то мы нарисовали касательную окружность внутри большой окружности. теперь обратим внимание на собственно точки касания, точнее на участки A и B (см. прикрепление) так вот если теперь указывать соответствующие привязки на этих участках acad нарисует новую окружность такого-же диаметра снаружи, справедливо полагая что в закрашенном зеленым цветом фигуре она разместиться не сможет
в общем случае вопрос в каком месте окружности указывать касательную привязку, чтоб получить ожидаемый результат, есть вопрос практики, сноровки если хотите... все это идет на уровне подсознания, так что если и выпрыгнет у меня когда-то привязка не туда просто повторю команду с небольшой коррекцией
Но! Никаких вспомогательных построений - сие есть моветон!
[ATTACH]1172748526.dwg[/ATTACH]
Zouss вне форума  
 
Непрочитано 01.03.2007, 15:42
#8
Serge Krasnikov

Конструктор, инженер-механик на пенсии
 
Регистрация: 03.10.2003
Новосибирск
Сообщений: 6,953


Цитата:
Сообщение от Хмурый
Mikhail
Проблема в том, чтобы научить Сube'а строить касательные.
Пройди по ссылке

Cube считает, что сорягающие окружности в AutoCAD'е строятся случайным образом. Он не может понять принцип указания сопрягаемых об'ектов.
Во истину так, Cube не может найти закономерности там где многое делается по ниитии, не задумываясь, хотя кто его знает
ЗЫ. Давно я здесь не был однако
Serge Krasnikov вне форума  
 
Непрочитано 01.03.2007, 17:01
#9
Cube


 
Регистрация: 01.03.2007
хе
Сообщений: 7


Цитата:
Сообщение от Zouss
...справедливо полагая что в закрашенном зеленым цветом фигуре она разместиться не сможет...
А на чём основано "справедливое положение" ? Имхо, оно неверно - я сделал скриншоты, где я делаю привязки вне участков A и B (поместил во вложении)

Цитата:
в общем случае вопрос в каком месте окружности указывать касательную привязку, чтоб получить ожидаемый результат, есть вопрос практики, сноровки если хотите...
Было бы реализовано построение по двум кривым, положению курсора, и радиусу, было бы гораздо удобнее.

Цитата:
Но! Никаких вспомогательных построений - сие есть моветон!
Окружность и прямая - это частный класс случаев.
Как быть, если это будет дуга и отрезок ? Скажем, во втором примере провести прямую (_xline _a 95) через центр сопрягающей окружности, из верхней точки пересечения вертикальной прямой с окружностью отрисовать вертикально вниз отрезок полилинии длиной 8. Большую дугу обрезать, оставив дугу между вертикальной и наклонной прямыми.

Сопрягающая окружность в этот "уголок" вписывается", но как её вписать туда с помощью _circle _ttr без вспомогательных построений ?
[ATTACH]1172758184.rar[/ATTACH]
Cube вне форума  
 
Непрочитано 01.03.2007, 17:24
#10
Zouss


 
Регистрация: 14.03.2006
Сообщений: 863


каюсь - неправильно определил эти самые участки, в прикреплении более верный вариант, который впрочем вы кажется и сами рисовали

так вот - во всех случаях, когда окружность отрисована снаружи, вы указывали касательную к окружности привязку в пределах участка A

а вот про это
Цитата:
Как быть, если это будет дуга и отрезок ? Скажем, во втором примере провести прямую (_xline _a 95) через центр сопрягающей окружности, из верхней точки пересечения вертикальной прямой с окружностью отрисовать вертикально вниз отрезок полилинии длиной 8. Большую дугу обрезать, оставив дугу между вертикальной и наклонной прямыми.
не понял. киньте хоть приблизительный эскизик
[ATTACH]1172760657.dwg[/ATTACH]
Zouss вне форума  
 
Непрочитано 01.03.2007, 18:02
#11
Cube


 
Регистрация: 01.03.2007
хе
Сообщений: 7


Цитата:
приблизительный эскизик
[ATTACH]1172857343.dwg[/ATTACH]

p.s. разве на ttr72.jpg привязка в пределах участка A второй редакции ?
Cube вне форума  
 
Непрочитано 03.03.2007, 14:02
#12
Cube


 
Регистрация: 01.03.2007
хе
Сообщений: 7


Отчаявшись постичь алгоритм работы этой _ttr, соорудил лисп-программку, строящую касательную окружность необходимого радиуса центр которой находится недалеко от текущего положения курсора.
Код:
[Выделить все]
;;; Функция ttrcircle-getcurve
;;; выбор кривой для функции ttrcircle
;;; Аргументы:
;;; нет
(defun ttrcircle-getcurve (msg / ent)
	(setq ent nil)
	(while (not ent)
		(setq ent
			(entsel msg)
		)
		(print)
	)
	(vlax-ename->vla-object
		(car ent)
	)
)

;;; Функция ttrcircle-makeoffset
;;; Создаёт подобный объект на заданном расстоянии
;;; Аргументы:
;;; object - заданный объект (vla-object)
;;; offset - расстояние смещения
;;; Результат:
;;; vla-object или nil, если построить подобный объект невозможно
(defun ttrcircle-makeoffset (object offset / newobject res)
	(setq res
		(vl-catch-all-apply
			'(lambda (object offset)
				(vla-offset object offset)
			)
			(list object offset)
		)
	)
	(if (vl-catch-all-error-p res)
		nil
		(vlax-safearray->list
			(vlax-variant-value res)
		)
	)
)

;;; Функция ttrcircle-intersectwith
;;; Определяет точки пересечения списка объектов
;;; Аргументы:
;;; objlist - список объектов (vla-object)
;;; Результат:
;;; список координат точек пересечения
(defun ttrcircle-intersectwith (objlist / i j res t1)
	(if (atom objlist)
		nil
		(if (null (cdr objlist))
			nil
			(progn
				(setq res nil)
				(foreach i objlist
					(foreach j (cdr (member i objlist))
						(progn
							(setq t1
								(vlax-variant-value
									(vla-intersectwith i j 3)
								)
							)
							(if (>= (vlax-safearray-get-u-bound t1 1) 0)
								(setq res
									(append res (vlax-safearray->list t1))
								)
							)
						)
					)
				)
				res
			)
		)
	)
)

;;; Функция ttrcircle
;;; Создаёт касательную к двум кривым окружность заданного радиуса
;;; Аргументы:
;;; нет
(defun c:ttrcircle ( / curve1 curve2 radius offsets selset intersection pt pt2 d d2 m oldosmode oldcmdecho oldcirclerad)
	(setq oldosmode (getvar 'osmode))
	(setq oldcmdecho (getvar 'cmdecho))
	(setq oldcirclerad (getvar 'circlerad))
	(vl-catch-all-apply
		'(lambda ()
			(setq curve1 (ttrcircle-getcurve "Укажите первую кривую:"))
			(setq curve2 (ttrcircle-getcurve "Укажите вторую кривую:"))
			(if (not ttrcircleradius)
				(setq radius (getreal "Радиус круга: "))
				(progn
					(setq radius
						(getreal
							(strcat
								"Радиус круга <"
								(vl-prin1-to-string ttrcircleradius)
								">: "
							)
						)
					)
					(if (not radius)
						(setq radius ttrcircleradius)
					)
				)
			)
			(setq ttrcircleradius radius)
			(setvar 'osmode 0)
			;;; теперь надо сместить объекты
			(setq offsets
				(append
					(ttrcircle-makeoffset curve1 radius)
					(ttrcircle-makeoffset curve1 (- 0 radius))
					(ttrcircle-makeoffset curve2 radius)
					(ttrcircle-makeoffset curve2 (- 0 radius))
				)
			)
			;;; и найти точки пересечения подобных объектов
			(setq intersection (ttrcircle-intersectwith offsets))
			;;; теперь подобные объекты можно удалить
			(while offsets
				(if (not (null (car offsets)))
					(vla-delete (car offsets))
				)
				(setq offsets (cdr offsets))
			)
			;;; теперь среди точек пересечения нужно найти точку, ближайшую к курсору
			(setq pt2 (cadr (grread 1)))
			(setq d2 nil)
			(setq m (list 'min))
			(while intersection
				(setq pt
					(list
						(car intersection)
						(cadr intersection)
						(caddr intersection)
					)
				)
				(setq d (distance pt pt2))
				(setq m (append m (list d)))
				(setq d2 (append d2 (list d pt)))
				(setq intersection (cdddr intersection))
			)
			(setq m (eval m))
			;;; теперь в списке нужно найти координаты этой точки, и построить окружность
			(setvar 'cmdecho 0)
			(while d2
				(setq d (car d2))
				(setq pt (cadr d2))
				(setq d2 (cddr d2))
				(if (= m d)
					(command "_circle" pt radius)
				)
			)
		)
	)
	(setvar 'osmode oldosmode)
	(setvar 'cmdecho oldcmdecho)
	(setvar 'circlerad oldcirclerad)
	(princ)
)
Теперь просьба к опытным лисп-разработчикам оценить опытным взглядом, показать на недостатки.

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

А ещё, чтобы программа автоматически определяла необходимость применения '3' последним аргументом функции vla-intersectwith, но я не могу сделать свою функцию ttrcircle-intersectwith лучше, чем она есть, т. к. не силён в обработке списков.

Последний раз редактировалось Cube, 24.03.2018 в 16:18.
Cube вне форума  
 
Непрочитано 05.03.2007, 08:27
#13
Cube


 
Регистрация: 01.03.2007
хе
Сообщений: 7


А вот ещё такой вариант - перебор нескольких возможных касательных (правая кнопка/пробел/enter - выбор следующей, чтобы оставить касательную, нужно выбрать её левой кнопкой)
Код:
[Выделить все]
;;; Функция ttrcircle5
;;; Создаёт касательные к двум кривым окружности заданного радиуса
;;; Аргументы:
;;; нет
(defun c:ttrcircle5 ( / curve1 curve2 radius offsets selset intersection pt pt2 d d2 m oldosmode oldcmdecho oldcirclerad)
	(setq oldosmode (getvar 'osmode))
	(setq oldcmdecho (getvar 'cmdecho))
	(setq oldcirclerad (getvar 'circlerad))
	(vl-catch-all-apply
		'(lambda ()
			(setq curve1 (ttrcircle-getcurve "Укажите первую кривую:"))
			(setq curve2 (ttrcircle-getcurve "Укажите вторую кривую:"))
			(if (not ttrcircleradius)
				(setq radius (getreal "Радиус круга: "))
				(progn
					(setq radius
						(getreal
							(strcat
								"Радиус круга <"
								(vl-prin1-to-string ttrcircleradius)
								">: "
							)
						)
					)
					(if (not radius)
						(setq radius ttrcircleradius)
					)
				)
			)
			(setq ttrcircleradius radius)
			(setvar 'osmode 0)
			;;; теперь надо сместить объекты
			(setq offsets
				(append
					(ttrcircle-makeoffset curve1 radius)
					(ttrcircle-makeoffset curve1 (- 0 radius))
					(ttrcircle-makeoffset curve2 radius)
					(ttrcircle-makeoffset curve2 (- 0 radius))
				)
			)
			;;; и найти точки пересечения подобных объектов
			(setq intersection (ttrcircle-intersectwith offsets))
			;;; теперь подобные объекты можно удалить
			(while offsets
				(if (not (null (car offsets)))
					(vla-delete (car offsets))
				)
				(setq offsets (cdr offsets))
			)
			;;; теперь нужно организовать перебор касательных
			(setq pt2 nil)
			(while intersection
				(setq pt
					(list
						(car intersection)
						(cadr intersection)
						(caddr intersection)
					)
				)
				(setq pt2 (append pt2 (list pt)))
				(setq intersection (cdddr intersection))
			)
			(print pt2)
			(while pt2
				(setq pt (car pt2))
				(setq pt2
					(append (cdr pt2) (list pt))
				)
				(command "_circle" pt radius)
				(setq d (entlast))
				(setq d2 (car (entsel)))
				(if (equal d d2)
					(progn
						(setq pt2 (vl-remove pt pt2))
					)
					(progn
						(setq d (vlax-ename->vla-object d))
						(vla-delete d)
					)
				)
			)
		)
	)
	(setvar 'osmode oldosmode)
	(setvar 'cmdecho oldcmdecho)
	(setvar 'circlerad oldcirclerad)
	(princ)
)

Последний раз редактировалось Cube, 24.03.2018 в 16:18.
Cube вне форума  
 
Непрочитано 06.03.2007, 10:16
#14
Cube


 
Регистрация: 01.03.2007
хе
Сообщений: 7


Ещё вариант, при перемещении курсора динамически отрисовывает возможные касательные окружности, центры которых находятся недалеко от курсора. Принять вариант - пробел/enter/левая кнопка, правая кнопка - принять вариант и завершить команду.
Код:
[Выделить все]
;;; Функция ttrcircle-makeoffset
;;; Создаёт подобный объект на заданном расстоянии
;;; Аргументы:
;;; object - заданный объект (vla-object)
;;; offset - расстояние смещения
;;; Результат:
;;; vla-object или nil, если построить подобный объект невозможно
(defun ttrcircle-makeoffset (object offset / newobject res)
	(setq res
		(vl-catch-all-apply
			'(lambda (object offset)
				(vla-offset object offset)
			)
			(list object offset)
		)
	)
	(if (vl-catch-all-error-p res)
		nil
		(vlax-safearray->list
			(vlax-variant-value res)
		)
	)
)

;;; Функция ttrcircle-intersectwith
;;; Определяет точки пересечения списка объектов
;;; Аргументы:
;;; objlist - список объектов (vla-object)
;;; Результат:
;;; список координат точек пересечения
(defun ttrcircle-intersectwith (objlist / i j res t1)
	(if (atom objlist)
		nil
		(if (null (cdr objlist))
			nil
			(progn
				(setq res nil)
				(foreach i objlist
					(foreach j (cdr (member i objlist))
						(progn
							(setq t1
								(vlax-variant-value
									(vla-intersectwith i j 3)
								)
							)
							(if (>= (vlax-safearray-get-u-bound t1 1) 0)
								(setq res
									(append res (vlax-safearray->list t1))
								)
							)
						)
					)
				)
				(setq t1 nil)
				(while res
					(setq i
						(list
							(car res)
							(cadr res)
							(caddr res)
						)
					)
					(setq t1 (append t1 (list i)))
					(setq res (cdddr res))
				)
				t1
			)
		)
	)
)

;;; Функция get-global-variables
;;; Возвращает значения глобальных переменных для последующего восстановления
;;; командой (mapcar 'eval var)
;;; Аргументы:
;;; varnames - список глобальных переменных в формате ("v1" "v2" ...)
;;; Результат:
;;; список значений глобальных переменных в формате ((setvar "v1" vv1) ...)
(defun get-global-variables (varnames)
	(mapcar
		'(lambda (x)
			(list 'setvar x (getvar x))
		) ;;; lambda
		'("osmode" "cmdecho" "circlerad")
	) ;;; mapcar	
)

;;; Функция get-value
;;; Предназначена для выполнения функций getreal, getint
;;; Выводит заданное сообщение, с последующим значением числовой переменной
;;; в угловых скобках (если переменная определена)
;;; Аргументы:
;;; fn - функция, которую необходимо выполнить
;;; msg - неизменяемая часть сообщения
;;; var - переменная, значение которой дополняет сообщение
;;; Результат:
;;; результат выполнения заданной функции fn
;;; Пример использования:
;;; (get-value getreal "Радиус круга:" ttrcirclerad)
;;; если переменная ttrcirclerad не определена, будет выдан запрос
;;; "Радиус круга:", если переменная ttrcirclerad имеет численное значение,
;;; например 20.0, будет выдан запрос "Радиус круга <20.0>:"
(defun get-value (fn msg var / res)
	(setq res
		(fn
			(strcat
				msg
				(if var
					(strcat " <" (rtos var) ">")
					""
				) ;;; if
				": "
			) ;;; strcat
		) ;;; getreal
	) ;;; setq
	(if res res var)
)

;;; Функция ttrcircle6
;;; Создаёт касательные к двум кривым окружности заданного радиуса
;;; Аргументы:
;;; нет
(defun c:ttrcircle6 ( / curve1 curve2 radius offsets selset intersection temp pt pt2 d d2 m oldvars curc)
	;;; сохраняем значения глобальных переменных
	(setq oldvars
		(get-global-variables '("osmode" "circlerad" "cmdecho"))
	) ;;; setq
	(vl-catch-all-apply
		'(lambda ()
			(setq curve1 (ttrcircle-getcurve "Укажите первую кривую:"))
			(setq curve2 (ttrcircle-getcurve "Укажите вторую кривую:"))
			(setq radius
				(get-value getreal "Радиус круга" ttrcircleradius)
			)
			(if (= (setq ttrcircleradius radius) 0) (exit))
			(setvar 'osmode 0)
			;;; теперь надо сместить объекты
			(setq offsets
				(append
					(ttrcircle-makeoffset curve1 radius)
					(ttrcircle-makeoffset curve1 (- 0 radius))
					(ttrcircle-makeoffset curve2 radius)
					(ttrcircle-makeoffset curve2 (- 0 radius))
				)
			)
			;;; и найти точки пересечения подобных объектов
			(setq intersection (ttrcircle-intersectwith offsets))
			;;; теперь подобные объекты можно удалить
			(while offsets
				(if (not (null (car offsets)))
					(vla-delete (car offsets))
				)
				(setq offsets (cdr offsets))
			)
			;;; теперь рисуем окружности с центром недалеко от курсора
			(setq temp nil)
			(setq curc nil)
			(while intersection
				(setq pt2 (grread t))
				(if (= (car pt2) 25)
					(progn
						(setq curc nil)
						(exit)
					)
				)
				(if (and
						curc
						(or
							(= (car pt2) 3)
							(equal pt2 '(2 13))
							(equal pt2 '(2 32))
						)
					)
					(progn
						(setq intersection
							(vl-remove
								(cdr (assoc '10 (entget curc)))
								intersection
							)
						)
						(setq curc nil)
					)
					(progn
						(setq pt2 (cadr pt2))
						(setq d2 nil)
						(setq m (list 'min))
						(setq temp intersection)
						(while temp
							(setq pt (car temp))
							(setq d (distance pt pt2))
							(setq m (append m (list d)))
							(setq d2 (append d2 (list d pt)))
							(setq temp (cdr temp))
						)
						(setq m (eval m))
						;;; теперь в списке нужно найти координаты этой точки, и построить окружность
						(setvar 'cmdecho 0)
						(while d2
							(setq d (car d2))
							(setq pt (cadr d2))
							(setq d2 (cddr d2))
							(if (= m d)
								(progn
									(if (and
											curc
											(not
												(equal
													pt
													(cdr (assoc '10 (entget curc)))
												)
											)
										)
										(setq curc
											(vla-delete
												(vlax-ename->vla-object curc)
											)
										)
									)
									(if curc
										(if (not
												(equal
													pt
													(cdr (assoc '10 (entget curc)))
												)
											)
											(setq curc
												(vla-delete
													(vlax-ename->vla-object curc)
												)
											)
										)
										(progn
											(command "_circle" pt radius)
											(setq curc (entlast))
											(setq pt pt2)
										)
									)
								)
							)
						)
					)
				)
			)
		)
	)
	(if curc
		(vla-delete
			(vlax-ename->vla-object curc)
		)
	)
	;;; восстанавливаем значения глобальных переменных
	(mapcar 'eval oldvars)
	(princ)
)

Последний раз редактировалось Cube, 24.03.2018 в 16:19.
Cube вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > AutoCAD > Окружности, касательные к прямой и другой окружности

Размещение рекламы
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск