cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - Did you get called away in the middle of writing a post? Don't worry you can find your unfinished post later in the Drafts section of your profile page. X

How to work out length and angle between 2 picked points?

TimSharp
6-Contributor

How to work out length and angle between 2 picked points?

I'm trying to create a little macro that gets the user to click 2 points on the drawing and then draws a bezier curve between the two points. Of course I need to work out all the positions required for the bezier curve: Start point - known Position for first handle - this needs to be worked out relative to the position and angle of the end point. Position for second handle - again needs working out. End Point - known. I'm used to Co Create's ME10 macro language which has functions to work out things such as the length and angle between 2 points so that trig functions can be applied to work out new points relative to known ones. How is this done in Isodraw? Also, how do you prompt the user to pick the start and end points - there is no command line in Isodraw so the only way I've found to do it is to use the message function that required the user to close the message before picking the point, so no use really.
21 REPLIES 21

Though IsoDraw does allow for a lot of functionality through the macro language, it can be a bit length getting to where you need. To get the points from the user
17cfc43dbe
You would likely do this twice, once directly after the first, to allow the selection of the first and then second points. Note that the variables would need to change to say F3 and F4 as to not overwrite your initial coordinates. In regards to prompting, you have only one choice, and that is the message command. I might recommend leaving out the prompt however, as the user likely will assume that selecting the macro Draw_a_bezier (or similar) will prompt for the two points. To determine the math for angles, etcetera, that is not quite as simple as you might hope. I'd recommend the Function section of the macro help from under the menu to get some trig commands.
TimSharp
6-Contributor
(To:thendricks)

Thanks Trevor I've got as far as getting the first and second points OK. The problem I have is working out the relationship between them (length betweeen the points and the angle between them) so that I can apply the trig functions properly.

I was never very good at trig unfortunately. I'd think your starting point would be to X and Y differences. Maybe something along the lines of comparing the points. Check if F1 is greater than F3, if so, F1-F3. Otherwise, F3-F1. Do the same with F2 and F4. That will give you the rise and run of your triangle. You should be able to determine your slope from that. As I said, it's not as simple as what you think. If you are still stuck, give a little more detail, specifically with determining handle locations. I can't promise today, but I can see what I can do with it.

My wife, the math major, was kind enough to put together some basic trig functions. Attached is a cheat sheet that should assist you. For reference, the points you gather (F1, F2, F3, and F4) allow you to determine the X and Y coordinates.
TimSharp
6-Contributor
(To:thendricks)

Thanks Trevor. I think with this information and the invaluable cheat sheet I should be able to get this done. I used to use trig a lot a few years ago but never knew which one to use and when. My main problem is the transition from ME10 macro language to this one - the syntax is so different and there are far fewer commands in Isodraw to help with drawing related macros. Thanks to your wife for the cheat sheet, it will be a very useful reference. If I get this macro done, I'll probably post it here so people can have a giggle at my coding.

Hello gentlemen, I believe this is a further good example for the "user helps user" system. Great work! Tim, can you detail a bit what the use case behind this function is? E.g. do you want to add your own measure function? [Edit: Or what do you need the coordinates and angles for?] Thank you, Christian

I was a full time programmer for ME10 - CoCreate's 2d CAD system for over 10 years and did macros to effectively add new features (to automate standard drawing tasks), so I thought it would be good to do the same with Isodraw. I'm finding it difficult as the structure of the language is so different and the drawing commands don't seem very flexible. I may have been a little sheltered as the ME10 macro language is superb, intuitive and has lots of drawing functions. Anyway, there are some things that Isodraw does not have functions for that we use quite a lot - for example drawing ribbed pipes (takes ages manually). To start off though, I just wanted to do a very simple macro to draw the elliptical shape representing the end of a cut off bar or pipe (don't know if it has a name). The attached .jpg file shows an example of what I'm trying to do. The idea is to just pick 2 points (the ends of the pipe) and the macro works out the angle of the points and draws the ellipses to suit. It doesn't look like you can draw segments of curves (or can you?) so I'm trying to use bezier curves instead, and need to work out the positions to place the handles so the curves look OK.

I believe you are correct in the use of bezier cures. I'd recommend starting with the "Create bezier" command and then adding by using the "Append bezier segment" command. An example is below. I'll see if I can figure it out, but I have to admit that this is a fairly complex endeavor so it might be a bit before I have enough time to work on this. create bezier curve 100 100 150 100 150 200 200 200 append bezier segment 250 200 250 100 300 100 append bezier segment 350 100 350 200 400 200 append bezier segment 450 200 450 100 500 100 A note for Christian, This is a common issue. At this point, we've been manually creating this effect on our end, but a macro would be beneficial.

Hi, thanks for the details, that really sounds interesting. I guess it will be possible but the alignment and length of the anchor points handles might be a bit challenging. Attached a screenshots of the handles as I would set them. You may also create different macros which consider to which direction the cut pipe is open afterwards. Much success, Christian

Thanks for the help. I've finished the bar end macro, though it's a compromise because I didn't have time to work out all the points required with trig functions, so my copout solution draws the shape horizontally, then rotates it to the correct angle. It's perhaps very long winded - maybe other people will advise how to cut the code down - especially where it works out the angle to rotate at the end. Also bear in mind that I don't really understand the syntax of this language so some of my coding might look strange - if anyone has any comments about what I've done wrong, I would appreciate it. One thing I don't understand is that despite having a Select none statement at the end of the macro, the bezier curve remains selected once the macro completes - why? I've attached the working macro below. It's very simple, you just click a start and end point on the drawing and it draws the shape between the 2 points. Hope it's useful - maybe I could do macros for nuts and bolts next. Macro end bar not_in_menu define me as MouseEvent define ppx1 as Point # x value of first user selected point define ppy1 as Point # y value of first user selected point define ppx2 as Point # x value of second user selected point define ppy2 as Point # y value of second user selected point define cpx1 as point # x value of centre point between user selected points define cpy1 as point # y value of centre point between user selected points #get first point me = Wait MouseClick ppx1 = me.ptMMGrid.x ppy1 = me.ptMMGrid.y #get second point me = Wait MouseClick ppx2 = me.ptMMGrid.x ppy2 = me.ptMMGrid.y cpx1 = ((ppx1 + ppx2) / 2) cpy1 = ((ppy1 + ppy2) / 2) #determine X and Y distance between the user selected points define tempx1 as point # x distance between the user selected points define tempy1 as point # y distance between the user selected points if (ppx1 > ppx2) tempx1 = (ppx1 - ppx2) else tempx1 = (ppx2 - ppx1) end if if (ppy1 > ppy2) tempy1 = (ppy1 - ppy2) else tempy1 = (ppy2 - ppy1) end if # determine the distance between the user selected points (hypotenuse) define hyplength as point # the length of the line between the user selected points hyplength = (sqrt ((tempx1 * tempx1) + (tempy1 * tempy1))) # determine the angle between the user selected points define hypangle as point if (tempx1 > tempy1) hypangle = arctan (tempy1 / tempx1) else hypangle = arctan (tempx1 / tempy1) end if # COP OUT SOLUTION IS TO DRAW BEZIER HORIZONTALLY AND THEN ROTATE THE WHOLE THING. define copx2 as point define copy2 as point cpx1 = (ppx1 + (hyplength / 2)) cpy1 = ppy1 copx2 = (ppx1 + hyplength) copy2 = ppy1 define ofp1x as point define ofp1y as point ofp1x = (cpx1 - (hyplength / 16)) ofp1y = (cpy1 + (hyplength / 20)) define ofp2x as point define ofp2y as point ofp2x = (cpx1 + (hyplength / 16)) ofp2y = (cpy1 -(hyplength / 20)) # NEXT DEFINE THE BEZIER CURVE AS AN ELEMENT SO THAT LINE THICKNESSES CAN BE SET define bz1 as element bz1 = create bezier curve ppx1 ppy1 ppx1 (ppy1 + (hyplength / 5)) (ofp2x - (hyplength / 4)) (ofp2y + (hyplength / 4)) ofp2x ofp2y append bezier segment (ofp2x + (hyplength / 6)) (ofp2y - (hyplength / 6)) copx2 (copy2 - (hyplength / 6)) copx2 copy2 append bezier segment copx2 (copy2 + (hyplength / 6)) (ofp1x + (hyplength / 6)) (ofp1y + (hyplength / 6)) ofp1x ofp1y bz1.bezier.segments[1].pen = "Thick" bz1.bezier.segments[2].pen = "Thin" bz1.bezier.segments[3].pen = "Thick" Group Selection # NOW TO DETERMINE THE ANGLE TO ROTATE THE FINISHED BEZIER define ppx_diff as point define ppy_diff as point ppx_diff = (ppx2 - ppx1) ppy_diff = (ppy2 - ppy1) define rotate_angle as point rotate_angle = 0 if (ppx_diff > 0) if (ppy_diff > 0) if (abs (ppx_diff) > abs (ppy_diff)) rotate_angle = ( + hypangle) else rotate_angle = (90 - hypangle) end if else if (abs (ppx_diff) > abs (ppy_diff)) rotate_angle = (- hypangle) else rotate_angle = (-90 + hypangle) end if end if else if (ppy_diff > 0) if (abs (ppx_diff) > abs (ppy_diff)) rotate_angle = (180 - hypangle) else rotate_angle = (90 + hypangle) end if else if (abs (ppx_diff) > abs (ppy_diff)) rotate_angle = (180 + hypangle) else rotate_angle = (-90 - hypangle) end if end if end if Rotate selection ppx1 ppy1 rotate_angle no_Patterns Select none End Macro

OK so I fix up your code above. This code is great but I had spend an hour laying it out in Note++

 

I also added two key features: 1) Select None at the beginning 2) At the end it will copy delete and Paste same_Position then mirror the Pig Tail so if you need the pig upside down or right side up you can simply Undo to the mirrored version of your choice. This is a big help.

 

Macro Pipe End Pig Tail Bologna Slice

	Select none
	define me as MouseEvent
	define ppx1 as Point
# x value of first user selected point
	define ppy1 as Point
# y value of first user selected point
	define ppx2 as Point
# x value of second user selected point
	define ppy2 as Point
# y value of second user selected point
	define cpx1 as point
# x value of centre point between user selected points
	define cpy1 as point
# y value of centre point between user selected points
#get first point
	me = Wait MouseClick
	ppx1 = me.ptMMGrid.x
	ppy1 = me.ptMMGrid.y
#get second point
	me = Wait MouseClick
	ppx2 = me.ptMMGrid.x
	ppy2 = me.ptMMGrid.y
	cpx1 = ((ppx1 + ppx2) / 2)
	cpy1 = ((ppy1 + ppy2) / 2)
#determine X and Y distance between the user selected points
	define tempx1 as point
# x distance between the user selected points
	define tempy1 as point
# y distance between the user selected points
		if (ppx1 > ppx2)
	tempx1 = (ppx1 - ppx2)
			else
	tempx1 = (ppx2 - ppx1)
		end if
		if (ppy1 > ppy2)
	tempy1 = (ppy1 - ppy2)
			else
	tempy1 = (ppy2 - ppy1)
		end if
# determine the distance between the user selected points (hypotenuse)
	define hyplength as point
# the length of the line between the user selected points
	hyplength = (sqrt ((tempx1 * tempx1) + (tempy1 * tempy1)))
# determine the angle between the user selected points
	define hypangle as point
		if (tempx1 > tempy1)
	hypangle = arctan (tempy1 / tempx1)
			else
	hypangle = arctan (tempx1 / tempy1)
		end if
# COP OUT SOLUTION IS TO DRAW BEZIER HORIZONTALLY AND THEN ROTATE THE WHOLE THING.
	define copx2 as point
	define copy2 as point
	cpx1 = (ppx1 + (hyplength / 2))
	cpy1 = ppy1
	copx2 = (ppx1 + hyplength)
	copy2 = ppy1
	define ofp1x as point
	define ofp1y as point
	ofp1x = (cpx1 - (hyplength / 16))
	ofp1y = (cpy1 + (hyplength / 20))
	define ofp2x as point
	define ofp2y as point
	ofp2x = (cpx1 + (hyplength / 16))
	ofp2y = (cpy1 -(hyplength / 20))
# NEXT DEFINE THE BEZIER CURVE AS AN ELEMENT SO THAT LINE THICKNESSES CAN BE SET
	define bz1 as element
	bz1 = create bezier curve ppx1 ppy1 ppx1 (ppy1 + (hyplength / 5)) (ofp2x - (hyplength / 4)) (ofp2y + (hyplength / 4)) ofp2x ofp2y
	append bezier segment (ofp2x + (hyplength / 6)) (ofp2y - (hyplength / 6)) copx2 (copy2 - (hyplength / 6)) copx2 copy2
	append bezier segment copx2 (copy2 + (hyplength / 6)) (ofp1x + (hyplength / 6)) (ofp1y + (hyplength / 6)) ofp1x ofp1y
	bz1.bezier.segments[1].pen = "Medium"
	bz1.bezier.segments[2].pen = "Medium"
	bz1.bezier.segments[3].pen = "Medium"
	Group Selection
# NOW TO DETERMINE THE ANGLE TO ROTATE THE FINISHED BEZIER
	define ppx_diff as point
	define ppy_diff as point
	ppx_diff = (ppx2 - ppx1)
	ppy_diff = (ppy2 - ppy1)
	define rotate_angle as point
	rotate_angle = 0
		if (ppx_diff > 0)
		if (ppy_diff > 0)
		if (abs (ppx_diff) > abs (ppy_diff))
	rotate_angle = ( + hypangle)
			else
	rotate_angle = (90 - hypangle)
		end if
			else
		if (abs (ppx_diff) > abs (ppy_diff))
	rotate_angle = (- hypangle)
			else
	rotate_angle = (-90 + hypangle)
		end if
		end if
			else
		if (ppy_diff > 0)
		if (abs (ppx_diff) > abs (ppy_diff))
	rotate_angle = (180 - hypangle)
			else
	rotate_angle = (90 + hypangle)
		end if
			else
		if (abs (ppx_diff) > abs (ppy_diff))
	rotate_angle = (180 + hypangle)
			else
	rotate_angle = (-90 - hypangle)
		end if
		end if
		end if
	Rotate selection ppx1 ppy1 rotate_angle no_Patterns
	Copy
	Delete selection
	Paste same_Position
	Reflect selection ppx1 ppy1 rotate_angle no_Patterns
	Delete selection
	Paste same_Position
	Select none

End Macro
TimSharp
6-Contributor
(To:BLArts)

Amazing - a reply after over 9 years. Thanks BLArts. That was one of my first useful drawing macros and your enhancement to copy it several times to allow undo levels is very innovative - I relied on the toolbar icon being informative (i.e. showing point 1 and point 2 of a sketch of the shape), so hoping user would get it right first time.

 

I thought I'd tried Select None all over the place with no discernible effect. What does it do at the start?

 

I have lots of other macros to speed up drawing tasks. Maybe I should put some up to see if there is a reaction? A couple of examples:

ribbed pipe - draws a pipe with curved ribs following any bezier curve

scale toolbar - you set a scale point and click scale up or scale down to precisely scale selected geometry

Fixings - draws sets of fixings (either nuts with washers or screws with washers) automatically to correct scale and orientation by one click on the hole they fit into and one click in the general direction to draw them (draws both exploded and fitted fixings in several types and lengths).

 

 

 

Tim,  Yeah LOL 9 years! This is a great macro so thanks. I added the Select none at beginning because if someone forgot they had something selected. The selection gets grouped in with the pig tail if so. 

 

I also have other helpful macros and we could compare them and see what might be helpful to each other. I have one the will scale up or down proportionally that might be similar to yours. We might be able to use parts of each others. Lets touch base if possible. I'm currently trying to use some of your macro to figure out how to determine a lines angle for a macro I would like to create.

 

What would be the best way to do this. I would be open to calling because I can talk faster than I type. Whatever works for you LMK.

Anyone have any idea why this macro does not work on Windows 10? I'm guessing it has something to do with the mouse click event but not sure how to get this to work on Windows 10.

TimSharp
6-Contributor
(To:BLArts)

Hi BLArts. There seems to be a problem with all macros in Windows 10 with mouse click events.

If you click fairly quickly, then there is no problem, but if you wait a few seconds too long, the screen hangs. Sometimes it clears after a while, but other times it requires a restart of Isodraw. It's a severe limitation for macros now and I wish they would fix it - perhaps they don't know about it, though I'm sure I asked support about it when it first happened. 

03.JPG04.JPG

 

I came up with this work around for Windows 10. Instead of using Mouse clicks to determine the points.

 

You first simply draw a polyline using the Line tool between the two anchor points you want your pipe end pigtail on.

 

Then RUN the macro.

 

Remember after macro has run you can Undo once and get the mirrored angle of the pigtail.

 

Macro Any - Pig Tail Bologna Slice PROTECTED

	DEFINE ppx1 AS float
	DEFINE ppy1 AS float
	DEFINE ppx2 AS float
	DEFINE ppy2 AS float
	DEFINE cpx1 AS point
# x value of centre point between user selected points
	DEFINE cpy1 AS point
# y value of centre point between user selected points
#get first point
	ppx1 = activeDoc.firstSelectedElement.line.startPoint.x
	ppy1 = activeDoc.firstSelectedElement.line.startPoint.y
#get second point
	ppx2 = activeDoc.firstSelectedElement.line.segments[1].endPoint.x
	ppy2 = activeDoc.firstSelectedElement.line.segments[1].endPoint.y
	Delete selection
	Select none
	cpx1 = ((ppx1 + ppx2) / 2)
	cpy1 = ((ppy1 + ppy2) / 2)
#determine X and Y distance between the user selected points
	DEFINE dx AS point
# x distance between the user selected points
	DEFINE dy AS point
# y distance between the user selected points
		if (ppx1 > ppx2)
	dx = (ppx1 - ppx2)
			Else
	dx = (ppx2 - ppx1)
		End if
		if (ppy1 > ppy2)
	dy = (ppy1 - ppy2)
			Else
	dy = (ppy2 - ppy1)
		End if
# determine the distance between the user selected points (hypotenuse)
	DEFINE hyplength AS point
# the length of the line between the user selected points
	hyplength = (sqrt ((dx * dx) + (dy * dy)))
# determine the angle between the user selected points
	DEFINE hypangle AS point
		if (dx > dy)
	hypangle = arctan (dy / dx)
			Else
	hypangle = arctan (dx / dy)
		End if
	#Message hypangle
# COP OUT SOLUTION IS TO DRAW BEZIER HORIZONTALLY AND THEN ROTATE THE WHOLE THING.
	DEFINE copx2 AS point
	DEFINE copy2 AS point
	cpx1 = (ppx1 + (hyplength / 2))
	cpy1 = ppy1
	copx2 = (ppx1 + hyplength)
	copy2 = ppy1
	DEFINE ofp1x AS point
	DEFINE ofp1y AS point
	ofp1x = (cpx1 - (hyplength / 16))
	ofp1y = (cpy1 + (hyplength / 20))
	DEFINE ofp2x AS point
	DEFINE ofp2y AS point
	ofp2x = (cpx1 + (hyplength / 16))
	ofp2y = (cpy1 -(hyplength / 20))
# NEXT DEFINE THE BEZIER CURVE AS AN ELEMENT SO THAT LINE THICKNESSES CAN BE SET
	DEFINE bz1 AS element
	bz1 = create bezier curve ppx1 ppy1 ppx1 (ppy1 + (hyplength / 5)) (ofp2x - (hyplength / 4)) (ofp2y + (hyplength / 4)) ofp2x ofp2y
	append bezier segment (ofp2x + (hyplength / 6)) (ofp2y - (hyplength / 6)) copx2 (copy2 - (hyplength / 6)) copx2 copy2
	append bezier segment copx2 (copy2 + (hyplength / 6)) (ofp1x + (hyplength / 6)) (ofp1y + (hyplength / 6)) ofp1x ofp1y
	bz1.bezier.segments[1].pen = "Medium"
	bz1.bezier.segments[2].pen = "Medium"
	bz1.bezier.segments[3].pen = "Medium"
	Group Selection
# NOW TO DETERMINE THE ANGLE TO ROTATE THE FINISHED BEZIER
	DEFINE ppx_diff AS point
	DEFINE ppy_diff AS point
	ppx_diff = (ppx2 - ppx1)
	ppy_diff = (ppy2 - ppy1)
	DEFINE rotate_angle AS point
	rotate_angle = 0
		if (ppx_diff > 0)
		if (ppy_diff > 0)
		if (abs (ppx_diff) > abs (ppy_diff))
	rotate_angle = ( + hypangle)
			Else
	rotate_angle = (90 - hypangle)
		End if
			Else
		if (abs (ppx_diff) > abs (ppy_diff))
	rotate_angle = (- hypangle)
			Else
	rotate_angle = (-90 + hypangle)
		End if
		End if
			Else
		if (ppy_diff > 0)
		if (abs (ppx_diff) > abs (ppy_diff))
	rotate_angle = (180 - hypangle)
			Else
	rotate_angle = (90 + hypangle)
		End if
			Else
		if (abs (ppx_diff) > abs (ppy_diff))
	rotate_angle = (180 + hypangle)
			Else
	rotate_angle = (-90 - hypangle)
		End if
		End if
		End if
	Rotate selection ppx1 ppy1 rotate_angle no_Patterns
	Set active pen "Medium"
	Reflect selection ppx1 ppy1 rotate_angle no_Patterns

End Macro

 

TimSharp
6-Contributor
(To:BLArts)

Sorry I missed this when you posted it. What a good idea.

Thank you! I've been able to come up with some pretty complex macros that help us a lot! There's often one or two workarounds needed due to some bug or conflict.

TimSharp
6-Contributor
(To:BLArts)

Yes same here. I've even done a set of macros that analyse macro useage to give an estimate of how much time the macros save over doing things manually. So far, we've saved over 2200 person hours and that's with me being very conservative with time savings.

That's the way to use the power of automation! Without getting into aspects of the companies we work for and the work we do. I'd love to compare some things we've came up with on developing Macros. I've been able to do much but still have more I'd like to do. Not sure if this is possible but if you're interested maybe we can learn from each other. LMK

TimSharp
6-Contributor
(To:BLArts)

That’s a good idea. Not many people seem to have developed macros for Isodraw, the language isn’t very comprehensive – the lack of a proper of menu system is exasperating.

 

But there is lots of scope for macros that speed things up or do things better. We just have half a dozen icon ‘menus’ around the edges of our screens.

 

Tim

Top Tags