Ruby API: face and push/pull direction inconsistent


#1

I’m using a script to draw some solids using faces and push-pull. It appears there is a strange and un-expected corner case behavior. A positive push-pull distance is normally drawn in a positive Z direction (for faces in a plane parallel to the XY plane). But, when the faces is actually in the XY plane (Z=0), that
direction is reversed. I’m guessing the face and back face are swapped.

The following code file demonstrates the behavior. Simply open the Ruby console and load the code from a file. The red cylinder shows the “problem”. Is this intentional ? Does it make sense for some reason ?

=begin rdoc 


================================================================
 SketchUp strange behavior (from Ruby API).

 A cylinder can be drawn by drawing a circlular face, then 
 performing a push/pull to a specific height.  This can all 
 be done from a Ruby script.  But there seems to be an odd
 corner case in the way the API works.  The direction of the 
 face seems to depend upon the Z coordinate of its origin.
 If this coordinate is 0, the direction is reversed.
 ================================================================
=end


=begin rdoc 
 ================================================================
 Method:  cylinder
 
 Creates an empty group in the entities for the active model, 
 then adds cylinder entities to that group.  The cyliinder has
 a vertical axis. 
 
 Arguments: 
   * origin    3dPoint at center of bottom face of cyliner
   * radius    radius of the cylinder 
   * height    height of the cylinder
   * material  color of the cylinder 

 ================================================================
=end


def cylinder( origin, radius, height, material ) 
  group = Sketchup.active_model.entities.add_group 
  entities = group.entities
  up = Geom::Vector3d.new(0,0,1)
  # Call methods on the group's entities collection to draw a 
  # circle perpendicular to the specified axis 
  circle = entities.add_circle origin, up, radius
  face   = entities.add_face( circle )
  face.material      = material  
  face.back_material = material  
  face.pushpull height
  #
  return 
end # method    


=begin rdoc 
 ================================================================
                             Main

                         
 3 identical cylinders are drawn to show how the direction of 
 the push/pull differs when the face is at Z=0. The Red cylinder
 is the oddball.                             
 ================================================================
=end

#
# 3 cylinders will be drawn.  They are parametrically identical
#
radius   =  10                 # radius of all cylinders
height   =  50                 # height of all cylinders

#
# The cylinders are spaced out in the XY plane (they all have 
# vertical axes).  The only difference is the polarity of the
# Z coordinate of the origin.
#
spacing  =  4 * radius         # XY spacing between cylinders 
center  =  [] 
center[0] = Geom::Point3d.new(1*spacing,1*spacing,-10)
center[1] = Geom::Point3d.new(2*spacing,2*spacing,  0)
center[2] = Geom::Point3d.new(3*spacing,3*spacing, 10)

#
# Draw the 3 cylinders
#
cylinder( center[0], radius, height, "Green" ) 
cylinder( center[1], radius, height, "Red" ) 
cylinder( center[2], radius, height, "Green" )

#2

SketchUp perform some exceptions to its rules some times. This include the ground plane. When you draw a face on the ground plane it always face down. And while I don’t have a full overview of all the quirks, I’m not surprised if PushPull also has some.


#3

Thomas, the z=0 quirk is well known among developers, but do you know if it is officially documented anywhere?


#4

As far as I’m aware of, I don’t think it’s mentioned in the API docs anywhere.
It’s a side effect of the underlying push pull tool - not a contract the API declares.


#5

To quibble, it’s a surprise effect of creating any Face at z=0. Push/pull is just an innocent bystander!


#6

I’m certainly not the expert on this, but I have, um, …“history” on my side. I believe it’s because of the typical user pattern: draw a face on z=0, then push-pull in the positive z direction, expecting the style’s front color to be displayed. It wasn’t, and people were having to reverse faces. We saved them the trouble.


#7

Trouble is that this behaviour was exposed to the API - where it’s quite often a noisy obstacle.
Though changing it now would break all kinds of extensions.


#8

True that, though cautious developers learned long ago to test the direction of the normal before doing a push-pull and reverse either the face or the push/pull direction before the operation.


#9

Yea, that is the safe way to do it - but you know people will cry murder if we change it. Optional argument is possible - oh the joy of API clutter due to compatibility.


#10

Thanks to all of you for the explanations. I guess you guys are well aware of this “quirk”. I thought it might be a bug, and am a little surprised to hear that it was intentional. But i have been using the API exclusively, and have hardly any experience using the GUI. So it may in fact be a beneficial work saver.

From my perspective just a clear description of the rules for face reversal in the API would have saved me a lot of time and effort. First i had to debug my bad results down to the API. Then i had to experiment with a ton of cases to figure out what i thought the trigger was. I would suggest this info be added to the docs both under the Face class, and perhaps under Entities.add_face().

Now that you have provided that info i have already solved my problem. I just coded a little operator method to “fix” the face orientation. It grabs the normal vector from the face, and a (the first) vertex. If the Z coordinate of the normal is 1, and the Z coordinate of the vertex is 0, it does a reverse! on the face. I always call the method everywhere i create a face for push-pull. This way i get consistent behavior (up is always up).


#11

I’m creating an issue to improve the Ruby API for add_face to describe this quirk. You’re absolutely correct - if you haven’t been a user of SketchUp you would never have observed this behaviour.


#12

Thanks API-Ites, I thought it was my new computer, OPENGL, …as my fixes to assure no z=0.000000 I am from the school, how could they be wrong after umpteen releases. API is short for APItite, and hunger is needed to secure every victual crumb into its dispensing!