# # Name : GetCentroid 1.0 # Description : Draws a construction point at the centroid of a shape that is # drawn on the X-Y plane (the ground). Also calculates # area and Moments of Inertia of face (Ix, Iy, Ixy) # Usage : 1. Draw shapes on the X-Y (ground) plane and select at least # one face, make sure top of te face is up! # 2. Select "Get Face Centroid" from the Tools menu # 3. A construction point will be placed at the centroid and # the area properties will be displayed # PLEASE NOTE: Since SketchUp approximates curved shapes with # polygons, this calculation will only be as good as the # approximation. To increase accuracy, increase the number # of polygons. # # Author : Alexander Schreyer, www.alexschreyer.net # E-Mail: mail@alexschreyer.net # Date : October 11, 2008 # Type : Tool # Disclaimer: THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE. # # History: 1.0 (10/11/2008) - first version # To-Do List: - Implement translate so that this works on arbitrarily # oriented surfaces # - Get angle of strong axis and draw it. Also get Section # Modulus and radius of gyration # require 'sketchup.rb' # ========================================= def face_selected # Check if face is in selection set - for context menu lookup = false selection_set = Sketchup.active_model.selection selection_set.each {|entity| if entity.typename == "Face" lookup = true end } return lookup end # ========================================= def calculate_centroid (a_face) # Do the math and display the results - returns the centroid # Get all the vertices for the current face vertices = a_face.vertices if (vertices.length < 3) UI.messagebox "Awfully sorry. Can't calculate centroid.\nPlease select at least one valid face." return false else # First calculate centroid: # Loop the first vertex around and create a point for the centroid vertices[vertices.length] = vertices[0] centroid = Geom::Point3d.new a_sum = 0.0 x_sum = 0.0 y_sum = 0.0 for i in (0...vertices.length-1) temp = vertices[i].position.x * vertices[i+1].position.y - vertices[i+1].position.x * vertices[i].position.y a_sum += temp x_sum += (vertices[i+1].position.x + vertices[i].position.x) * temp y_sum += (vertices[i+1].position.y + vertices[i].position.y) * temp end area = a_sum / 2 centroid.x = x_sum / (3 * a_sum) centroid.y = y_sum / (3 * a_sum) centroid.z = 0 # Now calculate moments: adjusted_points_x = [] adjusted_points_y = [] i_x = 0.0 i_y = 0.0 i_xy = 0.0 # Get all the vertices for the current face and wrap the first one again for i in (0...vertices.length) adjusted_points_x[i] = vertices[i].position.x - centroid.x adjusted_points_y[i] = vertices[i].position.y - centroid.y end for i in (0...adjusted_points_x.length-1) j = i+1 temp = 0.5 * (adjusted_points_x[i] * adjusted_points_y[j] - adjusted_points_x[j] * adjusted_points_y[i]); i_x += (adjusted_points_y[i] * adjusted_points_y[i] + adjusted_points_y[i] * adjusted_points_y[j] + adjusted_points_y[j] * adjusted_points_y[j]) / 6 * temp; i_y += (adjusted_points_x[i] * adjusted_points_x[i] + adjusted_points_x[i] * adjusted_points_x[j] + adjusted_points_x[j] * adjusted_points_x[j]) / 6 * temp; i_xy += (2 * adjusted_points_x[i] * adjusted_points_y[i] + adjusted_points_x[i] * adjusted_points_y[j] + adjusted_points_x[j] * adjusted_points_y[i] + 2 * adjusted_points_x[j] * adjusted_points_y[j]) / 12 * temp; end # Show results - better in inputbox, can copy values # if larger than 5 ft^2 go with larger units if (area > 3600) prompts = ["Area (ft^2)", "Ix (ft^4)", "Iy (ft^4)", "Ixy (ft^4)"] values = [sprintf("%.4f",area/144), sprintf("%.4f",i_x/20736), sprintf("%.4f",i_y/20736), sprintf("%.4f",i_xy/20736)] else prompts = ["Area (in^2)", "Ix (in^4)", "Iy (in^4)", "Ixy (in^4)"] values = [sprintf("%.4f",area), sprintf("%.4f",i_x), sprintf("%.4f",i_y), sprintf("%.4f",i_xy)] end inputbox prompts, values, "Face Area Properties" # Send the centroid back as a point return centroid end end # calculate_centroid # ========================================= def get_centroid # Get the active model model = Sketchup.active_model # Get currently selected objects selection_set = model.selection vector = Geom::Vector3d.new if selection_set.empty? UI.messagebox 'Please select at least one face.' else # Do this for each face in the selection set seperately selection_set.each {|entity| if entity.typename == "Face" if entity.normal.samedirection? [0,0,-1] UI.messagebox "I need to flip this face (white side up) for a correct calculation." entity.reverse! end # Calculate centroid centroid = calculate_centroid (entity) # Draw a construction point and axis lines at centroid if (centroid != false) model.entities.add_cpoint(centroid) model.entities.add_cline centroid.offset(X_AXIS, -2.feet), centroid.offset(X_AXIS, 2.feet) model.entities.add_cline centroid.offset(Y_AXIS, -2.feet), centroid.offset(Y_AXIS, 2.feet) end end } end end # get_centroid # ========================================= # Load plugin at startup and add menu items filename = "_GetCentroid.rb" if !file_loaded?(filename) # Add to the SketchUp tools menu tools_menu = UI.menu("Tools") tools_menu.add_item($exStrings.GetString("Get Face Centroid")) { get_centroid } # Add to the context menu UI.add_context_menu_handler do |menu| if( face_selected ) menu.add_separator menu.add_item($exStrings.GetString("Get Face Centroid")) { get_centroid } end end # Let Ruby know we have loaded this file file_loaded(filename) end # =========================================