Request for help in developing a new Tool
-
I think view.screen_coords needs the actual position so
view.draw_text view.screen_coords(@ip1.position), "Test0"
should make it work
-
Many thanks for responding.
The Ruby API docs say there should be two parameters to the view.draw_text method - point and text:
point: A Point3d object.
text: The text string to draw.Unfortunately, your suggestion doesn't work, though I can see why it should.
Re-read the API docs for view.draw_text. Finally spotted that it says:
View.draw_text
This method is used to draw text on the screen.
This method is usually invoked within the draw method of a tool.In my previous almost-working tool, I had the code in both places - the onMouseMove, AND in the draw_geometry method. When I put it in the draw method here, and drawgets called, it works. DOH!
(Note to self: RTFM more carefully!)
-
@johnwmcc said:
...This method is usually invoked within the draw method of a tool.
It should say This method is ONLY WORKS when invoked within the draw method of a tool.
I have many a doh! moments with it...
john
-
I'm making progress on this, but I've run into another question.
At one point, I need to find the angle between a vector in the X-Y (red/green) plane and the X_AXIS.
I calculate
# Calculate a vector (vec3) which is the projection of a face.normal onto the red/green plane vec3 = Geom;;Vector3d.new [face.normal.x, face.normal.y, 0] rotate3 = X_AXIS.angle_between vec3
Perhaps naively, I had expected the value of rotate3 to change sign if the direction of vec3 is rotated past the X_AXIS from (say) [1,-1,0] (-45 degrees) through [1,0,0] (0 degrees) to [1,1,0] +45 degrees.
But it doesn't. rotate 3 is always positive.
Is this because in the general case, the angle between two arbitrary vectors doesn't have a 'sense of direction'?
So do I have to distinguish cases where face.normal.y may be positive or negative?
Doing that with an IF statement works.
But is there a more elegant way of calculating this angle, WITH a sign attached?
-
@johnwmcc said:
I'm making progress on this, but I've run into another question.
At one point, I need to find the angle between a vector in the X-Y (red/green) plane and the X_AXIS.
I calculate
> # Calculate a vector (vec3) which is the projection of a face.normal onto the red/green plane > vec3 = Geom;;Vector3d.new [face.normal.x, face.normal.y, 0] > rotate3 = X_AXIS.angle_between vec3 >
Perhaps naively, I had expected the value of rotate3 to change sign if the direction of vec3 is rotated past the X_AXIS from (say) [1,-1,0] (-45 degrees) through [1,0,0] (0 degrees) to [1,1,0] +45 degrees.
But it doesn't. rotate 3 is always positive.the angle will always be positive and between 0 and 180 degrees
Is this because in the general case, the angle between two arbitrary vectors doesn't have a 'sense of direction'?
So do I have to distinguish cases where face.normal.y may be positive or negative?
Yes
Doing that with an IF statement works.But is there a more elegant way of calculating this angle, WITH a sign attached?
No I don't think so. -
Use
vectorC = vectorA.cross(vectorB)
Substituting thevec3
[the 'flat-vector' you've just made] and theX_AXIS
forvectorA
&vectorB
as appropriate***.
if vectorC == face.normal
then the angle is positive; if it is not - i.e. it's==face.normal.reverse
then the angle is negative. I think you should just get a +/-ve Z value difference ?***The order you substitute the two vectors in the 'cross' affects the resultant
vectorC
...
Do some tests to work out which way is which... -
Thanks again, TIG.
-
I thought I'd just got to a working version of this tool, when I discovered a bug in my code that I don't understand, and wonder if anyone can help me figure it out.
I have drawn (using my Draw Framing tool) a component representing a rectangular piece of wood, at an arbitrary angle (though it can also happen at orthogonal angles).
I pick a point on its face from which to start drawing another component, but I find that the reported face.normal vector is along the green axis, not normal to the face.
The image may help to visualize it. The magenta rectangle is generated by the draw_geometry method of my tool, which also draws the face normal along what will become the @long_axis of the about-to-be-created component.
But as you can see in the drawing, instead of being normal to the face, the @long_axis is parallel to the green axis. (By the way, the 3x2 cursor text is the nominal size in inches of the cross section of the component about to be drawn, in case you were wondering.)
The code which finds the face normal is derived from the sample ruby CLineTool:
@ip1.pick view, x, y if( @ip1.valid? ) ... other code... ## Detect if pick point is on a face, and if so, orient long axis normal to it # unless axis is locked if @ip.face f = @ip.face puts "Face picked; normal is \n" puts f.normal.inspect if @@axis_lock == NO_LOCK # axis not locked @long_axis = f.normal puts "@long_axis = " + @long_axis.inspect
This outputs in the Ruby console :
Face picked; normal is Vector3d(0, 1, 0) @long_axis = Vector3d(0, 1, 0)
The code which draws the feedback geometry is:
# Display long axis as visual feedback view.line_width = 2; view.line_stipple = "" view.set_color_from_line(pt1 - @long_axis, pt1 + @long_axis) view.draw_line(@first_pick.position, @first_pick.position + @long_axis) ... view.drawing_color = "magenta" view.draw_polyline(@profile_points)
I find that if I open the component for editing, and copy and paste its top face into the World coordinate system, the face.normal IS normal to this face, which is in the red-blue plane, not at the angle it appears as the top surface of the component.
I'm sure this is because I've originally drawn the far end face of the visible component in the r-g plane (as @profile_points0, which got transformed into @profile_points in the feedback view.draw.polyline above), then did the same transforms on the component face -- rotated it about two different axes and translated it -- then push-pulled it along (its) long_axis to generate the component shown.
Yet (as you can see from the blue highlighted bounding box) the previous component axes are in line with its faces.
In case it helps, I also attach the complete tool draw_framing.rb file.
Any clues as to how to fix this would be most welcome. Until I discovered this 'bug' in my code, I thought I was nearing v1.0 of my code!
So how do I reset the axes of the original face and the component which it becomes, to get a component drawn whose faces AREN'T weirdly distorted internally so as to throw off the apparent face.normal?
I found (before I recoded it this way) that if I first made a group, then a component instance, it didn't have this problem, but its component axes were along world axes, not tightly around the shape of a non-orthogonal component. That is easy to fix manually with a Change Axes command, but there isn't an API function to do the same, afaik.
If anyone knows how to do that, I could revert to that method of creating the component instance.
For example, would it help to explode the component in code, then re-group it and make component?
Or can anyone suggest an alternative approach altogether?
Thanks in advance for any advice I could follow, to work round this.
-
can you utilise
face.bounds.center.normal
where face is the 'new' face???
thinking out loud...
john -
Thanks for the suggestion. Unfortunately, it reports just the same normal as face.normal - off at an angle from the face, but along one axis to which the face is NOT normal geometrically!
I shall look again at the sequence of inserting and transforming the face into the component definition - I'm now pretty sure that the problem lies in the create_geometry method, where I draw the face, insert it into a component definition, then transform it to the required position. Doing that is somehow seriously distorting where the component thinks its face normals point - not normal to the physical face!
-
@johnwmcc said:
Thanks for the suggestion. Unfortunately, it reports just the same normal as face.normal - off at an angle from the face, but along one axis to which the face is NOT normal geometrically!
I shall look again at the sequence of inserting and transforming the face into the component definition - I'm now pretty sure that the problem lies in the create_geometry method, where I draw the face, insert it into a component definition, then transform it to the required position. Doing that is somehow seriously distorting where the component thinks its face normals point - not normal to the physical face!
If you are picking a face in a component or group, the normal will need to be transformed.
@ip1.pick view, x, y if( @ip1.valid? ) ... other code... ## Detect if pick point is on a face, and if so, orient long axis normal to it # unless axis is locked if @ip.face f = @ip.face puts "Face picked; normal is \n" ####### n = @ip.face.normal; t = @ip.transformation; n.transform! t ####### puts f.normal.inspect; n.inspect if @@axis_lock == NO_LOCK # axis not locked @long_axis = f.normal puts "@long_axis = " + @long_axis.inspect
Advertisement