Polygon Positioning Tool
-
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
-
Just an FYI, the posted code's improper indentation is so annoying I will not bother to read nor try it out.
-
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.
-
@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.
-
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.
-
Expecting the user to get within 0.0001 of the first point to close is way to restrictive.
-
-
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.
-
@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.
-
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.
-
Nat, use 2 space characters for indents. Tabs will not come out well in the forum code blocks.
-
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.
-
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 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.
-
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.
-
@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.
Advertisement