Question about Normal vector
-
Hi everybody,
I'm a beginner in the study sketchup API's.
I don't understand the following behavior: If I test the normal vector of a face before and after a rotation, it does not seem to change.
Here is my code:
ent = Sketchup.active_model.entities face = ent.add_face [0,0,0], [1,0,0], [1,1,0], [0,1,0] face.reverse! face.pushpull 1 group1 = ent.add_group face.all_connected puts face.normal rot=Geom;;Transformation.rotation(Geom;;Point3d.new(0, 0, 0), Geom;;Vector3d.new(0, 1, 0), 30.degrees) ent.transform_entities rot, group1 puts face.normal,"_______________________" group1.entities.each{|e| if e.typename =="Face" puts e.normal end }
and here is the ruby console return:
load "Tests/testnormalvector.rb" (0.0, 0.0, -1.0) (0.0, 0.0, -1.0) _______________________ (0.0, 0.0, -1.0) (0.0, 0.0, 1.0) (0.0, -1.0, 0.0) (1.0, 0.0, 0.0) (0.0, 1.0, 0.0) (-1.0, -0.0, -0.0) true
The normal vector still point to the same direction. If I loop on each faces.normal of my object, the results are the same as if there was no rotation.
Have I missed something?
My goal is to rotate gradually an entity and stop the rotation when the normal vector of a reference face reaches a certain direction.
I'm using Sketchup 7 pro.
Thank you in advance
Gerard
-
First of all - when making groups using the Ruby API you change the order of who you make things.
You make the group first, then add the content:
<span class="syntaxdefault"><br />ent </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">Sketchup</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">active_model</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">entities<br />group1 </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">ent</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">add_group<br /><br />face </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">group1</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">entities</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">add_face</span><span class="syntaxkeyword">( [</span><span class="syntaxdefault">0</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">0</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">0</span><span class="syntaxkeyword">], [</span><span class="syntaxdefault">1</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">0</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">0</span><span class="syntaxkeyword">], [</span><span class="syntaxdefault">1</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">1</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">0</span><span class="syntaxkeyword">], [</span><span class="syntaxdefault">0</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">1</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">0</span><span class="syntaxkeyword">] )<br /></span><span class="syntaxdefault">face</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">reverse</span><span class="syntaxkeyword">!<br /></span><span class="syntaxdefault">face</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">pushpull 1<br /></span>
Grouping existing geometry can lead to problems very easily.
Also, #typename is tertrible slow. Read this for more info: http://www.thomthom.net/thoughts/2011/12/never-ever-use-typename/
If you're new to SketchUp plugin development I also recommend you read this:
http://www.thomthom.net/thoughts/2012/01/golden-rules-of-sketchup-plugin-development/(Still looking at the code and question you asked.)
-
Ah! You're rotating the group itself. The vector you're reading from the face remains contant because within the group itself the face hasn't moved. You get the local coordinate of the face.
If you want the global you need to transform the face normal with the group's transformation as well as the current edit context. http://www.sketchup.com/intl/en/developer/docs/ourdoc/model#edit_transform
More info on instances and definitions in SketchUp:
http://www.thomthom.net/thoughts/2012/02/definitions-and-instances-in-sketchup/ -
You put a face in a group.
It has aface.normal
.
You then rotate the group:
ent.transform_entities(rot, group1)
the group rotates but its contents stay in the same relationship to the group's axes.
The face is still inside the group's context and it's unchanged, so theface.normal
is unchanged, since it's reported relative to the group's axes.
If you rotate the group's contents:
group1.entities.transform_entities(rot, group1.entities.to_a)
Then theface.normal
will change.
You can also get thegroup.transformation
and apply that to theface.normal
, asface.normal.transform!(group.transformation)
etc... You need to decide if you want to transform the group or the face inside it... -
Got it!
I suspected that the problem was that the normal vector's coordinates are expressed relative to the axes of the object.
Thank you for your explanations and your valuable advice.
Gerard
-
if e.is_a?(entity) should work better. Can't put space between certain arguments.
-
if e is_a? Sketchup::Face ==NO ==missing '.'
if e.is_a? Sketchup::Face ==YES
or better
if e.is_a?(Sketchup::Face)
-
Hi guys, I'm trying to find the normal of a face that i have selected in my model I thought something similar to this script shown below might do the trick but alas it hasn't. The ruby console says I have an undefined method e. With my limited ruby brain I though this might be helped by making e = [] or e = 0 which of course it did not. I have used similar script to this below for finding areas. Any help or advice is greatly appreciated. Thanks
<span class="syntaxdefault">model </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">Sketchup</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">active_model<br />ents </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">Sketchup</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">active_model</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">entities<br />sel </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">model</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">selection<br />mat </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">sel</span><span class="syntaxkeyword">[</span><span class="syntaxdefault">0</span><span class="syntaxkeyword">].</span><span class="syntaxdefault">material </span><span class="syntaxcomment"># selected items with material we are interested in<br /></span><span class="syntaxdefault">normal_vector </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">0<br /></span><span class="syntaxcomment"># go through all the entities<br /></span><span class="syntaxdefault">ents</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">each </span><span class="syntaxkeyword">do |</span><span class="syntaxdefault">e</span><span class="syntaxkeyword">|<br />if </span><span class="syntaxdefault">e is_a</span><span class="syntaxkeyword">? </span><span class="syntaxdefault">Sketchup</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">Face </span><span class="syntaxcomment"># if e is a face<br /></span><span class="syntaxkeyword">if </span><span class="syntaxdefault">e</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">material</span><span class="syntaxkeyword">==</span><span class="syntaxdefault">mat </span><span class="syntaxcomment">#if e material is the material of the selected entity<br /><br /># normal equals initial normal vector plus the new normal vector<br />#this returns the normal of the selected face<br /></span><span class="syntaxdefault">normal_vector </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">normal_vector </span><span class="syntaxkeyword">+ </span><span class="syntaxdefault">face</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">normal<br /><br />end </span><span class="syntaxcomment">#end if<br /></span><span class="syntaxdefault">end </span><span class="syntaxcomment">#end if<br /></span><span class="syntaxdefault">end </span><span class="syntaxcomment">#end loop<br /><br /></span><span class="syntaxdefault">puts normal_vector</span>
-
this:
normal_vector = normal_vector + face.normal
will not work as expected, if you set
normal_vector
to reference the integer object0
, because the integer+()
method will get called, and it is not likely that it would know how to handle an argument that references aGeom::Vector3d
object.Smarter to create either a unit vector object to start with, or a zero length vector:
normal_vector = Geom::Vector3d.new(0,0,0)
THEN, when you call the
+()
method using:
normal_vector = normal_vector + face.normal
the special vector addition API method will get called.In other words your statement is evaluated as if it were written:
normal_vector.=( normal_vector.+( face.normal ) )
This is one of the important things about Ruby... = and + (etc,) are not really operators, they are instance method names.
Advertisement