sketchucation logo sketchucation
    • Login
    🛣️ Road Profile Builder | Generate roads, curbs and pavements easily Download

    Transform face to a known plane

    Scheduled Pinned Locked Moved Developers' Forum
    15 Posts 5 Posters 1.7k Views 5 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • G Offline
      Garry K
      last edited by

      The face can be rotated on both x and y axis.

      The key part is that rourke has centroid code but it only works on a face that is parallel to the ground.

      What I want to do is transform the points of the face to ground plane, calculate the centroid and then transform the centroid back so it lays on the original face.

      1 Reply Last reply Reply Quote 0
      • sdmitchS Offline
        sdmitch
        last edited by

        @garry k said:

        What I want to do is transform the points of the face to ground plane, calculate the centroid and then transform the centroid back so it lays on the original face.

        Not sure where I found this code but it will calculate the centriod of xyz pts.

        def calc_centroid(f)
         tx=0.0;ty=0.0;tz=0.0;
         p=f.outer_loop.vertices.collect{|v|v.position}
         p.each{|v| tx+=v.x;ty+=v.y;tz+=v.z}
         ax=tx/p.length;ay=ty/p.length;az=tz/p.length
         c=Geom;;Point3d.new(ax,ay,az);#ent.add_cpoint(c)
         area = 0.0;cx = 0.0;cy = 0.0;cz = 0.0;
         for i in 0...p.length
          areat = (p[i].distance(p[i-1])*(c.distance_to_line([p[i],p[i].vector_to(p[i-1])])))/2.0
          area = area + areat;
          cx = cx + areat * ( p[i].x + p[i-1].x + c.x ) / 3.0;
          cy = cy + areat * ( p[i].y + p[i-1].y + c.y ) / 3.0;
          cz = cz + areat * ( p[i].z + p[i-1].z + c.z ) / 3.0;
         end
         cx = cx / area;cy = cy / area;cz = cz / area;
         Geom;;Point3d.new(cx,cy,cz)
        end
        
        
        

        Nothing is worthless, it can always be used as a bad example.

        http://sdmitch.blogspot.com/

        1 Reply Last reply Reply Quote 0
        • G Offline
          Garry K
          last edited by

          Thanks sdmitch

          This indeed produces a centroid on a face.

          I also need to transform the face to ground level. The reason is I will need to do some panel optimization. So I need the shapes on ground level.

          1 Reply Last reply Reply Quote 0
          • jolranJ Offline
            jolran
            last edited by

            Ok missed the the key part in the first post....

            It might be difficult to find a general solution if you want the correct X or Y rotation flat at the ground from a reversed face transformation ? Don't know if anyone found a simple solution to that unless digging in at entity level and comparing angles.
            For a simple rectangle face it might be solvable, but a complex polygon how do you tell which edge or vertice to use for alignment ? It's easier to do with parametric Surface and derivatives 😉

            An alternative might be to use Vector3d.axes, where you form your own axes with the face.normal as Z-axis and use those with your Formulas. Might remove the need to move the face to Origin. Same problem with alignment though but when creating a tempgroup for a faceclone ( you can't move the original 😄 )its Z-axis is not pointing in the face normal direction, so there is quite some work to make the boundingbox aligned so the face is flat on the ground when reversing transformations..

            1 Reply Last reply Reply Quote 0
            • C Offline
              CAUL
              last edited by

              @garry k said:

              I have a face that can be on any plane. I need to transform it so that it is on a specific plane. Does anyone know how to do this.

              In most cases the specific plane will be flat on the ground.

              I think the code below works:

              
              module AlignToNormal
              
                def self.get_alignment_matrix(face_normal, p, plane_normal)
                  return Geom;;Transformation.new if (plane_normal.dot(face_normal)- 1).abs < 0.00000001   
                  cv = face_normal.cross(plane_normal)
                  a = face_normal.angle_between(plane_normal)
                  return Geom;;Transformation.rotation(p, cv, a)
                end
                
                def self.get_centroid(f)
                  c = Geom;;Point3d.new(0, 0, 0)
                  f.outer_loop.vertices.map { |v| v.position }.each { |p| 
                    c.x += p.x ; c.y += p.y; c.z += p.z
                  }
                  div = f.outer_loop.vertices.length
                  c.x = c.x / div; c.y = c.y / div; c.z = c.z / div;
                  return c
                end
              
                def self.main
                  mod = Sketchup.active_model
                  ent = mod.entities
                  sel = mod.selection
                  
                  f = sel.grep(Sketchup;;Face)[0]
                  centroid = get_centroid(f)
                  m = get_alignment_matrix(f.normal, centroid, Geom;;Vector3d.new(1, 1, 1).normalize!)
                  ent.transform_entities(m, f)
                end
                
                main
              end
              
              
              
              1 Reply Last reply Reply Quote 0
              • jolranJ Offline
                jolran
                last edited by

                That's nice but..

                @unknownuser said:

                I also need to transform the face to ground level. The reason is I will need to do some panel optimization. So I need the shapes on ground level.

                I gather this information as he actually DO want the face to the ground to do something with it there. Maybe I'm wrong this time as well.

                Edit, sorry missed the part in the code where one can edit the plane. Your code seams to work for the purpose of getting the plane correct!

                1 Reply Last reply Reply Quote 0
                • C Offline
                  CAUL
                  last edited by

                  @jolran said:

                  I gather this information as he actually DO want the face to the ground to do something with it there. Maybe I'm wrong this time as well.

                  You can concatenate transformations with multplication:

                  
                  align = get_alignment_matrix(face_normal, centroid, plane_normal)
                  translate = Geom;;Transformation.translation(to_point - centroid)
                  align_and_translate = translate * align
                  ent.transform_entities(align_and_translate, f)
                  
                  
                  1 Reply Last reply Reply Quote 0
                  • G Offline
                    Garry K
                    last edited by

                    Thanks guys - I've adjusted Caul's code and I can now get everything working the way I want.

                    1 Reply Last reply Reply Quote 0
                    • G Offline
                      Garry K
                      last edited by

                      The plane is rotated from the ground plane on all axis.

                      1 Reply Last reply Reply Quote 0
                      • fredo6F Offline
                        fredo6
                        last edited by

                        Usually, you achieve this with Geom::Transformation.axes.

                        In your case, assuming the face is at top level of the model:

                        
                        tr_axe_inv = Geom;;Transformation.axes(face.vertices[0].position, *(face.normal.axes)).inverse
                        
                        

                        tr_axe_inv is the transformation to be used for the projection.

                        Fredo

                        1 Reply Last reply Reply Quote 0
                        • G Offline
                          Garry K
                          last edited by

                          Thanks Fredo,

                          Seems like there is always something new to learn !!

                          1 Reply Last reply Reply Quote 0
                          • fredo6F Offline
                            fredo6
                            last edited by

                            This projects the face on the XY plane, with vertex 0 at Origin.

                            If you wish to project to another plane, say with [pt2, normal2], use an additional direct Axe transformation.

                            Fredo

                            1 Reply Last reply Reply Quote 0
                            • C Offline
                              CAUL
                              last edited by

                              @fredo6 said:

                              
                              > tr_axe_inv = Geom;;Transformation.axes(face.vertices[0].position, *(face.normal.axes)).inverse
                              > 
                              

                              Neat! Just saved fifteen lines of code in a script...

                              1 Reply Last reply Reply Quote 0
                              • 1 / 1
                              • First post
                                Last post
                              Buy SketchPlus
                              Buy SUbD
                              Buy WrapR
                              Buy eBook
                              Buy Modelur
                              Buy Vertex Tools
                              Buy SketchCuisine
                              Buy FormFonts

                              Advertisement