Count Certain Shapes
-
Hi all,
I have a model that is full of different shapes. I need a function that would only count the number of rectangles with dimensions 100x50. Can someone help me with this? Thanks. -
A few clarifications...
Are the rectangles four edges each or faces or groups or component instances?
If edges/faces are they ever joined together?
Are they arranged so the edges are parallel to the axes?
Is a rectangle 100x50 the same as one 50x100 ?
Are the sizes you gave in inches - i.e. 100" and 50" - or some other units? -
@tig said:
Are the rectangles four edges each or faces or groups or component instances?
Faces. I'll add faces using:
rect = Sketchup.active_model.entities rect.add_face ([x1,y1,0],[x2,y2,0],[x3,y3,0],[x4,y4,0])
@tig said:
If edges/faces are they ever joined together?
No.
@tig said:
Are they arranged so the edges are parallel to the axes?
No. I was actually going to ask if there is a code to change the axes to make it parallel to the rectangles.
@tig said:
Is a rectangle 100x50 the same as one 50x100 ?
Yes, but all rectangles are oriented the same direction. So, if 50x100 then all are 50x100, if 100x50 then all are 100x50.
@tig said:
Are the sizes you gave in inches - i.e. 100" and 50" - or some other units?
It should be inchesI would like to make it inches, but in the code I put above, shouldn't the x's and y's be in pixels.
Thanks TIG -
Working backwards...
Setting points as 'plain numbers' is the same as setting them in inches.
Sketchup's default units are inches.
You only need to worry about other units if you want to use them.There's scant access to the Axes in the API.
You can of course change them manually.To collect faces that have edges 100 and 50 long use something like this.
BUT may I suggest that you change the confusing 'rect' to say 'ents' ??
AND perhaps consider ...model.active_entities
as this allows the code to be called while you are within a group edit etc...faces=[] rect.each{|face| next unless face.is_a?(Sketchup;;Face) next unless face.edges.length==4 faces << face if (face.edges[0].length==50 && face.edges[1].length==100)||(face.edges[1].length==50 && face.edges[0].length==100) }
faces
is now an array of matching faces... -
Thanks for your reply, TIG. I apologize if I wasn't clear.
My program actually draws some rectangles, then the user deletes some of them.
I need to count the number of rectangles left. -
To find that just use
count=faces.length
which returns the number of faces that match the shape pattern.
Obviously you can replace the 100 and 50 with some variables to make a more flexible tool that finds all faces matching those patterns. -
Thanks, TIG. I think I mixed up with the logic of Sketchup.
(1) Does count=faces.length count all faces on the screen OR in the array I made?
(2) If a user deletes a face manually, will it be removed from the array? OR only from the screen?
(3) If the answer to (2) is "only from the screen" does this mean that if I re-draw the array, will the shape that the user deleted get re-drawn?
Thanks, again. -
@michaelazer said:
Thanks, TIG. I think I mixed up with the logic of Sketchup.
(1) Doescount=faces.length
count all faces on the screen OR in the array I made? It's 'faces' in the array you have made - so it counts just the faces that match your pattern.
(2) If a user deletes a face manually, will it be removed from the array? OR only from the screen? When a users erases a face it vanishes from the model's entities collection. If you have made the array of faces before the deletion then the now deleted face is still counted - because the array is a list of faces that matched the pattern at the moment the list was made... You can check for each face's 'validity' before 'counting' thus:
count=0; faces.each{|face|count+=1 if face.valid?}
Now 'count' only includes 'valid' [i.e. NOT-deleted faces.
Again this is dependent on the moment you make the count.
The array 'faces' includes all matching faces at the moment the list is made.
The 'count' is now the number of valid faces within that array [they were check to be 'matching'].
If the user erases another face after the count is made you are again 'out of step'.
Similarly if additional matching faces are added after the matching 'faces' array is compiled the list is incomplete.
It's easy enough to have some code to compile a list of matching faces and count valid ones at various stages of your tool's use, just remember to do it at the appropriate moment to avoid having out of date information in the array or count...]
(3) If the answer to (2) is "only from the screen" does this mean that if I re-draw the array, will the shape that the user deleted get re-drawn?
Thanks, again.The array is only a list of faces that match your pattern. You can't 'redraw the array' as it's a list of references to faces only. If a face is deleted from the model you can no longer access its information as it no longer exists. If you mean 'remake' the array you can just rerun the code (remembering to empty the array first withfaces=[])
, and the new list will no longer include the face that was erased. If you want to remember faces even if they are gone you can make an array of say 'face_points' and later use those to recreate a missing face... this is porbably more complex than you want... for each faceface_points=[]; face.vertices.each{|v|face_points<<v.position}
Advertisement