sketchucation logo sketchucation
    • Login
    🤑 SketchPlus 1.3 | 44 Tools for $15 until June 20th Buy Now

    Polygon Positioning Tool

    Scheduled Pinned Locked Moved Developers' Forum
    13 Posts 4 Posters 1.8k 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.
    • medeekM Offline
      medeek
      last edited by

      I've got the polygon positioning tool mostly worked out for my foundation plugin. However, when the user enters in a value for the length of the segment (VCB_VALUE) then the subsequent line selection does not properly infer the X and Y axis. I've spent already way too much time on this and I can't figure it out. My code is shown below for the polygon positioning tool:

      
      #########################################
      #
      # Foundation POSITIONING LOGIC (Polygon)
      #
      #########################################
      
      
      
      module FoundationPositionToolPolygon
      
      
      # --------  FOUNDATION POSITIONING TOOL  -----------------------------
      
      # Positions the foundation assembly. This tool allows the user
      # to place the foundation assembly using the mouse to select a polygon 
      
      
      
      class PositionToolPolygon
      
      	# Show the Ruby Console at startup so we can
      	# see any programming errors we may make.
      	# SKETCHUP_CONSOLE.show
      
      	#  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_2 = 2 if not defined? STATE_PICK_2
      	STATE_PICK_3 = 3 if not defined? STATE_PICK_3
      	STATE_PICK_FINAL = 4 if not defined? STATE_PICK_FINAL
      	STATE_MOVING = 6 if not defined? STATE_MOVING
      	STATE_SELECT = 7 if not defined? STATE_SELECT
         
      
      def initialize()
          	@tool_name = "FOUNDATION LOCATOR"
      	@type = "foundation"
      	@pointcount = 0
      end
      
      def reset
          	@pts = []
          	@state = STATE_PICK
      	@pointcount = 0
      	
          	# This sets the label for the VCB
          	Sketchup;;set_status_text "MEDEEK FOUNDATION", SB_VCB_LABEL
          	Sketchup;;set_status_text "[#{@tool_name}] Click first corner of Polygon"
      	@status_text = "[#{@tool_name}] Click first corner of Polygon"
          	@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 onMouseMove(flags, x, y, view)
      	self.set_current_point(x, y, view)
      	Sketchup;;set_status_text @status_text,SB_PROMPT
      end
      
      
      def onLButtonDown(flags, x, y, view)
          	self.set_current_point(x, y, view)
          	self.update_state
      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_2
              @pts[1] = @ip.position
      	@sectionlength = @pts[0].distance @pts[1]
      	Sketchup;;set_status_text @sectionlength.to_s, SB_VCB_VALUE
          when STATE_PICK_3
      	@pts[2] = @ip.position
      	@sectionlength = @pts[1].distance @pts[2]
      	Sketchup;;set_status_text @sectionlength.to_s, SB_VCB_VALUE
          when STATE_PICK_FINAL
      	@pts[@pointcount] = @ip.position
      	@sectionlength = @pts[@lastpointcount].distance @pts[@pointcount]
      	Sketchup;;set_status_text @sectionlength.to_s, SB_VCB_VALUE
          end   
      
          view.invalidate if need_draw
      end
      
      def update_state
          case @state
          when STATE_PICK
              @ip1.copy! @ip
      	@lastpointcount = @pointcount
      	@pointcount = @pointcount + 1
              Sketchup;;set_status_text "[#{@tool_name}] Click second corner of Polygon"
      	Sketchup;;set_status_text "Section Length", SB_VCB_LABEL
              Sketchup;;set_status_text "", SB_VCB_VALUE
              @state = STATE_PICK_2
      	puts "#{@state} #{@pointcount}"
      	@status_text = "[#{@tool_name}] Click second corner of Polygon"
          when STATE_PICK_2
              # @ip1.clear
      	@ip1.copy! @ip
      	@lastpointcount = @pointcount
      	@pointcount = @pointcount + 1
      	Sketchup;;set_status_text "[#{@tool_name}] Click third corner of Polygon"
      	Sketchup;;set_status_text "Section Length", SB_VCB_LABEL
              Sketchup;;set_status_text "", SB_VCB_VALUE
              @state = STATE_PICK_3
      	puts "#{@state} #{@pointcount}"
      	@status_text = "[#{@tool_name}] Click third corner of Polygon"
          when STATE_PICK_3
              # @ip1.clear
      	@ip1.copy! @ip
      	@lastpointcount = @pointcount
      	@pointcount = @pointcount + 1
      	Sketchup;;set_status_text "[#{@tool_name}] Click fourth corner of Polygon"
      	Sketchup;;set_status_text "Section Length", SB_VCB_LABEL
              Sketchup;;set_status_text "", SB_VCB_VALUE
              @state = STATE_PICK_FINAL
      	puts "#{@state} #{@pointcount}"
      	@status_text = "[#{@tool_name}] Click fourth corner of Polygon"
          when STATE_PICK_FINAL
      	# @ip1.clear
      	@ip1.copy! @ip
      	ptcurrent = @ip.position
      	@distorigin = @pts[0].distance ptcurrent
      	if (@distorigin > 0.0001)
      		@lastpointcount = @pointcount
      		@pointcount = @pointcount + 1
      		@nextpointcount = @pointcount + 1
      		@state = STATE_PICK_FINAL
      		puts "#{@state} #{@pointcount}"
      		Sketchup;;set_status_text "[#{@tool_name}] Click corner #{@nextpointcount} of Polygon"
      		Sketchup;;set_status_text "Section Length", SB_VCB_LABEL
              	Sketchup;;set_status_text "", SB_VCB_VALUE
      		@status_text = "[#{@tool_name}] Click corner #{@nextpointcount} of Polygon"
      	else
      		# Final point picked, jump to calculation and exit tool to main program
      		
              	self.calculate_obj
              	Sketchup.active_model.select_tool(nil)
      	end
      	
          end
      end
      
      
      def calculate_obj
          	
      	###########
      	#
      	# Check units of template again
      
      	lengthconstant = Sketchup.active_model.options["UnitsOptions"]["LengthUnit"]
      
       	if (lengthconstant == 0) || (lengthconstant == 1)
      		@Unitstemplate2 = "imperial"
      	else
      		@Unitstemplate2 = "metric"
       	end
      
      
      	if @Unitstemplate2 == "metric"
      		# Sketchup;;set_status_text "Foundation Width; #{@BuildingSpan_m.round(4)} m - Foundation Length; #{@BuildingLength_m.round(4)} m"
      	else
      		# Sketchup;;set_status_text "Foundation Width; #{@BuildingSpan_ft.round(4)} ft. - Foundation Length; #{@BuildingLength_ft.round(4)} ft."
      	end
      	
      
      	# Back to main program
      
      	MedeekMethods.main_menu_polygon @pts, @pointcount
         
      end
      
      
      def onCancel(flag, view)
          view.invalidate if @drawn
          reset
      end
      
      def onUserText(text, view)
          # The user may type in something that we can't parse as a length
          # so we set up some exception handling to trap that
          begin
              value = text.to_l
          rescue
              # Error parsing the text
              UI.beep
              value = nil
              Sketchup;;set_status_text "", SB_VCB_VALUE
          end
          return if !value
          
          case @state
          when STATE_PICK_2
              # update the section length
              vec = @pts[1] - @pts[0]
              if( vec.length > 0.0 )
                  vec.length = value
                  @pts[1] = @pts[0].offset(vec)
                  # view.invalidate
                  self.update_state
              end
          when STATE_PICK_3
              # update the section length
              vec = @pts[2] - @pts[1]
              if( vec.length > 0.0 )
                  vec.length = value
                  @pts[2] = @pts[1].offset(vec)
                  # view.invalidate
                  self.update_state
              end
          when STATE_PICK_FINAL
      	# update the section length
              vec = @pts[@pointcount] - @pts[@lastpointcount]
              if( vec.length > 0.0 )
                  vec.length = value
                  @pts[@pointcount] = @pts[@lastpointcount].offset(vec)
                  # view.invalidate
                  self.update_state
              end
          end
      end
      
      def getExtents
          bb = Geom;;BoundingBox.new
          case @state
          when STATE_PICK
              # We are getting the first point
              if( @ip.valid? && @ip.display? )
                  bb.add @ip.position
              end
          when STATE_PICK_2
              bb.add @pts[0]
              bb.add @pts[1]
          when STATE_PICK_3
              bb.add @pts[2]
          when STATE_PICK_FINAL
      	bb.add @pts
          end
          return bb
      end
      
      def onKeyDown(key, rpt, flags, view)
          if( key == CONSTRAIN_MODIFIER_KEY && rpt == 1 )
              @shift_down_time = Time.now
              
              # if we already have an inference lock, then unlock it
              if( view.inference_locked? )
                  view.lock_inference
              elsif( @state == 0 )
                  view.lock_inference @ip
              elsif( @state == 1 )
                  view.lock_inference @ip, @ip1
      	elsif( @state == 2 )
                  view.lock_inference @ip, @ip1
      	elsif( @state == 3 )
                  view.lock_inference @ip, @ip1
      	elsif( @state == 4 )
                  view.lock_inference @ip, @ip1
              end
          end
      end
      
      def onKeyUp(key, rpt, flags, view)
          if( key == CONSTRAIN_MODIFIER_KEY &&
              view.inference_locked? &&
              (Time.now - @shift_down_time) > 0.5 )
              view.lock_inference
          end
      end
      
      # draw a polygon for the outline of the foundation
      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_2
              # just draw a line from the start to the end point
              view.set_color_from_line(@ip1, @ip)
      	# view.drawing_color = [0, 0, 200]
              inference_locked = view.inference_locked?
      	view.line_width = 2 if inference_locked
      	view.line_width = 2
              view.draw(GL_LINE_STRIP, @pts[0], @pts[1])
              @drawn = true
          when STATE_PICK_3
              # just draw a line from the start to the end point
              view.set_color_from_line(@ip1, @ip)
      	# view.drawing_color = [0, 0, 200]
              inference_locked = view.inference_locked?
      	view.line_width = 2 if inference_locked
      	view.line_width = 2
      	# view.draw(GL_LINE_STRIP, @ip1, @ip)
      	view.draw(GL_LINE_STRIP, @pts)
              @drawn = true
          else
      	# just draw a line from the start to the end point
      	view.set_color_from_line(@ip1, @ip)
      	# view.drawing_color = [0, 0, 200]
      	inference_locked = view.inference_locked?
      	view.line_width = 2 if inference_locked
      	view.line_width = 2
              view.draw(GL_LINE_STRIP, @pts)
              @drawn = true
          end
      end
      
      end # class PositionToolPolygon
      
      
      #######################################
      
      end # module FoundationPositionToolPolygon
      

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

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

        Just an FYI, the posted code's improper indentation is so annoying I will not bother to read nor try it out.

        I'm not here much anymore.

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

          I agree, the indentation is killing me. Trust me it doesn't actually look like this, when I cut and past it into the text box it completely mucks it up.

          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:

            I've got the polygon positioning tool mostly worked out for my foundation plugin. However, when the user enters in a value for the length of the segment (VCB_VALUE) then the subsequent line selection does not properly infer the X and Y axis.

            There are two problems as I see it.

            1. You are using @ip1 and @ip to set the line color but, when you enter a length, @ip1 is no longer valid since the point it represents has changed. I think you should use the last to values of the @pts array to set the color.

            2. Expecting the user to get within 0.0001 of the first point to close is way to restrictive.

            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

              I replace the set color line with:

              view.set_color_from_line(@pts[@lastpointcount], @pts[@pointcount])

              however the behavior is identical.

              I agree the .0001 is probably too restrictive. What I should probably do is insert a temporary guide point (add_cpoint) and then delete it once I jump back to my main program out of the tool or as the tool terminates. This way the user has something to snap to in order to close out the polygon.

              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:

                I replace the set color line with:

                view.set_color_from_line(@pts[@lastpointcount], @pts[@pointcount])

                however the behavior is identical.

                I too find it odd that entering a length suddenly causes the axis inference to change its' behavior. The tooltip seems to think that @ip1 is still valid while, if you zoom in and move the mouse very slowly, the correct inference will occur. After that everything is back to normal until the next length entry.

                Very strange indeed and an obvious bug in Sketchup.

                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

                  Yes it is strange. If you enter a value then the next line won't infer the axis, but if you then click the mouse and begin another line the inference returns to normal. The whole tool thing is still somewhat of a black box to me so I don't really understand it fully but this certainly has me confounded.

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

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

                    Nat, use 2 space characters for indents. Tabs will not come out well in the forum code blocks.

                    I'm not here much anymore.

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

                      I've been using tabs for indents since 1999, getting me to change now is not easy. You can probably tell that I like a lot of whitespace in my code, easier to read.

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

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

                        That is okay (whitespace). I use Notepad++ which automatically replaces TAB with spaces. Each language can have a different indent spacing. (I'd think most editors can [or should] do this.)

                        I'm not here much anymore.

                        1 Reply Last reply Reply Quote 0
                        • G Offline
                          Garry K
                          last edited by

                          I totally agree. I use Notepad++ as well and I do not use tabs.

                          The main reason is everyone can set their tabs differently - but spaces are spaces so the reader gets to see what you want them to see.

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

                            I tried Notepad++ a couple years ago but something about it perturbed me so I went back to my basic Windows Notepad, I may revisit it.

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

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

                              @medeek said:

                              ... so I went back to my basic Windows Notepad, ...

                              How do you know what encoding it saves the file it ?
                              How do you know what type of line ending characters it uses ?

                              These are things easily set with a real code editor.

                              In addition code editors use color lexing to help you spell keywords correctly, match up the begins and ends of code blocks, etc. They also can use autocomplete features to help fillout method calls.

                              I'm not here much anymore.

                              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