sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    Trimming a Solid Group

    Scheduled Pinned Locked Moved Developers' Forum
    12 Posts 2 Posters 1.4k Views 2 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.
    • sdmitchS Offline
      sdmitch
      last edited by

      @medeek said:

      My next problem to solve is how to delete all of the entities (edges, faces) that are on one side or the other side of a plane. I can easily enough collect all of the entities in a (solid) group but I'm not seeing a way to select only the entities of a group that are on side of the bisecting plane.

      This trims all edges on the backside of the face

      mod = Sketchup.active_model
      ent = mod.active_entities
      fac = ent.grep(Sketchup;;Face)[0]
      grp = ent.grep(Sketchup;;Group)[0]
      ge = grp.entities; gt = grp.transformation
      ge.intersect_with(true,gt,ge,gt,false,fac)
      vts = ge.grep(Sketchup;;Edge).map{|e|e.vertices}.flatten.uniq
      nrm = fac.normal; pln = fac.plane; remove = []
      vts.each{|v|
       vp=v.position.transform(gt)
       next if vp.on_plane?(pln)
       next if vp.project_to_plane(pln).vector_to(vp).samedirection?(nrm)
       remove << v.edges
      }
      remove.flatten!.uniq!.reverse!
      ent.erase_entities(remove)
      

      erase backside.gif

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

      http://sdmitch.blogspot.com/

      1 Reply Last reply Reply Quote 0
      • medeekM Offline
        medeek
        last edited by

        Started working on this problem in earnest tonight. I've got the tool selecting the plane and then selecting the correct entity if it is a solid group or component. It then finds all of the edges (lines) that intersect this cutting plane and stores them in an array. However this is not quite good enough I need to determine if the intersection point of the line (edge) and plane actually falls on the edge itself (between the two vertices that make up the edge). If it does not then the plane does not cut through the edge and I can safely ignore it. I appreciate everyone's help thus far.

        Nathaniel P. Wilkerson PE
        Medeek Engineering Inc
        design.medeek.com

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

          @medeek said:

          Started working on this problem in earnest tonight. I've got the tool selecting the plane and then selecting the correct entity if it is a solid group or component. It then finds all of the edges (lines) that intersect this cutting plane and stores them in an array. However this is not quite good enough I need to determine if the intersection point of the line (edge) and plane actually falls on the edge itself (between the two vertices that make up the edge). If it does not then the plane does not cut through the edge and I can safely ignore it. I appreciate everyone's help thus far.

          Compute the intersection point of the edge and the plane then test to verify the the point lies on the edge and the face.

          mod = Sketchup.active_model
          ent = mod.active_entities
          sel = mod.selection
          vue = mod.active_view
          edg = sel.grep(Sketchup;;Edge)[0]
          fac = sel.grep(Sketchup;;Face)[0]
          ip = Geom.intersect_line_plane(edg.line,fac.plane)
          if edg.bounds.contains?(ip)&&[1,2,4].include?(fac.classify_point(ip))
           puts 'Trim this edge'
          end
          
          

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

          http://sdmitch.blogspot.com/

          1 Reply Last reply Reply Quote 0
          • medeekM Offline
            medeek
            last edited by

            @Sdmitch

            Your first block of code has me intrigued. I've been testing the intersect method which I did not know existed. It definitely has some potential. I am having a couple problems with it though.

            1.) The intersecting member may not intersect with the face itself but intersects with the plane defined by the face. How do I specify the plane and not the face with this function (intersect_with).

            2.) Most of the time the group (solid) that I am intersecting with the plane is nested within another component and then that component is inside of another group. Testing my script with an un-nested group works fine but if its nested it does not work. There is probably a simple work around for this, just need to figure it out.

            Nathaniel P. Wilkerson PE
            Medeek Engineering Inc
            design.medeek.com

            1 Reply Last reply Reply Quote 0
            • medeekM Offline
              medeek
              last edited by

              Here is the current tool in its entirety. At this point it kind of works. I've got some debugging code embedded in the mix so don't let that confuse you:

              module TrimTools
              
              
              # --------  MINOR ROOF POSITIONING TOOL  ------------------------------------------------
              
              # Positions the minor roof assembly. This tool allows the user
              # to place the assembly using the mouse to select two
              # corners of the structure. Choose the following corners in order;
              #    left front
              #    right front
              #    
              # Note that the corners should be the corners of the bearing walls not the corners
              # of the roof at the overhangs. 
              
              
              
              class PlaneSelectionTool
              
              	include Math
              
              	#  these are the states that a tool can be in
              	STATE_EDIT = 0 if not defined? STATE_EDIT
              	STATE_PICK = 1 if not defined? STATE_PICK
              	STATE_PICK_NEXT = 2 if not defined? STATE_PICK_NEXT
              	STATE_PICK_LAST = 3 if not defined? STATE_PICK_LAST
              	STATE_MOVING = 4 if not defined? STATE_MOVING
              	STATE_SELECT = 5 if not defined? STATE_SELECT
                 
              
              def initialize(licensemode)
              
              	@Licensemode = licensemode
              	@tool_name = "TRIM TOOL"
              	@type = "trim tool"
              	
              end
              
              def reset
                  	@pts = []
                  	@state = STATE_PICK
              	
                  	# This sets the label for the VCB
                  	Sketchup;;set_status_text "MEDEEK TOOLS", SB_VCB_LABEL
                  	Sketchup;;set_status_text "[#{@tool_name}] Click Trimming Plane"
                  	@drawn = false
              
              end
              
              def activate
                  	@ip1 = Sketchup;;InputPoint.new
                  	@ip = Sketchup;;InputPoint.new
                  	self.reset
              end
              
              def deactivate(view)
              	view.invalidate if @drawn
              	@ip1 = nil
              	
              end
              
              
              
              def get_member(x, y, view)
              
              	model = Sketchup.active_model
               	view = model.active_view
              	entities = model.active_entities
              
              	ph2 = view.pick_helper
               	ph2.do_pick(x, y)
              
              	# Iterate all pick-routes;
               	ph2.count.times { |pick_path_index|
              		@Pickdepth2 = ph2.depth_at(pick_path_index)
              		@Pickpath2 = ph2.path_at(pick_path_index)
              		@TRroof2 = ph2.transformation_at(pick_path_index)
               	}
              
              	@pickcount2 = ph2.count
              	best_entity = ph2.best_picked
              	# puts "Plane Trans; #{@TRroof2} Pick Depth; #{@Pickdepth2} Pick Path; #{@Pickpath2}"
              	# puts "Pick Count; #{@pickcount2} Best Entity; #{best_entity}"
              	
              	if @Pickpath2.nil?
              		# Do nothing
              	else
              		pathsize2 = @Pickpath2.size - 1
              	
              		for step in 0..pathsize2
              			entityi = @Pickpath2[step]
              			typei = entityi.typename
              			if (typei == "ComponentInstance") || (typei == "Group")
              				definitioni = entityi.definition
              				namei = definitioni.name
              				manifoldi = entityi.manifold?
              				
              				# puts "#{step} #{entityi} Type; #{typei} Name; #{namei} Definition; #{definitioni} Manifold; #{manifoldi}"
              
              				if manifoldi
              
              					# Selects Group or Component Instance that is a solid
              
              					p0x = @pts[0].x.to_f
              					p0y = @pts[0].y.to_f
              					p0z = @pts[0].z.to_f
              
              					p1x = @pts[1].x.to_f
              					p1y = @pts[1].y.to_f
              					p1z = @pts[1].z.to_f
              					
              					puts "P0; #{p0x} #{p0y} #{p0z} P1; #{p1x} #{p1y} #{p1z}"
              
              					@group_entities = entityi.entities
              					@group_trans = entityi.transformation
              
              					# puts @group_entities
              
              					@Intersectpoints = []
              					@Intersectpoints2 = []
              					@Newfacepoints = []
              					@Newfacepoints2 = []
              					@Interents = []
              					counter0 = 0
              					counter1 = 0
              					
              					#  Checks each entity (edge) in group to see if it intersects with trimming plane
              
              					@group_entities.each do |ent|
              						if ent.typename == "Edge"
              							line = ent.line
              							intersect_point = Geom.intersect_line_plane(line, @trim_plane)
              
              							if intersect_point
              					
              								# puts  "Intersect point detected at #{intersect_point}"
              								@Intersectpoints[counter0] = intersect_point
              								@Intersectpoints2[counter0] = intersect_point.transform @TRroof2
              
              								counter0 = counter0 + 1
              	
              								# Checks that intersection point is within bounds of edge
              								
              								usedbyedge = ent.bounds.contains?(intersect_point)
              								
              								if usedbyedge
              									@Newfacepoints[counter1] = intersect_point
              									@Interents[counter1] = ent
              									@Newfacepoints2[counter1] = intersect_point.transform @TRroof2
              									
              									counter1 = counter1 + 1
              								end
              							end
              						end
              					end
              
              					# puts @Newfacepoints
              					# puts @Interents
              
              					if @Newfacepoints.empty?
              						UI.messagebox ("Member does not intersect trimming plane, click OK to proceed.")
              						Sketchup.active_model.select_tool(nil)
              					else
              
              						# new_face1 = @group_entities.add_face @Newfacepoints
              						# @group_entities.intersect_with(true, @group_trans, @group_entities, @group_trans, false, @member_face)
              						@group_entities.intersect_with(true, @TRroof2, @group_entities, @TRroof2, false, @member_face)
              	
              						# Remove edges on other side of plane
              
              						vts = @group_entities.grep(Sketchup;;Edge).map{|e|e.vertices}.flatten.uniq
              						nrm = @member_face.normal
              						pln = @member_face.plane 
              						remove = []
              
              						vts.each{|v|
               							# vp= v.position.transform(@group_trans)
               							vp= v.position.transform(@TRroof2)
               							next if vp.on_plane?(pln)
               							next if vp.project_to_plane(pln).vector_to(vp).samedirection?(nrm)
               							remove << v.edges
              						}
              
              						remove.flatten!.uniq!.reverse!
              						entities.erase_entities(remove)
              					end
              
              					break
              				end
              				
              			else
              				definitioni = "Not Defined"
              				namei = "Not Defined"
              				manifoldi = "Not Defined"
              
              				# puts "#{step} #{entityi} Type; #{typei} Name; #{namei} Definition; #{definitioni} Manifold; #{manifoldi}"
              			end
              
              
              			
              		end
              	end
              end
              
              
              
              def get_plane(x, y, view)
              
              	model = Sketchup.active_model
               	view = model.active_view
              
              	ph = view.pick_helper
               	ph.do_pick(x, y)
              
              	# Iterate all pick-routes;
               	ph.count.times { |pick_path_index|
                 		# puts ph.transformation_at(pick_path_index)
              		@TRroof = ph.transformation_at(pick_path_index)
              		@Pickdepth = ph.depth_at(pick_path_index)
               	}
              
              	# UI.messagebox ("Plane Trans; #{@TRroof} \n Pick Depth; #{@Pickdepth}")
              	# best_entity = ph.best_picked
              
               	@member_face = ph.picked_face
              	@face_vertices = @member_face.vertices
              
              	# trim_plane = @member_face.plane
              
              	@Vertices = []
              
              	counter = 0
              	for xi in @face_vertices
              		vertexi = @face_vertices[counter].position
              		@Vertices[counter] = vertexi.transform @TRroof
              		counter = counter + 1
              	end
              
              	@trim_plane = Geom.fit_plane_to_points(@Vertices[0], @Vertices[1], @Vertices[2])
              
              	# puts @member_face
              	# puts counter
              	# puts @Vertices
              	puts @trim_plane
              
              
              
              
              end
              
              
              
              def set_current_point(x, y, view)
                  if (!@ip.pick(view, x, y, @ip1))
                      return false
                  end
                  need_draw = true
                  
                  # Set the tooltip that will be displayed
                  view.tooltip = @ip.tooltip
                      
                  # Compute points
                  case @state
                  when STATE_PICK
                      @pts[0] = @ip.position
                      need_draw = @ip.display? || @drawn
                  when STATE_PICK_NEXT
              	@pts[1] = @ip.position
                  end   
              
                  view.invalidate if need_draw
              end
              
              
              
              def onMouseMove(flags, x, y, view)
              	self.set_current_point(x, y, view)
              end
              
              
              def update_state
                  case @state
                  when STATE_PICK
                      @ip1.copy! @ip
                      Sketchup;;set_status_text "[#{@tool_name}] Click entity you wish to trim"
                      @state = STATE_PICK_NEXT
                  when STATE_PICK_NEXT
                    	# @ip1.clear
              	Sketchup;;set_status_text "[#{@tool_name}] Trimming entity"
              	@state = STATE_PICK_LAST
                  when STATE_PICK_LAST
                      Sketchup.active_model.select_tool(nil)
                  end
              end
              
              def onLButtonDown(flags, x, y, view)
              
                  	case @state
                  	when STATE_PICK
              		self.set_current_point(x, y, view)
              		self.get_plane(x, y, view)
              		self.update_state
              	when STATE_PICK_NEXT
              		self.set_current_point(x, y, view)
              		self.get_member(x, y, view)
              		self.update_state
              	when STATE_PICK_LAST
              		self.update_state
              	end
              end
              
              def onCancel(flag, view)
                  view.invalidate if @drawn
                  reset
              end
              
              
              def draw(view)
                  @drawn = false
                  
                  # Show the current input point
                  if( @ip.valid? && @ip.display? )
                      @ip.draw(view)
                      @drawn = true
                  end
              
                  case @state
                  when STATE_PICK
              	# Do Nothing	
                  when STATE_PICK_NEXT
              	view.drawing_color = [0, 200, 0]
              	view.line_width = 5
              	view.draw(GL_LINE_LOOP, @Vertices)
              
                      @drawn = true
                 when STATE_PICK_LAST
              	
              	view.draw_points(@Intersectpoints2, 10, 4, "red")
              	view.draw_points(@Newfacepoints2, 12, 3, "blue")
                      @drawn = true
                  else
                      #do nothing
                  end
              end
              
              end # class Tool
              

              Nathaniel P. Wilkerson PE
              Medeek Engineering Inc
              design.medeek.com

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

                @medeek said:

                @Sdmitch

                Your first block of code has me intrigued. I've been testing the intersect method which I did not know existed. It definitely has some potential. I am having a couple problems with it though.

                1.) The intersecting member may not intersect with the face itself but intersects with the plane defined by the face. How do I specify the plane and not the face with this function (intersect_with).

                intersect_with only works with entities. You could create a large temporary face that matches the plane.

                2.) Most of the time the group (solid) that I am intersecting with the plane is nested within another component and then that component is inside of another group. Testing my script with an un-nested group works fine but if its nested it does not work. There is probably a simple work around for this, just need to figure it out.

                Handling embedded groups and component instances is very tricky. You will need to combine the local transformation with all of the 'above' transformations to get to the real world position.

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

                http://sdmitch.blogspot.com/

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

                  @medeek said:

                  Here is the current tool in its entirety. At this point it kind of works.

                  How does it fail?

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

                  http://sdmitch.blogspot.com/

                  1 Reply Last reply Reply Quote 0
                  • medeekM Offline
                    medeek
                    last edited by

                    The temporary face seems to do the trick. I've only have two main issues left.

                    1. Nested groups is causing me grief and sometimes the tool cannot detect the intersection. I need to dig into this further.

                    2. The intersect routine works great but how do I get it to draw a face where it created the edges so that the solid is reclosed when trimmed?

                    Nathaniel P. Wilkerson PE
                    Medeek Engineering Inc
                    design.medeek.com

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

                      @medeek said:

                      The temporary face seems to do the trick. I've only have two main issues left.

                      1. Nested groups is causing me grief and sometimes the tool cannot detect the intersection. I need to dig into this further.

                      2. The intersect routine works great but how do I get it to draw a face where it created the edges so that the solid is reclosed when trimmed?

                      1. Here is an example of how I solve the problem of nested components/groups
                      def recurse(ents,tran)
                       ents.each{|e|
                        if ["ComponentInstance","Group"].include?(e.typename)
                         ee = e.typename=="Group" ? e.entities ; e.definition.entities; 
                         if ee.grep(Sketchup;;ComponentInstance) || ee.grep(Sketchup;;Group)
                          tr = tran * e.transformation; recurse(ee,tr)
                         end
                        end
                       }
                       self.trim(ents,tran)
                      end
                      
                      
                      1. Let Sketchup create the face by using .find_faces for each edge that is on the cutting plane.

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

                      http://sdmitch.blogspot.com/

                      1 Reply Last reply Reply Quote 0
                      • medeekM Offline
                        medeek
                        last edited by

                        When I use the truss plugin to create complex roofs I would like to be able to use the trim tool to trim some of the members (ie. a hip roof):

                        Link Preview Image
                        3D Warehouse

                        3D Warehouse is a website of searchable, pre-made 3D models that works seamlessly with SketchUp.

                        favicon

                        (3dwarehouse.sketchup.com)

                        Nathaniel P. Wilkerson PE
                        Medeek Engineering Inc
                        design.medeek.com

                        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