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.
    • Dan RathbunD Offline
      Dan Rathbun
      last edited by

      SketchUp is not a solid modeler.. it's a surface modeler.

      So of course there will be no face where the plane cuts it.

      However, you might take advantage of the "left-over geometry". try moving the vertices in the left over face, up to those vertices (directly above them z-wise,) on the bottom of the hollow object.

      Or .. if it is easier, draw a new face on the bottom of the hollow object, insect it with the group. Find the inner face and delete it, leaving a new "ring face".

      I'm not here much anymore.

      1 Reply Last reply Reply Quote 0
      • 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