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

    Help Understanding Classes and Class objects

    Scheduled Pinned Locked Moved Developers' Forum
    30 Posts 4 Posters 276 Views 4 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.
    • thomthomT Offline
      thomthom
      last edited by

      Also - when creating Group with the API you create the group first - then add the entities directly into the group. As oppose to when you model in SketchUp where you draw the geometry - then group.

      Thomas Thomassen — SketchUp Monkey & Coding addict
      List of my plugins and link to the CookieWare fund

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

        You CAN make a group from existing entities gp=entities.add_group(array_of_entities)... BUT if those entities are not all in the same context OR if their context is NOT the active_entities then you will get a Bugsplat.
        If you are making new entities then it is best to make them inside the desired context in the first place - using a new [initially] empty group gp=entities.add_group();gp.entities.add_face(points) to get the face etc.
        Doing this also removes the risk of your new geometry clashing with some existing geometry in the active_context - e.g. overlapping faces, which will intersect unexpectedly if not separated from the very creation of your new face.
        The only time I would suggest you want even to think about making a group from existing objects... is when you are using a user's [premade] selection - because they can only select objects in the 'active_entities' context then you can safely group those objects [or a filtered sub-set of them - e.g. just faces and edges] into a new group that is made in the same context, thus: gp=model.active_entities.add_group(model.selection.to_a) will make a group of the current selection.

        TIG

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

          @dan rathbun said:

          There is still a basic grouping protocol steps that are out of sequence in your original example, and in mine above.

          Can you figure out what the proper sequence is ???

          @thomthom said:

          ... when creating Group with the API you create the group first - then add the entities directly into the group. As oppose to when you model in SketchUp where you draw the geometry - then group.

          Thomas gave away the answer.

          So ... lets see the my example, using this protocol.

          We will first create the conveyor group, add a temporary construction point to it, so SU does not clean it up, then past that parent group's entities reference into the other method, and have the subordinate method add it's subgroup to the parent group. Finally we will add pully primitives to the subgroup and return it's reference.

          module Magans
           
            class Conveyor
           
              # make @group var and .group() instance method;
              attr_reader(;group)
           
              private
           
              def initialize(st_point, end_point)
           
                  @st_point = st_point
                  @end_point = end_point
           
                  ents = Sketchup.active_model.active_entities
           
                  # hold reference to group;
                  @group = ents.add_group()
                  cpt = @group.entities.add_cpoint(ORIGIN)
                  @group.name = "CONVEYOR ASSY"
                 
                  # pully1
                  create_end_pully(@group.entities,@st_point,36,18)
           
                  # pully2
                  create_end_pully(@group.entities,@end_point,36,18)
                  
                  cpt.erase!
                 
              end #of initialize()
           
              def create_end_pully(ents,pts,width,length)
                 
                  pt1 =[pts[0] - (width/2),pts[1],pts[2]]
                  pt2 =[pts[0] - (width/2),pts[1]+length,pts[2]]
                  pt3 =[pts[0] + (width/2),pts[1]+length,pts[2]]
                  pt4 =[pts[0] + (width/2),pts[1],pts[2]]
                 
                  subgroup = ents.add_group()
                  face = subgroup.entities.add_face( pt1,pt2,pt3,pt4 )
                  subgroup.name = "END PULLEY"
          
                  face.reverse!
                  face.pushpull( 5 )
           
                  # return the pully's group reference;
                  return subgroup
           
              end #of create_end_pully()
           
              public
           
              # Example "wrapper" methods
           
              def name()
                 return @group.name
              end #of name()
           
              def valid?()
                 return @group.valid?
              end #of name()
           
            end #of Conveyor class
           
          end # module Magans
          

          I'm not here much anymore.

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

            First of all I would like to thank you guys for all of the help. My thought process was skewed in the wrong direction and I don't think I would've come up with the passing the group object. Also starting with the group and then adding the entities is now clear in my head. I had read that before in other posts but could never quite understand the "how". That was where I was hopelessly stuck for the past day. I have re-written the previous code and module-ized it and it works perfectly.

            I kept the classes for Conveyor and EndPulley seperate so that I can use both seperately for inheritance in the future.

            I still need to check into "Wrapper" classes further for how I can implement them effectively.

            The only snag was I had to remove the private designation for the methods under the Conveyor class to work. I'm not really certain why.

            module Pmagans
            	# Type in Console
            	# load 'Conveyor/CONVEYOR2.rb'
            	# conv = Pmagans;;Conveyor.new([0,0,0], [0,120,0])
            	
            	class Conveyor
            		#make the @group var and .group()instance
            		attr_reader(;group)
            		
            		#private #why does this need to be private?		
            		def initialize(st_point, end_point)
            			ents = Sketchup.active_model.entities
            			
            			@st_point = st_point
            			@end_point = end_point
            			
            			#hold reference to group;
            			@group = ents.add_group()
            			cpt = @group.entities.add_cpoint(ORIGIN)
            			@group.name = "CONVEYOR ASSY"
            						
            			self.create_geometry
            			cpt.erase!
            			
            		end #of initialize()
            	
            		def create_geometry()
            			ents = Sketchup.active_model.entities
            			puts ents.length
            			
            			#pulley 1
            			st_ep = EndPulley.new(@group, @st_point)
            			
            			#pulley 2
            			end_ep = EndPulley.new(@group, @end_point)
            			
            			puts ents.length
            			
            		end #of create_geometry()
            	
            	end #of Conveyor class
            	
            	
            	
            	class EndPulley
            			attr_reader(;group)
            			
            		def initialize(conv_group, ins_pt)
            			#TODO; add *args if a group not passed to EndPulley just "create_geometry"
            			@conv_group = conv_group
            			@ins_pt = ins_pt
            			
            			self.create_geometry
            			
            		end #of initialize()
            		
            		def create_geometry()
            			pts = @ins_pt
            			width = 36
            			length = 18
            			
            			ents = Sketchup.active_model.entities
            			pt1 =[pts[0] - (width/2),pts[1],pts[2]]
            			pt2 =[pts[0] - (width/2),pts[1]+length,pts[2]]
            			pt3 =[pts[0] + (width/2),pts[1]+length,pts[2]]
            			pt4 =[pts[0] + (width/2),pts[1],pts[2]]
            	
            			@group = @conv_group.entities.add_group()
            			face = @group.entities.add_face pt1,pt2,pt3,pt4
            			face.reverse!
            			face.pushpull 5
            			@group.name = "END PULLEY"
            					
            		end #of create_geometry()
            		
            	end #of EndPulley class 
            	
            end #of module Pmagans
            
            1 Reply Last reply Reply Quote 0
            • P Offline
              pmagans
              last edited by

              I'm not sure if my last post went through. I wanted to thank everyone though. Also I got everything working and kept the two classes seperate for future inheritence. I had to remove the "private" so that the methods for the Conveyor class could be accessed. I'm not really sure why?

              module CONVEYOR #CONVEYOR.rb
              	# Type in Console
              	# load 'Conveyor/CONVEYOR2.rb'
              	# ex. conv = CONVEYOR;;Conveyor.new([0,0,0], [0,120,0])
              	
              	require 'sketchup.rb'
              	
              	class Conveyor
              		#make the @group var and .group()instance
              		attr_reader(;group)
              		
              		#private #why does this need to be private?
              		
              		def initialize(st_point, end_point)
              			ents = Sketchup.active_model.entities
              			t1 = Geom;;Transformation.translation [0,0,-5]
              			
              			@st_point = st_point
              			@end_point = end_point
              			
              			#hold reference to group;
              			@group = ents.add_group()
              			cpt = @group.entities.add_cpoint(ORIGIN)
              			@group.name = "CONVEYOR ASSY"
              			@group.transform! t1
              			
              			self.create_geometry
              			cpt.erase!
              			
              		end #of initialize()
              	
              		def create_geometry()
              			ents = Sketchup.active_model.entities
              			puts ents.length
              			
              			#pulley 1
              			st_ep = EndPulley.new(@group, @st_point)
              			
              			#pulley 2
              			end_ep = EndPulley.new(@group, @end_point)
              			
              			puts ents.length
              			
              		end #of create_geometry()
              	
              	end #of Conveyor class
              	
              	
              	
              	class EndPulley
              			attr_reader(;group)
              			
              		def initialize(conv_group, ins_pt)
              			#TODO; add *args if a group not passed to EndPulley just "create_geometry"
              			@conv_group = conv_group
              			@ins_pt = ins_pt
              			
              			self.create_geometry
              			
              		end #of initialize()
              		
              		def create_geometry()
              			pts = @ins_pt
              			width = 36
              			length = 18
              			
              			ents = Sketchup.active_model.entities
              			pt1 =[pts[0] - (width/2),pts[1],pts[2]]
              			pt2 =[pts[0] - (width/2),pts[1]+length,pts[2]]
              			pt3 =[pts[0] + (width/2),pts[1]+length,pts[2]]
              			pt4 =[pts[0] + (width/2),pts[1],pts[2]]
              	
              			@group = @conv_group.entities.add_group()
              			face = @group.entities.add_face pt1,pt2,pt3,pt4
              			face.reverse!
              			face.pushpull 5
              			@group.name = "END PULLEY"
              					
              		end #of create_geometry()
              		
              	end #of EndPulley class 
              	
              end #of module CONVEYOR
              
              1 Reply Last reply Reply Quote 0
              • thomthomT Offline
                thomthom
                last edited by

                @pmagans said:

                I'm not sure if my last post went through.

                The first few posts of new members must be approved by a moderator before it appear on the forum - this is an anti-spam measure.

                Thomas Thomassen — SketchUp Monkey & Coding addict
                List of my plugins and link to the CookieWare fund

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

                  You still have this
                  st_ep = EndPulley.new(@group, @st_point)
                  which won't return the new object [group] unless you add
                  return @group
                  as the final code in the EndPulley method...

                  TIG

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

                    So I added the return @group per your recommendation TIG however I am having some confusion as to how Sketchup sees the newly created groups. It doesn't seem like you can manipulate the returned groups as per the example code below returns undefined method transform!
                    It seems as though Sketchup is treating the groups st_ep and end_ep as objects not groups. I have been creating "dummy-container groups to bypass this like Conveyor but I'm guessing from your comment there is an easier way to access the groups that I am creating in the EndPulley class?

                    module CONVEYOR #CONVEYOR.rb
                       # Type in Console
                       # load 'Conveyor/CONVEYOR2.rb'
                       # ex. conv = CONVEYOR;;Conveyor.new([0,0,0], [0,120,0])
                       
                       require 'sketchup.rb'
                       
                       class Conveyor
                          #make the @group var and .group()instance
                          attr_reader(;group)
                          
                          #private #why does this need to be private?
                          
                          def initialize(st_point, end_point)
                             ents = Sketchup.active_model.entities
                             #t1 = Geom;;Transformation.translation [0,0,-5]
                             
                             @st_point = st_point
                             @end_point = end_point
                             
                             #hold reference to group;
                             @group = ents.add_group()
                             cpt = @group.entities.add_cpoint(ORIGIN)
                             @group.name = "CONVEYOR ASSY"
                             #@group.transform! t1
                             
                             self.create_geometry
                             cpt.erase!
                             
                          end #of initialize()
                       
                          def create_geometry()
                             ents = Sketchup.active_model.entities
                             t1 = Geom;;Transformation.translation [0,0,-5]
                             #pulley 1
                             st_ep = EndPulley.new(@group, @st_point)
                             #puts st_ep
                             st_ep.transform! t1
                             
                             #pulley 2
                             end_ep = EndPulley.new(@group, @end_point)
                             end_ep.transform! t1
                             
                          end #of create_geometry()
                       
                       end #of Conveyor class
                       
                       
                       
                       class EndPulley
                             attr_reader(;group)
                             
                          def initialize(conv_group, ins_pt)
                             #TODO; add *args if a group not passed to EndPulley just "create_geometry"
                             @conv_group = conv_group
                             @ins_pt = ins_pt
                             
                             self.create_geometry
                             
                          end #of initialize()
                          
                          def create_geometry()
                             pts = @ins_pt
                             width = 36
                             length = 18
                             
                             ents = Sketchup.active_model.entities
                             pt1 =[pts[0] - (width/2),pts[1],pts[2]]
                             pt2 =[pts[0] - (width/2),pts[1]+length,pts[2]]
                             pt3 =[pts[0] + (width/2),pts[1]+length,pts[2]]
                             pt4 =[pts[0] + (width/2),pts[1],pts[2]]
                       
                             @group = @conv_group.entities.add_group()
                             face = @group.entities.add_face pt1,pt2,pt3,pt4
                             face.reverse!
                             face.pushpull 5
                             @group.name = "END PULLEY"
                             
                             return @group
                                   
                          end #of create_geometry()
                          
                       end #of EndPulley class 
                       
                    end #of module CONVEYOR
                    
                    1 Reply Last reply Reply Quote 0
                    • TIGT Offline
                      TIG Moderator
                      last edited by

                      end_ep = EndPulley.new(@group, @end_point)

                      NOW ADD

                      puts 'end_tp details...' puts end_tp puts end_tp.class puts end_tp.name puts 'END'

                      THEN

                      end_ep.transform!(t1)

                      FAIL ? IF end_tp is NOT a group or component_instance ???

                      Report back what the 'puts' show in the Ruby Console...

                      TIG

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

                        This is the output - Doesn't get to the puts statements

                        load 'Conveyor/CONVEYOR2.rb'
                        true
                        conv = CONVEYOR;;Conveyor.new([0,0,0], [0,120,0])
                        end_tp details...
                        Error; #<NameError; undefined local variable or method `end_tp' for #<CONVEYOR;;Conveyor;0xb8a563c>>
                        C;/PROGRA~2/Google/GOOGLE~1/Plugins/Conveyor/CONVEYOR2.rb;43
                        C;/PROGRA~2/Google/GOOGLE~1/Plugins/Conveyor/CONVEYOR2.rb;27;in `initialize'
                        (eval);435;in `new'
                        (eval);435
                        
                        1 Reply Last reply Reply Quote 0
                        • TIGT Offline
                          TIG Moderator
                          last edited by

                          Try this change: in the EndPulley code after
                          self.create_geometry
                          ###ADD
                          return @group

                          as the last code before the ' end' of the initialize...

                          REMOVE the equivalent line from the create_geometry method...

                          Run with the ' puts' to see what's what now...

                          TIG

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

                            Same message No change - its dying on the puts statements?

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

                              WAIT !!

                              Earlier on I attempted to explain that his custom classes were WRAPPER CLASSES. (And questioned why anyone would want to actually do this. Subsequent edits by a user such as boolean operations can cause the references held by the wrapper class instances to become invalid and point at Sketchup::DeletedEntity objects.)

                              I showed an example which did NOT have a EndPully class, because it would ALSO be a wrapper class, whose new() constructor returns the wrapper instance NOT a Sketchup::Group instance.

                              SO.. therefore... he needs to call the EndPully instance's group() wrapper method (created via the attr_reader(:group) call,) which will return the actual group reference:
                              st_ep.group.transform! t1

                              I'm not here much anymore.

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

                                Can you also add the equivalent 'puts' just after the
                                st_ep = EndPulley.new(@group, @st_point)

                                puts 'st_tp details...' puts st_tp puts st_tp.class puts st_tp.name puts 'END'

                                so we can see what the first part does...

                                TIG

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

                                  Sorry ... I got busy and did not get back to this thread,

                                  I was going to continue the discussion on why wrapper classes are extremely problematic for Sketchup::Drawingelement subclasses. (One issue is on Mac multiple models could be open, but the API does not yet have a good way to track them, and we know of some bugs on the PC, that causes issues.)


                                  Anyway... the alternative you REALLY should be using is to create a Sketchup::ComponentDefinition for your pully and conveyor, and then place instances of these (rather than Groups.)

                                  The definition's instances collection will keep track of them for you.

                                  The model's DefintionList collection will keep track of your definition(s) for each model that they are inserted into.

                                  When a model is opened, your plugin can search through it's DefintionList to find those definitions that are "known" to the plugin. And then grab an array of their instances, and iterate it to get references.

                                  I'm not here much anymore.

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

                                    Dan you are correct. Adding the .group gave me access to the "group" objects that were created.

                                    As for my thought process I am not sure that it is valid so let me describe my thoughts.

                                    I don't want to code "like" things so I assumed that using classes would allow me to inherit class attributes things without having to copy a bunch of code it multiple places. For example classes would be:

                                    1. FUNCTIONAL AREAS
                                      [list:11tc2ay1]1. CONVEYOR
                                    • CONVEYOR_COMPONENTS

                                    • END_PULLEY

                                    • DRIVE

                                    • INTERMEDIATE_BED

                                    • PAN_GUARD

                                    • BEARINGS

                                    • ETC.

                                    • BUILDING_MODSETC.[/*Ⓜ11tc2ay1][/list⭕11tc2ay1]Later I could write Customer specific code for each of the classes and inherit all of the functionality that I wrote in the "General" Classes

                                    One customer's end_pulley may contain different bearings, pulleys, profiles etc. Also there are many types of end pulleys. That being said they do have some similarities especially attribute definitions, layer structure, basic functionality.

                                    Am I on the right track or am I way off the rails?

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

                                      @TIG 🎉

                                      Simply put:

                                      A class constructor returns an instance of IT's class.

                                      CONVEYOR::EndPully.new() returns an instance of CONVEYOR::EndPully not an instance Sketchup::Group

                                      This is one of the MAJOR drawbacks of a wrapper class, you have to write wrapper methods for all the methods of the wrapped object that you wish to access "as if" the wrapper "were" the object itself.

                                      There are some ruby tricks to get a list of only the API methods, and define wrapper methods via an eval loop. But .. it's still can get complicated in other nitty-gritty ways.

                                      I just do not recommend it.

                                      I'm not here much anymore.

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

                                        Dynamic Component definitions can give you a lot of flexibility. A style of pully, were the diameter and width are settable via the Component Options dialog.

                                        Your code classes and modules... are geometry creators, but not the actual model objects themselves.

                                        You can also inherit (share) code functionality via mixin module libraries.

                                        Given a mixin module named BasicPully ...

                                        module FancyPully
                                        
                                          include BasicPully
                                        
                                          # now overrride inherited methods if desired
                                        
                                          # now add additional methods if desired
                                        
                                        end
                                        

                                        .. and later ...

                                        module NiftyPully
                                        
                                          include FancyPully
                                        
                                          # now overrride inherited methods if desired
                                        
                                          # now add additional methods if desired
                                        
                                        end
                                        

                                        I'm not here much anymore.

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

                                          ☀ 😒 doh!

                                          TIG

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

                                            I will check into the mixin module approach also the dynamic components. Are dynamic components "create-able" through Ruby code or only through the Sketchup interface?

                                            The only info/tutorial I could find was:
                                            http://sketchucation.com/forums/viewtopic.php?f=180&t=17888&p=145120&hilit=dynamic+component+tutorial#p145120

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

                                            Advertisement