Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Repeat subtracting regions

16 REPLIES 16
SOLVED
Reply
Message 1 of 17
Munozi
1694 Views, 16 Replies

Repeat subtracting regions

Being a newbie in this forum and a rather poor lisper, I am stuck with following problem: I have two partially overlapping regions which I want to rotate or (let 's say) 1 degree, subtract one fromm the other and repeat thet till the circle is full. Background is, i have to replace some ancient gears with pretty oddly shaped teeth.

Attached code doesn't work at all and I 'm unable to track down the error(s).

I hope I can make myself understandable and thank you for your attention, M.

p.s.: I 'm working with Autocad Mechanical 2011

defun C:ABW ( )
(princ "Objekt wählen, von dem subtrahiert werden soll,
\nObjekte dürfen aus nur EINER geschlossenen Linie bestehen: ")
	(setq ss1 nil)
	(setq ss2 nil)
	(setq ss1 (ssget))(command "region" ss1 "")
	(setq ss1 (entlast))
(princ " 2. Objekt wählen: ")
	(setq ss2 (ssget))(command "region" ss2 "")
	(setq ss2 (entget(entlast)))


(setq 	MP1(getpoint " Mittelpunkt 1. Objekt:\n"); midpoint 1. object
		MP2(getpoint "Mittelpunkt 2. Objekt: \n"); midpoint 2. object
		ÜB(getreal " Übersetzung 1 zu...? "); transmission ratio
		Wi(getint "Drehwinkel in Grad: "); rotation angle
)
(repeat Wi

	(command "_rotate" ss1 "" MP1 1)
	(command "_rotate" ss2 "" MP2 (- ÜB))
	(setq ss3 (entmake ss2))
	(command "differenz" ss1 "" (cdr(assoc -1 ss3)) "")
)
)

 

 

16 REPLIES 16
Message 2 of 17
Kent1Cooper
in reply to: Munozi

An illustration would be helpful for me, partly because I'm not familiar with some of the terminology [e.g. transmission ratio] and partly because I don't know German.

 

One thing I notice is that the Wi variable is described as a rotation angle where it is asked for, but then is used in a (repeat) function as the number of times to repeat the series of functions.  It's not used as a rotation angle, at least not in the Rotate commands.

Kent Cooper, AIA
Message 3 of 17
Munozi
in reply to: Kent1Cooper

Hello Kent1Kooper,

I feel honoured by your the fast answer!

forget about those variable names, and right, the rotation angle should be:

(command "_rotate" ss1 "" MP1 wi)

the routine should do:

 

substract gear from circle

create gear anew (because region is lost after subtracting, i think)

rotate circle with the gap from the subtraction clockwise and

rotate gear anticlockwise each for 1 degree

and do all of this 360 times.

 

Aim is to create a counterpart for the gear, so that they are able to mesh.

 

Thanks for your thoughts, i read a lot of your posts, with interest! M

 

 

 

000227.jpg

Message 4 of 17
Kent1Cooper
in reply to: Munozi

If I'm understanding correctly that the Circle to be subtracted from is object #1 and the existing gear shape is #2, this adjustment seems to work, in limited testing [and it's a lot of fun to watch it work! ]:

 

(defun C:ABW (/ ss1 ss2 MP1 MP2 Wi)
  (princ "Objekt wählen, von dem subtrahiert werden soll,
  \nObjekte dürfen aus nur EINER geschlossenen Linie bestehen: ")
;;  (setq ss1 nil); not needed if localized above
;;  (setq ss2 nil); likewise

  (setq ss1 (ssget ":S")); [no Enter required to complete selection]
  (command "region" ss1 "")
  (setq ss1 (entlast))
  (princ " 2. Objekt wählen: ")
  (setq ss2 (ssget ":S"))
  (command "region" ss2 "")
;;  (setq ss2 (entget (entlast))); entity data list
  (setq ss2 (entlast)); Region entity itself instead
  (setq
    MP1 (getpoint "Mittelpunkt 1. Objekt:\n"); midpoint 1. object
    MP2 (getpoint "Mittelpunkt 2. Objekt: \n"); midpoint 2. object
;;    ÜB (getreal " Übersetzung 1 zu...? "); transmission ratio ;; using same rotation angle [negative] as in Wi instead
    Wi (getint "Drehwinkel in Grad: "); rotation angle
  ); setq
  (repeat (/ 360 Wi)
    (command "_rotate" ss1 "" MP1 Wi)
    (command "_rotate" ss2 "" MP2 (- Wi))
;;    (setq ss3 (entmake ss2));; would have been always in original orientation
    (command "_.copy" ss2 "" MP2 MP2); copy to be lost in subtraction, at latest rotation
    (command "_.subtract" ss1 "" (entlast) ""); subtracting the copy
  ); repeat
); defun

 

Some things to consider:

 

You could restrict the object selection to a Circle and a Polyline with (ssget) filtering -- if not, you could use (entsel) instead of (ssget), and spell out your prompt within (entsel) so you're not stuck with (ssget)'s "Select objects: " prompt [always in the plural].  You could have it not proceed unless appropriate things are selected.

 

Since (repeat) requires an integer for the number of times, the angle specified must be evenly divisible into 360 degrees.  If, for example, you entered 7, it would repeat 51 times, and the last "tooth" would probably be incompletely adjusted.

 

Undo begin/end, error handling, command echo suppression, etc.

Kent Cooper, AIA
Message 5 of 17
Munozi
in reply to: Kent1Cooper

Well, Kent1Cooper,

this is very nice indeed! works like a charm and does what i imagined! Thank you a whole lot!

 

Now I will try to understand what you changed and follow your advice restricting selection with entget and the rest.

 

Thanks again, you are a great help!

sincerely M

Message 6 of 17
Kent1Cooper
in reply to: Munozi


@Munozi wrote:

Well, Kent1Cooper,

this is very nice indeed! works like a charm and does what i imagined! Thank you a whole lot!

....


You're welcome, but I realized, in playing with it a little more, that it works well if the two are approximately the same size, so that the "new" gear gets the same number of teeth as the "old" one.  But certainly that's not always the situation.  So I assume your UB variable, separate from your Wi variable, is worth having, and I think I get what "transmission ratio" is now.  Accounting for that makes it more complicated, because if the new one is larger than the old one, the process would need to spin the old one all the way around more than once, and conversely, if it's smaller, less than once around [though going all the way around wouldn't hurt].  And the amount of rotation would of course be calculated separately for each.  But it can probably be accounted for -- I won't dig into that right away, but I'll try some time soon.

Kent Cooper, AIA
Message 7 of 17
Kent1Cooper
in reply to: Kent1Cooper


@Kent1Cooper wrote:
....

.... it works well if the two are approximately the same size, so that the "new" gear gets the same number of teeth as the "old" one.  But certainly that's not always the situation.  So I assume your UB variable, separate from your Wi variable, is worth having, and I think I get what "transmission ratio" is now.  Accounting for that makes it more complicated, ....


Sooner than I expected to, but quickly:

 

(defun C:ABW (/ ss1 ss2 MP1 MP2 UB Wi)
  (princ "Objekt wählen, von dem subtrahiert werden soll,
  \nObjekte dürfen aus nur EINER geschlossenen Linie bestehen: ")
  (setq ss1 (ssget ":S")); new/Circle [no Enter required to complete selection]
  (command "region" ss1 "")
  (setq ss1 (entlast))
  (princ " 2. Objekt wählen: ")
  (setq ss2 (ssget ":S")); existing/gear
  (command "region" ss2 "")
  (setq ss2 (entlast)); Region entity itself
  (setq
    MP1 (getpoint "\nMittelpunkt 1. Objekt:"); midpoint 1. object
    MP2 (getpoint "\nMittelpunkt 2. Objekt:"); midpoint 2. object
    UB (getreal " Ubersetzung 1 zu...? "); transmission ratio [teeth ratio new-to-existing -- I hope that's the right relationship]
    Wi (getint "Drehwinkel in Grad: "); rotation angle [existing]
  ); setq
  (repeat (fix (/ (/ 360 Wi) UB))
    (command
      "_rotate" ss1 "" MP1 (* Wi UB)
      "_rotate" ss2 "" MP2 (- Wi)
      "_.copy" ss2 "" MP2 MP2 ; copy to be lost in subtraction, at latest rotation
      "_.subtract" ss1 "" (entlast) ""
    ); command
  ); repeat
); defun

 

But I have in mind some other improvements, for example, you don't really need to have a Circle to select, but could do it with selection of an existing gear and only the center-point of the new one, and the routine could also find the center of the existing one, assuming it's symmetrical as gears are.  Back later....

 

[I used a U without umlaut in UB, since I don't know how to get one on my English keyboard.]

Kent Cooper, AIA
Message 8 of 17
Munozi
in reply to: Kent1Cooper

Hi Kent1Cooper,

nice thing you wrote!

thinking about your ideas, I changed some parts and got it working for different transmission ratios. Though the  circumferences of the circles have to match. i.e. if ratio is 1:2, the new gear has to have a diamenter 2 times the (outer) diameter of existing gear. Do you see a way to eliminate that, I would be keen to see!

Also there is always one region left, overlaying the existing gear, from where does that come?

Best wishes, have a nice day, here it's early morning and sunny!, M

 

(defun C:ABW (/ ss1 ss2 MP1 MP2 UB Wi)
  (princ "Objekt wählen, von dem subtrahiert werden soll,
  \nObjekte dürfen aus nur EINER geschlossenen Linie bestehen: ")
  (setq ss1 (ssget "_:S")); new/Circle allows to select only one object
  (command "region" ss1 "")
  (setq ss1 (entlast))
  (princ " 2. Objekt wählen: ")
  (setq ss2 (ssget "_:S")); existing/gear
  (command "region" ss2 "")
  (setq ss2 (entlast)); Region entity itself
  (setq
    MP1 (getpoint "\nMittelpunkt 1. Objekt:"); midpoint 1. object
    MP2 (getpoint "\nMittelpunkt 2. Objekt:"); midpoint 2. object
    UB (getreal " Ubersetzung 1 zu...? "); transmission ratio [teeth ratio new-to-existing]
    Wi  360 ;  rotation of new gear will be allways 360 degrees
  ); setq
  (repeat Wi
    (command
      "_rotate" ss1 "" MP1  1 ;new ; one degree steps
      "_rotate" ss2 "" MP2 (-(/ 1 UB))
      "_.copy" ss2 "" MP2 MP2 ; copy to be lost in subtraction, at latest rotation
      "_.subtract" ss1 "" (entlast) ""
    ); command
  ); repeat
); defun

Message 9 of 17
Kent1Cooper
in reply to: Munozi


@Munozi wrote:

..., I changed some parts and got it working for different transmission ratios. Though the  circumferences of the circles have to match. i.e. if ratio is 1:2, the new gear has to have a diamenter 2 times the (outer) diameter of existing gear. Do you see a way to eliminate that, I would be keen to see!

Also there is always one region left, overlaying the existing gear, from where does that come?

....

      "_rotate" ss2 "" MP2 (-(/ 1 UB))
....


One tricky part about the ratio is determining the "circumference," or better, the "effective radius" of a gear-shaped Polyline.  I assume that in true gear configurations, the effective radius is not to the outermost edges of the teeth, but to mid-depth of the teeth, where it meets the same mid-depth effective radius of the other gear.  It's those radii that determine the transmission ratio.  That means that the radius of a selected Circle is not the effective radius of the gear to be made from it, either.  I'll have to think about whether there's a way to calculate that for a gear-outline Polyline.  But the important factor is really the location of the center of the Circle relative to the existing gear; the Circle itself can be bigger than necessary [see another reply of mine coming soon].

 

I don't get the extra Region left over.  Are there actually two Regions, or one Region and one Polyline?  If the latter, you probably have the DELOBJ System Variable set to 0, so the original Polyline remains in the Region command, rather than being deleted.

 

But your latest version doesn't work right without a change, of the line quoted above to:

 

      "_rotate" ss2 "" MP2 (- UB)

 

If the new one is going around once [360 one-degree steps], and if, for example, the ratio of teeth new-to-old [UB] is 2, then the existing gear needs to spin around twice in the same 360 steps, which means 2 degrees per step, or the value of UB directly [but negative to go the other direction from the spin of the new one].

Kent Cooper, AIA
Message 10 of 17
Kent1Cooper
in reply to: Kent1Cooper


@Kent1Cooper wrote:
.... 

But I have in mind some other improvements, for example, you don't really need to have a Circle to select, but could do it with selection of an existing gear and only the center-point of the new one, and the routine could also find the center of the existing one, assuming it's symmetrical as gears are.  Back later....

....


Give this a try.  It works as described above, and in addition, it accepts an existing gear shape if it's a Polyline or if it's already a Region.  [I used different variable names to help me keep track of what's going on, and it's all in English, but you can adjust any of that.]  Like the other approaches, it counts on the User calling for a reasonable transmission ratio -- maybe something could be done to calculate that.  It could still use some other aspects such as Undo begin/end, Osnap control and error handling, etc.....

(defun C:GearMesh (/ gearss ctrnew gearex min max ctrex gearnew ratio rotex rotnew)
  (prompt "\nSelect existing Gear outline Polyline and designate center of new meshing Gear.")
  (if
    (and
      (setq gearss (ssget "_+.:S:L" '((0 . "*POLYLINE,REGION"))))
      (setq ctrnew (getpoint "\nCenter of new gear: "))
    ); and
    (progn ; then
      (if (= (cdr (assoc 0 (entget (ssname gearss 0)))) "REGION"); already one?
        (setq gearex (ssname gearss 0)); then
        (progn ; else
          (command "region" (ssname gearss 0) "")
          (setq gearex (entlast)); Region from existing gear
        ); progn
      ); if
      (vla-getBoundingBox (vlax-ename->vla-object gearex) 'min 'max)
      (setq ctrex
        (mapcar '/ (mapcar '+ (vlax-safearray->list min) (vlax-safearray->list max)) '(2 2 2)); gear center
      ); setq
      (command
        "_.circle" ctrnew ctrex
        "region" (entlast) ""
      ); command
      (setq
        gearnew (entlast); Region from Circle
        ratio (getreal "\nRatio of teeth, new gear to existing: ")
        rotex (getreal "\nPrecision [rotational step on existing gear] in degrees: ")
        rotnew (- (/ rotex ratio))
      ); setq
      (repeat (fix (* (/ 360.0 rotex) ratio))
        (command
          "_rotate" gearnew "" ctrnew rotnew
          "_rotate" gearex "" ctrex rotex
          "_.copy" gearex "" ctrex "@" ; copy to be lost in subtraction, at latest rotation
          "_.subtract" gearnew "" (entlast) ""
        ); command
      ); repeat
    ); progn
    (prompt "\nNot a Polyline, or on a locked Layer, or no gear and/or no center selected.")
  ); if
); defun

 

Kent Cooper, AIA
Message 11 of 17
Munozi
in reply to: Kent1Cooper

Hi, i got your code working, those smileys within ssget confused me at first.

Though it does the same as my former code does, it works only correct if transmisson ratio and number of teeth are divisible without remainder. Otherwise the last teeth will be malformed.  The reason is:

"One tricky part about the ratio is determining the "circumference," or better, the "effective radius" of a gear-shaped Polyline.  I assume that in true gear configurations, the effective radius is not to the outermost edges of the teeth, but to mid-depth of the teeth,...". You wrote. I see you 're thinking into the same direction as me.

The "effective radius" lies in the middle between outer and inner diameter, there the circles have to touch each other and the circumferences must have the same ratio as the transmission. Because they have to roll upon eachother endlessly without slipping.

The new way to create selection is very nice, good idea with that big circle! And undo, osnaps and errorhanling will come later.

Thanks a whole lot for your thoughts! sincerely, M

 

Message 12 of 17
Kent1Cooper
in reply to: Munozi


@Munozi wrote:

..., those smileys within ssget confused me at first.

.... "effective radius" .... 


Pick Preferences near your User name at the upper right, then the Preferences tab within that, the Display heading, and under Emoticon type, pick None.  Then when you're signed in, you won't see any of the smileys that are triggered by colon-and-letter combinations.  We keep asking AutoDesk to get rid of emoticon capability entirely from the site, since they're really not worth having on a site like this, and they can cause the kind of problem you mention, but so far....  [See also this.]

 

I sort of have an idea of how one might determine the effective radius of a gear-shaped Polyline, but I need to work it out.  If it works, then it would be easy to calculate the effective radius of the new one from just its center relative to the existing one, and it could round the number of teeth to the nearest no-remainder multiple, before proceeding.

Kent Cooper, AIA
Message 13 of 17
Kent1Cooper
in reply to: Munozi

By the way, you might be interested in some gear-related Cadalyst CAD Tips:

 

This is the kind of gear in your example;

and

Here is one about bevel gears.

Kent Cooper, AIA
Message 14 of 17
Munozi
in reply to: Kent1Cooper

Dear Kent1Cooper,

I did some tests and your last code works beautiful! Provided that I give it correct conditions, see pic.

 

000228.jpg

It made a nice gear with 14 teeth!

Those smileys should at least really be deactivated by default.

I have seen this spurgear.lsp on Cadalyst. But sometimes I have  a gear with a tooth profile no gear manufacturing machine has ever seen or even dreamed of. Long before everything was standardized they were made with a hammer, a saw, probably some crude measuring tool and a lot of skill.

 

have a nice weekend! M

Message 15 of 17

Hello Kent,

I hope it was okay, but I copied your routine into a lisp to see if I could subtract regions from one another (and yes I had to run the Google German-English translator to see what it was prompting me to do haha). Anyway, I have a routine that I am trying to run using subtract for regions (including using entlast) but to no avail. For some reason I cannot get yours to run on my computer either (I am running Civil3D 2017 for now). Do you know if something has changed? I have another option available to me, but the region/subtract method is by far my preference (if it will work).

Thank you!

CRF

Message 16 of 17


@Yellowjacket98 wrote:

.... I cannot get yours to run on my computer either (I am running Civil3D 2017 for now). Do you know if something has changed? ….


 

I tried it [the code in Message 10] on Acad2016 where I am at the moment, and it worked [after I constructed the gear on the left]:
Gears.PNG

The file format  for my Acad2016 is the same as for your 2017, but I couldn't say what command-related differences there might be [though I can't imagine any that would matter, given the commands the routine uses], nor what effect the Civil3D overlay might have.

 

Does it say it loaded successfully?  What happens when you run it?  Are there any error messages?  Does it do something, but just not what you want, or does it not do anything?  If the former, what's different from what you want it to do?  Etc., etc.

Kent Cooper, AIA
Message 17 of 17

Actually I got it to run this last time; I am not sure what I did before. It was the subtraction item that gave me grief. At one point last evening I just reconstructed my own code and it worked fine. Now I am fighting another situation (ha) with subtracting regions - it works when I do it by hand, but not from my program. I'll keep hacking away at it though.
Thanks for the response and the help!
CRF

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost