Faces area in a group ?
-
Hi,
Has anyone ever figured out how to calculate the total area of all the faces that are in a group and this group has been scaled/rotated/moved, etc ?If you do that:
def faces_area(faces) a = 0.0 faces.each do |f| a+=f.area end a end
You'll get the area of the faces BEFORE the group was scaled.
So I tried that (assuming that faces is an array of faces of group.entities):
def faces_area(faces,group_transfo) a = 0.0 faces.each do |f| fv=[] f.vertices.each do |v| fv.push(v.position.transform(group_transfo)) end new_face=Sketchup.active_model.entities.add_face fv a+=new_face.area new_face.erase! end a end
But I got the "Points are not coplanar syndrom".
Any hint anyone ? -
Salut Didier !
Si tu exploses le groupe, calcules l'aire totale, et recompose le group ?
And if you explode group, calculate total area of the faces, and re-create group ?Petit truc pour afficher l'aire totale des face du groupe :
Smt to show the total area of all the faces in a group :def face_area model = Sketchup.active_model n = model.active_entities.count cn = 0 sel = [] group = model.selection[0] group.explode.each do |e| if e.typename == "Face" cn += e.area end end UI.messagebox("\nAire totale des faces du groupe ; " + cn.to_s + "unités") while(n < model.active_entities.count) sel.push(model.active_entities[n]) n += 1 end model.selection.add(model.active_entities.add_group(sel)) end
^^
-
I'd perhaps be best to copy the group inside another group, then explode it and get the areas and then delete the parent group. That way no coincident geometry will be erased and the original is not changed ?
-
Hi TIG!
This is the second time you corrected me on this error! -
TIG, you are my
Merci mate/Matt -
De rien mon initiateur de Ruby
-
Personally, I'd call that a bug in the #area method if it is not taking the scaling factor into consideration.
-
Hi Todd,
You know, groups are almost like component instances, they are stored in the model like "internal definitions" and a group is like an unique occurence of its definition, with or without a transformation applied. This is where the 'group' object in SU is wrong defined IMHO.
It's a shame we can't apply a transformation to a face, this will solve quickly the problem. I've written Face::transform myself, but for some unknown reason it sometimes raises an error "points are not coplanar" when applying the method to the edges of the face. Go figure...PS: great presentation at 3DBC, but perhaps you need a little bit more training with the compo spray ?
-
@AdamB: just let me call you the ruby wizard Voilà, c'est touT !
-
(FWIW I'd say face.area giving objects space area is the correct behaviour.)
But people, this is all the wrong approach. You don't want to be building geometry, you just want to run through each face in the object and scale the area by the transformation. The trick is to project the scaling into the face's basis frame.
So the code in my book is:
def objectsurfacearea(container, xform) total = 0 for ent in container.entities next unless ent.kind_of? Sketchup;;Face # get face basis frame normal = ent.normal binormal = Geom;;Vector3d.new(normal.y,normal.z,normal.x) tangent = (normal * binormal).normalize areascale = (xform * binormal).length * (xform * tangent).length total += ent.area * areascale end return total end
So you'd do:
objectsurfacearea(mygroup, mygroup.transformation)or
objectsurfacearea(myinstance.definition, myinstance.transformation)
Voila! C'est tous.
Adam
-
@didier bur said:
Voilà, c'est touT !
Enfin! Apres vingt ans avec une epouse Francais, plus ca change avec mon Franglais..
-
-
Sweet! Just what I needed.
How does it handle nested scaled groups/components? Do y ou have to add up the total transformation? -
Hey thanks a lot AdamB for your super professional approach!
Finally found what I was looking for, now my code works fantasticly.I did some additional reading about the Frennet-Serret/TNB frame but I don't really understand everything.
If I get it wel, the normal(N) is perpendicular to the face, the tangent(T)'touches' the face and de binormal(B) is perpendicular to both normal and tangent. But then how do you know on which side of the face formed by N and T, is B? I don't get the
@unknownuser said:tangent = (normal * binormal)
multiplication. Isn't B supposed to be the cross product of N and T?
And why is gives
@unknownuser said:(xform * binormal).length * (xform * tangent).length
you the scale factor?
Could you give me some extra matematical information about this?
I would like to understand why this code works,thanks, kat
-
@kat said:
I don't get the
tangent = (normal * binormal)
multiplication. Isn't B supposed to be the cross product of N and T?Makes no odds. Binormal and tangent both lie in the plane.
@kat said:
And why is gives
@adamb said:
(xform * binormal).length * (xform * tangent).length
you the scale factor?
I'm taking the unit vectors in the plane of the face and transforming them by the Group transform which may scale them. Getting the length in the binormal and tangent direction allows me to figure out how much to scale the area of the face accounting for the transform.
Adam
Advertisement