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

    Intersecting Hollow Objects using intersect_with

    Scheduled Pinned Locked Moved Developers' Forum
    12 Posts 3 Posters 780 Views 3 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.
    • TIGT Online
      TIG Moderator
      last edited by

      You are making it more complicated than it needs to be.
      Instead of slicing a plane through the object and producing some edges, and then having to do complicated checks to see what is to be erased and then what faces need creating on the cut plane etc.... why not use the 'solid' tools available to you in the API as a Pro users?
      Now you have an object_group [that is a 'solid'], and you want to 'chop' a piece off it - so you make another temp_group including the plane on the cut-line which is bigger than the object_group [as you are already doing for the intersect_with].
      Now offset that plane-face's 4 corners vertically down until they are all below the object_group.bounds.min.z.
      You now have a distorted 'box' in outline as temp_group.
      Add faces to its edges so it becomes another solid form with 6 faces in all.

      There are various methods available to Pro users that can cut/combine/trim 'solids'.
      In this case you'd want to use ' subtract'.
      Thus:
      result_group = object_group.subtract(temp_group)
      The result is a group that's still a 'solid' with faces added on the 'cut' plane etc...
      Note that the ' result_group' is a new group - the original ' object_group' and ' temp_group' no longer exist after the operation, so before doing the operation you will need to get references to the reference/name/layer/material/attribute_dictionaries [if any] for the ' object_group' and then reapply them to the new ' result_group'... Thus to the user it will look as if you have cut a piece off the original ' object_group' but actually the operation results in the destruction of the two solids used and the new solid that results has been reconfigured to match the original object in every way except it has modified geometry...

      See the API for 'group' and the various 'solid' tools it lists...

      TIG

      1 Reply Last reply Reply Quote 0
      • Dan RathbunD Offline
        Dan Rathbun
        last edited by

        That sounds better... I ruled out boolean tools because I knew a face cannot be made into a solid group.

        Wouldn't it be nice if SketchUp DID allow solid trimming with a face. We could specify the "trim direction" which is the direction to remove geometry. (In this case the -z direction.)

        I'm not here much anymore.

        1 Reply Last reply Reply Quote 0
        • P Offline
          pmagans
          last edited by

          Thanks TIG,
          I will definitely give that a go. I'll have to start up my work computer to give it a try though. I use the "free" version on a mac at home and the Pro windows version on my work laptop.

          Dan your thoughts are exactly where I wanted to go with being able to pick a direction for the cut. I envisioned a future user prompt to pick a side. I still think I could make it look like a plane being cut using TIG's described method by creating the geometry after the pick. But as a tool it would only be usable on a Pro machine it sounds.

          I thought using the array comparisons would be a quick check of the entities created, but actually it didn't work out well because it looks as though Sketchup "redraws" entities like lines and faces when the intersect_with happens even if it's basically the same location. That's why I started down the checking edges, then checking vertices, etc.

          1 Reply Last reply Reply Quote 0
          • TIGT Online
            TIG Moderator
            last edited by

            @dan rathbun said:

            That sounds better... I ruled out boolean tools because I knew a face cannot be made into a solid group.

            Wouldn't it be nice if SketchUp DID allow solid trimming with a face. We could specify the "trim direction" which is the direction to remove geometry. (In this case the -z direction.)
            Try this http://sketchucation.com/forums/viewtopic.php?p=433723#p433723

            TIG

            1 Reply Last reply Reply Quote 0
            • P Offline
              pmagans
              last edited by

              Thanks for the plugins, TIG! Those are awesome starting points for me. I will need to modify them so that they work for any plane that is non-orthogonal to the orgin. But I think that's just a matter of creating a "plane" through code and not choosing it like the plugin. Thanks again!

              intersect_with_plane.jpg

              1 Reply Last reply Reply Quote 0
              • TIGT Online
                TIG Moderator
                last edited by

                My plugins do cut on any plane that is defined by any three non-co-linear points: these don't need to be orthogonal, drawing a temp-grouped face, WorkPlane or even some guidelines to snap onto will define the plane for you...
                To hard-code it you simply need to define the three points used in @pts...
                Because a face has a plane and you can project a point onto a plane it's relatively straightforward to use an existing face to derive the plane, and thereby the points - you just need to project any point onto the face.plane (to be @pts[0]) then offset that original point 1.0 in the X and re-project for @pts[1], then 1.0 in the Y and re-project for @pts[2]... You'll need 'a trap' to ensure that the face isn't in an orientation that gives coincident/co-linear points for some projections - for example a face with a normal parallel to the X_AXIS will make @pts[1]==@pts[0] when it projects back onto the plane !
                A simple way is to convert the projected points into arrays [point.to_a] as you save them into @pts, and also to project more than you'll need - e.g. @pts[3] as Z 1.0, then doing a @pts.uniq! should leave you with at least three points that are on the plane and not co-linear or the same points... Use @pts[0..2] to be sure of a good set...

                TIG

                1 Reply Last reply Reply Quote 0
                • P Offline
                  pmagans
                  last edited by

                  Thanks TIG. I am still working on this and will post my results.

                  On a side note:
                  I tried to create a function in the module I wrapped everything in and it won't load in Sketchup but works fine outside of the function block.
                  ex.

                  module PMA_INT_TEST
                   ..code here to create geometry
                  end #of module
                  

                  load PMA_INT_TEST.rb into Sketchup works fine

                  then I changed:

                  module PMA_INT_TEST
                  create_geometry()
                  
                  def create_geometry()
                   exact same..code here to create geometry
                  end
                  end #of module
                  

                  load PMA_INT_TEST.rb into Sketchup get:
                  Error: #<NoMethodError: undefined method `create_geometry' for PMA_INT_TEST:Module>

                  1 Reply Last reply Reply Quote 0
                  • Dan RathbunD Offline
                    Dan Rathbun
                    last edited by

                    • You have two issues.

                    (1) The obvious. As the interpreter reads the module definition (for the first time,) it encounters a call to a method that is not yet defined, so the module's private method method_missing() is called passing the unknown method name in as a symbol.

                    Your module has no local override of this error handler, so Ruby passes the call on up the inheritance chain, superclass by superclass. When it finds a root handler, the error is handled. In this case the default from class Module just raises a NoMethodError exception.

                    The exception's message is what you see, which should have also told you the error originated on line 2.
                    If not.. at the console you can get a reference to the last exception instance object, via the global $!, and it's backtrace via the global $@.

                    So the general rule, is to define all your static objects first, usually in this order: constants, class/module @@variables, nested class or module defintions, class methods / module functions (grouping private and public together,) instance methods (grouping private and public together,) and finally "Run Once" init code that runs the first time the module or class is loaded.

                    "Run Once" init code is usually within a conditional block, such as:
                    ` unless file_loaded?(File.basename(FILE))

                    add menu items only once in here

                    end # Run Once`

                    If you have code that always runs each time you reload the module, then put it at the very end.

                    Keep in mind that the Ruby keywords module and class mean "open for editing (and create first if needed.)"

                    (2) The not so obvious quirk of instance methods inside modules.

                    Instance methods inside modules are allowed for a specific purpose. And that is so the module can be used as a "mixin" library module, to include or extend other module or class definitions.

                    You are not creating a "mixin" module, but you would still like to have internal methods that can be called like instance methods with no parent qualification.

                    The answer is a trick called an anonymous singleton proxy class.
                    Proxy class objects are associated with a proxy object, are opened for definition with the syntax:
                    ` class << proxy_object

                    end`

                    In the case of a custom module instance, the proxy object association is to the module it self.

                    SO... within a module, define instance methods as you would inside a normal class definition, but instead put them inside a proxy class definition block (grouping private and public together.)

                    module PMA_INT_TEST
                    
                      require("sketchup.rb")
                    
                      # Constants here;
                      THISFILE = "#{self.name};#{File.basename(__FILE__)}"
                    
                      # Module Variables here
                    
                      class << self
                    
                        # instance variables here
                    
                        public
                    
                        def use_my_tool()
                          # call an internal method
                        end
                    
                        private
                    
                        def create_geometry()
                          # code here to create geometry
                        end
                    
                      end # proxy class
                    
                      # RUN ONCE
                      unless file_loaded?(THISFILE)
                        # create menus and menuitems,
                        # populate a toolbar, etc.
                        file_loaded(THISFILE) # adds to $loaded_files array
                      end
                    
                      # ALWAYS RUN WHEN LOADED CODE here
                    
                    end #of module
                    

                    The global methods file_loaded() and file_loaded?() are defined in "Tools/sketchup.rb" so that file must be require'd if you use them. (Do not specify the "Tools" dir as it is already one of the members of the [ruby:1ngdxd24]$LOAD_PATH[/ruby:1ngdxd24] array that is used by require.)

                    💭

                    I'm not here much anymore.

                    1 Reply Last reply Reply Quote 0
                    • P Offline
                      pmagans
                      last edited by

                      Well I've been using the "solid" tools for the last few days and it is a whole lot easier than what I was trying before. It would be nice to find a non-Pro version, for home use. The following is my test_code. I will re-write using Dan's previous post as a guide. It's a little over my head at this moment and I'm still trying to completly understand it.

                      module PMA_INT_TEST
                      	require('sketchup.rb')
                      	
                      	l = 1.50
                      	w = 1.50
                      	t = 0.078
                      	h = 20
                      
                      	model = Sketchup.active_model
                      	ents = model.entities
                      	
                      	#Just test geometry
                      	pt1 = [0,0,0]
                      	pt2 = [l,0,0]
                      	pt3 = [l,w,0]
                      	pt4 = [0,w,0]
                      	object_group = ents.add_group()
                      	object_group.name = "OBJECT GROUP"
                      	cpt = object_group.entities.add_cpoint(ORIGIN)
                      	face1 = object_group.entities.add_face pt1,pt2,pt3,pt4
                      	cpt.erase!
                      	pt1 = [0+t,0+t,0]
                      	pt2 = [l-t,0+t,0]
                      	pt3 = [l-t,w-t,0]
                      	pt4 = [0+t,w-t,0]
                      	face2 = object_group.entities.add_face pt1,pt2,pt3,pt4
                      	face2.erase! 
                      	face1.reverse!
                      	face1.pushpull h
                      	
                      	#Creating Test Cutgroup1
                      	cut_group1 = ents.add_group()
                      	cpt = cut_group1.entities.add_cpoint(ORIGIN)
                      
                      	pt1 = [0,0,0]
                      	pt2 = [l,0,0]
                      	pt3 = [l,w,0]
                      	pt4 = [0,w,0]
                      	face3 = cut_group1.entities.add_face pt1,pt2,pt3,pt4
                      	face3.reverse!
                      	face3.pushpull h
                      	t1 = Geom;;Transformation.translation [0,0,10]
                      	ts1 = Geom;;Transformation.scaling [l/2,w/2,0], 10
                      	tr1 = Geom;;Transformation.rotation [0, 0, 0], [1, 0, 0], 10.degrees
                      	cut_group1.transform! tr1 * t1 * ts1  
                      	cut_group1.name = "CUT GROUP1"
                      	cpt.erase!
                      	
                      	#Creating Test Cutgroup2
                      	cut_group2 = ents.add_group()
                      	cpt = cut_group2.entities.add_cpoint(ORIGIN)
                      
                      	pt1 = [0,0,0]
                      	pt2 = [l,0,0]
                      	pt3 = [l,w,0]
                      	pt4 = [0,w,0]
                      	face4 = cut_group2.entities.add_face pt1,pt2,pt3,pt4
                      	face4.pushpull h
                      	t2 = Geom;;Transformation.translation [0,0,1]
                      	tr2 = Geom;;Transformation.rotation [0, 0, 0], [1, 0, 0], -10.degrees
                      	cut_group2.transform! tr2 * t2 * ts1  
                      	cut_group2.name = "CUT GROUP2"
                      	cpt.erase!
                      	
                      	#Create "NEW" group from cut group and from object group
                      	UI.messagebox("CUTTING")
                      	
                      	cut_group = cut_group1.subtract(object_group)
                      	cut_group = cut_group2.subtract(cut_group)
                      	cut_group.name = "NEW NAME"
                      
                      end #of module PMA_INT_TEST
                      
                      1 Reply Last reply Reply Quote 0
                      • TIGT Online
                        TIG Moderator
                        last edited by

                        There's BoolTools http://www.Smustard.com, for just $10...
                        There's also Oscarlok's Boolean ODCoolean toolset, in the Plugins Index, which is free... http://sketchucation.com/forums/viewtopic.php?p=112055#p112055
                        These both replicate several of the solid tools in Free that are available only in Pro...

                        TIG

                        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