Face.classify_point - compare results?
-
http://code.google.com/apis/sketchup/docs/ourdoc/face.html#classify_point
The method returns a fixnum. But the docs say:
@unknownuser said:
NOTE: It is important that return value comparisons be made against the symbolic constants (i.e. Sketchup::Face::PointUnknown, Sketchup::Face::PointInside, Sketchup::Face::PointOnVertex, etc.) rather than the absolute integer values as these values may change from one release to the next.
So I should not compare against the fixnum, but against the constant. But how do I do that? I used the example from the Docs and I get the error:
Error: #<NoMethodError: undefined method `equals?' for 1:Fixnum>
Which makes sense. But how do I go about comparing against the "symbolic constant", if the method is not returning the symbolic constant. Thanks!
Chris
-
You are getting an integer value, right? (Not some weird new bug in SU8?)
I always do stuff like this:
case face.classify_point(pt) when Sketchup;;Face;;PointOnVertex # Foo when Sketchup;;Face;;PointOnEdge # Bar end
or
result = face.classify_point(pt) if result == Sketchup;;Face;;PointOnEdge # Foo Bar end
-
Hmm, I'll try those. I think I now undestand the constant notation a little better here. I'll play around with it. Thanks Thom,
Chris
-
Yea Chris.. these constants are known as Class Constants, as opposed to Module Constants or Global Constants.
They are defined within the class definition.
` Sketchup::Face.constants["PointOutside", "PointInside", "PointOnFace", "PointUnknown", "PointOnEdge", "PointNotOnPlane", "PointOnVertex"]`
You access them like you would a Module constant. Note that they should be capitalized, to help Ruby find them instead of looking for a method (which is why it is encouraged that methods begin with a lowercase letter.) But there can be a method of the same name, but for Ruby to find the method instead of the constant, the call must use ().
PointInside
Ruby looks for a constant (if not found, Ruby will raise a NameError. Module, Class and Method Identfiers are themselves constants kept by Ruby internally.)
PointInside()
causes Ruby to make a method call. (If it does not exist, Ruby will raise a NoMethodError, and NOT look for the constant.)Also, (select a face, then in the console):
` f=Sketchup.active_model.selection[0]
f.class.constants["PointOutside", "PointInside", "PointOnFace", "PointUnknown", "PointOnEdge", "PointNotOnPlane", "PointOnVertex"]
f.class::PointInside
1`
~ -
I'm running into some pretty weird problems with the classify_point method. Here's the code I'm running:
puts ii.classify_point(curPoint).to_s if ii.classify_point(curPoint)&8 ...
The value 32 is always sent to the console, yet the if statement executes, even though 32&8 = 0. Can someone help me out with this?
-
@thedro said:
The value 32 is always sent to the console, yet the if statement executes, even though 32&8 = 0. Can someone help me out with this?
It's Ruby!
Only
false
andnil
evaluate to a logical .FALSE., everything else is logical .TRUE.If you want a zero test, use
==0
or.zero?
Ex:
unless (ii.classify_point(curPoint)&8).zero?
or
if not ii.classify_point(curPoint)&8 == 0
or
if ii.classify_point(curPoint)&8 != 0
-
@thedro said:
I'm running into some pretty weird problems with the classify_point method. Here's the code I'm running:
puts ii.classify_point(curPoint).to_s > if ii.classify_point(curPoint)&8 > ...
The value 32 is always sent to the console, yet the if statement executes, even though 32&8 = 0. Can someone help me out with this?
Take note of the description of that method: http://code.google.com/apis/sketchup/docs/ourdoc/face.html#classify_point
Don't use hard-coded numbers, but instead use the provided constants, as the values are different between versions. -
Ok, so what he's doing should read as:
if ii.classify_point(curPoint) & Sketchup::Face::PointOnFace != Sketchup::Face::PointUnknown
-
Or perhaps more transparently the full list from the API is
* 0: Sketchup::Face::PointUnknown (indicates an error), * 1: Sketchup::Face::PointInside (point is on the face, not in a hole), * 2: Sketchup::Face::PointOnVertex (point touches a vertex), * 4: Sketchup::Face::PointOnEdge (point is on an edge), * 16: Sketchup::Face::PointOutside (point outside the face or in a hole), * 32: Sketchup::Face::PointNotOnPlane (point off the face's plane). So you can test for several possibilities by Constant - for 'on the face itself' ...
if ii.classify_point(curPoint)==Sketchup::Face::PointInside
etc...
Or if you wanted it to be only on a vertex you'd use ...
if ii.classify_point(curPoint)==Sketchup::Face::PointOnVertex
etc... -
Correction: the API doc's list is completely foobar...
the proper list [by Brad] is [probably ]- 0: Sketchup::Face::PointUnknown (indicates an error)
- 1: Sketchup::Face::PointInside (point is on the face, not in a hole)
- 2: Sketchup::Face::PointOnEdge (point is on an edge)
- 4: Sketchup::Face::PointOnVertex (point touches a vertex)
- 8: Sketchup::Face::PointOutside (point is outside the face or in a hole)
- 16: Sketchup::Face::PointNotOnPlane (point is off the face's plane) There is no 'PointOnFace' ??
-
@tig said:
Correction: the API doc's list is completely foobar...
the proper list [by Brad] is [probably ]- 0: Sketchup::Face::PointUnknown (indicates an error)
- 1: Sketchup::Face::PointInside (point is on the face, not in a hole)
- 2: Sketchup::Face::PointOnEdge (point is on an edge)
- 4: Sketchup::Face::PointOnVertex (point touches a vertex)
- 8: Sketchup::Face::PointOutside (point is outside the face or in a hole)
- 16: Sketchup::Face::PointNotOnPlane (point is off the face's plane) There is no 'PointOnFace' ??
His list of constants and values is not relevant for SU8M1
-
So... thomthom what IS the list ?
Why the secrecy?
I now think it should be fromSketchup::Face.constants
- which returns
["PointOutside", "PointInside", "PointOnFace", "PointUnknown", "PointOnEdge", "PointNotOnPlane", "PointOnVertex"]
I assume in the order they list here and not related to any 'integer' value they represent I THINK they are now...PointOutside= Outside the outer loop edges of the face, but perhaps still on its plane, BUT does a hole count as 'outside' ?
PointInside= Inside the outer loop edges of the face, but perhaps in a hole so not 'onface' ?
PointOnFace= On the face - different from PointInside - as it cannot be in a hole - it is therefore within all loops ?
PointUnknown= An Error - invalid point
PointOnEdge= On an edge belonging to the face
PointNotOnPlane= A valid point, but it's NOT on the plane of the face
PointOnVertex= On a vertex belonging to the face
This really is a complete mess ! Bitwise was much more logical that f'ing 'constant names' -
I think the list is the one listed in the docs now. There was an old value listed before, which I think where never returned. And SU8M1 introduced a new value.
What appear to have changed in the docs is that before it said that the comparisons had to be done bitwise.
I am a bit confused about best practice myself. I only found out about the constants when they released M1. The info has been sparse and I've been doing a bit of trial and error to get things working. -
You can use the WayBack Machine to see the older versions of the docs:
http://waybackmachine.org/*/http://code.google.com/apis/sketchup/docs/ourdoc/face.html#classify_pointI had basically no info....
Not sure where I got the bitwise comparison from...
-
The current API lists 6 Constants [Brad has 7] BUT the .constants method returns 7 that aren't the same as Brad's 7 so something is wrong soemwhere?? aaargh! My post http://forums.sketchucation.com/viewtopic.php?p=316191#p316191 list what I think might be right [today at least ] ???
-
Cheers TheDro
-
TheDro
Thanks, could you perhaps publish a definitive list in the Face API note explaining which is what and that there is [possibly] an obsolete constant too... Comparing and contrasting with the current text and the Brad's follow up notes too... -
Alright, let's try to put this one to rest . I just tested it with a face on the xy plane with a hole in it and here are the results(and code):
puts "On Face(Inside); " + face.classify_point([0.25,0.25,0]).to_s #1 puts "On Vertex; " + face.classify_point([0,0,0]).to_s #2 puts "On Edge; " + face.classify_point([0.25,0,0]).to_s #4 puts "Outside; " + face.classify_point([-0.5,0,0]).to_s #16 puts "In Hole; " + face.classify_point([0.6,0.6,0]).to_s #16 puts "NotOnPlane; " + face.classify_point([0,0,1]).to_s #32
So this means that whether the point is in a hole or outside the face, the return value is the same (16). I think that answers TIG's question about the matter. The OnFace constant (which is is not in the API nor am I able to choose a point that returns the value. It could therefore be obsolete. If someone can think of another case that I missed, let me know (other than an error (0) of course).
Oh and just a quick note. The return value of the classify_point method will be one of the above values and NOT a sum of multiple values. I mention this because I expected a point on an vertex to return 6 or 7 because a point on a vertex is on the face and an edge at the same time, but this is not the case.
As for how I'll write my code, well there are two ways of doing and I think this would be the shortest way (syntactically) of doing it:
if (face.classify_point(point)&(Sketchup;;Face;;PointInside+Sketchup;;Face;;PointOnVertex+Sketchup;;Face;;PointOnEdge))!=0
As long as those constants remain powers of 2, the code should work although to be safe I might just go with if((p==a) or (p==b) or (p==c)), which doesn't require any bitwise operations (I just find the bitwise way of doing cool since I've come to understand it recently ).
EDIT:
As requested, here is the definitive list of the constants:0: Sketchup::Face::PointUnknown (error)
1: Sketchup::Face::PointInside (somewhere on the face)
2: Skethcup::Face::PointOnVertex (on one of the vertices of the face)
4: Skethcup::Face::PointOnEdge (on one of the edges of the face, vertices do not count since they return 2)
8: Sketchup::Face::PointOnFace (likely obsolete)
16:Sketchup::Face::PointOutside (on plane of the face but not on face; this includes holes)
32:Sketchup::Face::PointNotOnPlane (not on the face's plane)Remember that this is for version 8.0 and that the constants should be used instead of the numerical values for forward compatibility.
-
TheDro has edited the list provided a few posts back with 'all know data'...
Unexpectedly it agrees exactly with the list in the main API -[except for that omitting '8 PointOnFace' as it is obsolete anyway - why is it in the constants still ? Have Google just forgotten to remove it ?]
Brad's list in the API notes is therefore wrong [probably].
I've suggested to TheDro to add another note to the API docs to state what seems to be the correct situation with v8M1 -
I digged in my emails - here's a quote from a Googler:
@unknownuser said:
Here is a comment from our defect database about this issue
"..I learned that the Sketchup::Face::PointOnFace constant is never used, so I just removed it from the docs.."
Advertisement