### Arc Tool
#
module Tools2D
class ArcTool2D

def db(string)
  dir=File.dirname(__FILE__) ### adjust folder to suit tool
  toolname="2Dtools"  ### adjust xxx to suit tool...
  locale=Sketchup.get_locale.upcase
  path=File.join(dir, toolname+locale+".lingvo")
  unless File.exist?(path)
     return string
  else
    deBabelizer(string,path)
  end 
end#def

def getExtents
    bbox=Sketchup.active_model.bounds
    bbox.add(@ip.position)if @ip and @ip.valid?
    bbox.add(@ip1.position)if @ip1 and @ip1.valid?
    bbox.add(@ip2.position)if @ip2 and @ip2.valid?
    bbox.add(@ip3.position)if @ip3 and @ip3.valid?
    return bbox
end

@@cursor=nil
def initialize()
  @state=0 
  @points=[]
  @@cursor=nil
  curpath=File.join(File.dirname(__FILE__), "Icons", "2Darc_cursor.png")
  @@cursor=UI::create_cursor(curpath, 0, 31) if File.exist?(curpath)
end

def reset
  ### get/set reference plane 'z'
    @z=Sketchup.active_model.get_attribute("2Dtools","z",nil)
    Sketchup.active_model.set_attribute("2Dtools","z",0.0.mm)if not @z
    @z=Sketchup.active_model.get_attribute("2Dtools","z",nil)
    @zmsg=" [ Z="+@z.to_s+" ] "
  ###
  @arc_angle=0.0
  @dang=0.0
  @state = 0
  @segs = 18 if !@segs
  if @ctrl
    Sketchup::set_status_text((db("2D Arc:"))+@zmsg+(db(" Pick the Center - Toggles: Ctrl=Center+2point/3point, Alt=Arc>180°")))
  else
    Sketchup::set_status_text((db("2D Arc:"))+@zmsg+(db(" Pick the Start - Toggles: Ctrl=Center+2point/3point")))
  end#if
  Sketchup.set_status_text(@segs.to_s,SB_VCB_VALUE)                  
  Sketchup.set_status_text((db("Segments")), SB_VCB_LABEL) 
  @points=[]
end

def activate
  @ip  = Sketchup::InputPoint.new 
  @ip1 = Sketchup::InputPoint.new 
  @ip2 = Sketchup::InputPoint.new 
  @ip3 = Sketchup::InputPoint.new 
  @ctrl=false
  @alt=false
  self.reset
end

def deactivate(view)
  view.invalidate if @drawn 
  @ip = nil 
  @ip1 = nil 
  @ip2 = nil 
  @ip3 = nil
    Sketchup::set_status_text("",SB_PROMPT)
    Sketchup::set_status_text("",SB_VCB_LABEL)
    Sketchup::set_status_text("",SB_VCB_VALUE)
end

def onSetCursor()
    #return nil if RUBY_PLATFORM =~ /darwin/
	UI::set_cursor(@@cursor)if @@cursor
end

def onMouseMove(flags, x, y, view)
  @ip.pick(view,x,y)
  case @state 
  when 0
    if @ctrl
      Sketchup::set_status_text((db("2D Arc:"))+@zmsg+(db(" Pick the Center - Toggles: Ctrl=Center+2point/3point, Alt=Arc>180°")))
    else
      Sketchup::set_status_text((db("2D Arc:"))+@zmsg+(db(" Pick the Start - Toggles: Ctrl=Center+2point/3point")))
    end#if
    Sketchup.set_status_text(@segs.to_s,SB_VCB_VALUE)                  
    Sketchup.set_status_text((db("Segments")), SB_VCB_LABEL) 
    if @ip.valid? && @ip1 != @ip
      view.lock_inference
      @ip1.copy!(@ip)
      view.tooltip=@ip1.tooltip
      view.invalidate 
    end
  when 1
    @ip.pick(view,x,y,@ip1)
    if @ctrl
        Sketchup::set_status_text((db("2D Arc:"))+@zmsg+(db(" Pick an End - Toggles: Ctrl=Center+2point/3point, Alt=Arc>180°")))
        Sketchup.set_status_text((db("Radius")),SB_VCB_LABEL)
    else
        Sketchup::set_status_text((db("2D Arc:"))+@zmsg+(db(" Pick the End - Toggles: Ctrl=Center+2point/3point")))
        Sketchup.set_status_text((db("Chord")),SB_VCB_LABEL)
    end#if
    if @ip.valid? && @ip != @ip1 && @ip != @ip2
      view.lock_inference
      @ip2.copy!(@ip)
      view.tooltip=@ip2.tooltip
      @points[1] = @ip2.position
      @points[1].z=@z
      view.invalidate
      dim=@points[0].distance(@points[1])
      Sketchup.set_status_text(dim.to_s,SB_VCB_VALUE)
    end
  when 2
    @ip.pick(view,x,y,@ip1)
    if @ctrl
        Sketchup::set_status_text((db("2D Arc:"))+@zmsg+(db(" Pick Point to Fix the Other End - Toggles: Ctrl=Center+2point/3point, Alt=Arc>180°")))
    else
        Sketchup::set_status_text((db("2D Arc:"))+@zmsg+(db(" Pick a Point on the Arc - Toggles: Ctrl=Center+2point/3point")))
    end#if
    if @ip.valid? && @ip != @ip1 && @ip != @ip2 && @ip != @ip3
      @ip3.copy!(@ip)
        view.lock_inference
        view.tooltip=@ip3.tooltip
        @points[2] = @ip3.position
        @points[2].z=@z
        @points[3] = @ip3.position
        @points[3].z=@z
      ### also report angle in VCB
      ax=@arc_angle.radians
      dp=1000 #############
      ax=((ax*dp).round).to_f/dp ############
      vang=ax.to_s
      Sketchup.set_status_text(vang,SB_VCB_VALUE)
      Sketchup.set_status_text((db("Swept Angle")), SB_VCB_LABEL)
      ###
      view.invalidate 
    end
  end#case
end

def enableVCB?
   return true
end

def onUserText (text, view)
  if text.split("").last=="s" ###e.g. 12s
    @lastseg = @segs
    @segs = text.to_i 
    if @segs < 3 
      UI.beep 
      @segs = @lastseg 
    end
    Sketchup.set_status_text(@segs.to_s,SB_VCB_VALUE)
    return nil
  end#if
  if @state==2 ### angle e.g. 22.5
    Sketchup.set_status_text((db("Swept Angle")),SB_VCB_LABEL)
    if @ctrl
      @dang=text.to_f
      if @dang!=0.0
        pt1=@points[0]
        pt2=@points[1]
        pt3=pt2.clone
        tr=Geom::Transformation.rotation(pt1,Z_AXIS,@dang.degrees)
        pt3.transform!(tr)
        create_geometry(pt1,pt2,pt3)
        @state = 0
        self.reset 
      end#if
    else ### 3-point
      @dang=text.to_f
      if @dang !=0.0 and @dang.abs < 360.0
        pt1=@points[0]
        pt2=@points[1]
        vec=(pt2-pt1)
        dis=(pt1.distance(pt2))/2
        pt3=pt1.clone
        pt3.offset!(vec,dis)
        off=(dis/Math::tan(((180.degrees-(@dang.degrees/2))/2)))#.abs
        tr=Geom::Transformation.rotation(pt3,Z_AXIS,90.degrees)
        vec.transform!(tr)
        pt3.offset!(vec,off)
        create_geometry(pt1,pt2,pt3)
        @state = 0
        self.reset 
      else
        puts db("Angle cannot be 0 or 360 degrees - infintely small or large arcs would result")
      end#if
    end#if
  end#if
  ###
  if @ctrl and @state==1 ### could type in radius
    value=text
    Sketchup.set_status_text((db("Radius")),SB_VCB_LABEL)
    begin
        value = text.to_l
    rescue # Error parsing the text
        UI.beep
        puts (db("Cannot convert "))+text+(db(" to a Length"))
        value = nil
    end
    return if !value
    pt1 = @ip1.position
    pt1.z=@z
    pt2=@ip2.position
    pt2.z=@z
    vec = pt2 - pt1
    if vec.length == 0.0
        UI.beep
        return
    end
    vec.length = value
    pt2 = pt1 + vec
    @points[1]=pt2
    @state=2
    view.invalidate
  end#if
  if not @ctrl and @state==1 ### set chord length
    value=text
    Sketchup.set_status_text((db("Chord")),SB_VCB_LABEL)
    begin
        value = text.to_l
    rescue # Error parsing the text
        UI.beep
        puts(db("Cannot convert "))+text+(db(" to a Length"))
        value = nil
    end
    return if !value
    pt1 = @ip1.position
    pt1.z=@z
    pt2=@ip2.position
    pt2.z=@z
    vec = pt2 - pt1
    if vec.length == 0.0
        UI.beep
        return
    end
    vec.length = value
    pt2 = pt1 + vec
     @points[1]=pt2
    @state=2
    view.invalidate
  end#if
end#def

def draw(view)
  if @ip.valid? && @ip.display?
    @ip.draw(view)
    @drawn = true
  end
  if (@points.length > 0) 
    view.draw_points(@points, 5, 5, "blue")
    @drawn = true 
  end 
  case @state 
   when 1 
    view.drawing_color = "blue"
    view.set_color_from_line(@ip1,@ip2)if @points[1]
    view.draw(GL_LINE_STRIP, @points[0],@points[1])if @points[1]
    @drawn = true
   when 2 
    view.drawing_color = "blue"
    view.set_color_from_line(@ip1,@ip2)if @points[1]
    view.draw(GL_LINE_STRIP, @points[0],@points[1])if @points[1]
    ### draw temp arc
    view.drawing_color = "black"
if @points[2]
 begin
  if not @ctrl### 3point
    pt1=@points[0];pt2=@points[1];pt3=@points[2]
    arc_points=[pt1,pt3,pt2]
  v1 = arc_points[1]-arc_points[0]
  v2=arc_points[2]-arc_points[1]
  vz=(arc_points[0] - arc_points[1]).cross(arc_points[0] - arc_points[2])
  vz=Z_AXIS if vz==[0,0,0]
#compute center of arc
v1m=v1.clone
v1m.length = v1.length/2.0
t=Geom::Transformation.translation v1m
mid_v1= arc_points[0].transform t
#entities.add_cpoint mid_v1
r1 = Geom::Transformation.rotation(mid_v1, vz, Math::PI/2.0)
v1mr=v1m.transform r1
v2m=v2.clone
v2m.length = v2.length/2.0
t=Geom::Transformation.translation v2m
mid_v2= arc_points[1].transform t
r2 = Geom::Transformation.rotation(mid_v2, vz, Math::PI/2.0)
v2mr=v2m.transform r2
center=Geom.intersect_line_line([mid_v1, v1mr], [mid_v2, v2mr])
#draw arc
arc_rad = center.distance arc_points[0]
@arc_angle = (arc_points[2] - center).angle_between((arc_points[0] - center))
if (pt3-pt1).angle_between(pt3-pt2) < Math::PI/2
  @arc_angle=(Math::PI*2)-@arc_angle
end#if
  gp=view.model.active_entities.add_group()
  gp.entities.add_arc(center,(arc_points[0]-center),vz,arc_rad,0, @arc_angle,@segs)
  curve=gp.entities[0].curve
  points=[]; curve.vertices.each{|v|points<<v.position}
  gp.erase! if gp.valid?
  view.draw_polyline(points)
  view.draw_points([center],5,5,"blue")
  ###
else####### it's centered
  pt1=@points[0];pt2=@points[1];pt3=@points[2]
  v1=pt2-pt1
  v2=pt3-pt1
  vz=(pt3 - pt2).cross(pt1 - pt3)
  vz=Z_AXIS if vz==[0,0,0]
  center=pt1.clone
  arc_rad=center.distance(pt2)
  @arc_angle = (pt3 - center).angle_between((pt2 - center))
  @arc_angle= 360.degrees-@arc_angle if @alt ############
  vx=(pt2-center)
  vx=(pt3-center) if @alt ##########
  ###
  gp=view.model.active_entities.add_group()
  gp.entities.add_arc(center,vx, vz,arc_rad,0,@arc_angle,@segs)
  curve=gp.entities[0].curve
  points=[]; curve.vertices.each{|v|points<<v.position}
  gp.erase! if gp.valid?
  view.draw_polyline(points)
  view.drawing_color = "blue"
  view.set_color_from_line(@ip1,@ip3)
  view.draw_line(pt1,pt3)
  view.draw_points([points.last], 5, 5, "blue")
 end#if ctrl
rescue
###
end#begin
end#if arc  
    @drawn = true
  end
end 

def onLButtonDown(flags, x, y, view)
  @ip.pick(view,x,y)
  if @ip.valid?
    case @state 
    when 0
      Sketchup.active_model.start_operation(db("2D Arc"))
      @points[0] = @ip.position
      @points[0].z=@z
      @v1 = @ip.position
      @v1.z=@z
      @state += 1
      if @ctrl
        Sketchup::set_status_text((db("2D Arc:"))+@zmsg+(db(" Pick an End to give Radius - Toggles: Ctrl=Center+2point/3point, Alt=Arc>180°")))
      else
        Sketchup::set_status_text((db("2D Arc:"))+@zmsg+(db(" Pick the End - Toggles: Ctrl=Center+2point/3point")))
      end#if
    when 1
      if @ip.position != @v1
        @points[2] = @ip.position 
        @points[2].z=@z
        #@points[4] = @points[0]
        @v2 = @ip.position
        @v2.z=@z
        @state += 1
        if @ctrl
          Sketchup::set_status_text((db("2D Arc:"))+@zmsg+(db(" Pick Point to Fix the Other End - Toggles: Ctrl=Center+2point/3point, Alt=Arc>180°")))
        else
          Sketchup::set_status_text((db("2D Arc:"))+@zmsg+(db(" Pick a Point on the Arc - Toggles: Ctrl=Center+2point/3point")))
        end#if
      else 
        UI.beep
      end  
    when 2
      if @ip.position != @v1 && @ip.position != @v2
        @v3 = @ip.position  
        @v3.z=@z
        @points[3] = @v3
        #create_geometry(@v1,@v2,@v3)
        create_geometry(@points[0],@points[1],@points[2])        
        @state = 0
        self.reset 
      elsif @alt and @ctrl and @ip.position != @v1
        @v3 = @ip.position  
        @v3.z=@z
        @points[3] = @v3
        #create_geometry(@v1,@v2,@v3)
        create_geometry(@points[0],@points[1],@points[2])   
        @state = 0
        self.reset 
      else 
        UI.beep
      end
    end 
  end
  view.lock_inference
end

def onKeyDown(key, repeat, flags, view)
    if key == CONSTRAIN_MODIFIER_KEY && repeat == 1
        @shift_down_time = Time.now
        if view.inference_locked?
            view.lock_inference
        elsif @state == 0 && @ip1.valid?
            view.lock_inference @ip1
        elsif @state == 1 && @ip2.valid?
            view.lock_inference @ip2, @ip1
        end
    end
    if key==VK_CONTROL || key==VK_COMMAND  ### Ctrl toggles lines / clines
      if @ctrl
        @ctrl=false
      else
        @ctrl=true
      end#if
    end#if
    if key==VK_ALT  ### Alt toggles lines / polylines
      if @alt 
        @alt=false
      else
        @alt=true
      end#if
    end#if
end

def onKeyUp(key, repeat, flags, view)
    if key == CONSTRAIN_MODIFIER_KEY && view.inference_locked? && (Time.now - @shift_down_time) > 0.5
        view.lock_inference
    end
    view.invalidate
end

def resume(view)
  view.invalidate
  if @state==0
    if @ctrl
      Sketchup::set_status_text((db("2D Arc:"))+@zmsg+(db(" Pick the Center - Toggles: Ctrl=Center+2point/3point, Alt=Arc>180°")))
    else
      Sketchup::set_status_text((db("2D Arc:"))+@zmsg+(db(" Pick the Start - Toggles: Ctrl=Center+2point/3point")))
    end#if
  elsif @state==1
    if @ctrl
      Sketchup::set_status_text((db("2D Arc:"))+@zmsg+(db(" Pick an End to give Radius - Toggles: Ctrl=Center+2point/3point, Alt=Arc>180°")))
    else
      Sketchup::set_status_text((db("2D Arc:"))+@zmsg+(db(" Pick the End - Toggles: Ctrl=Center+2point/3point")))
    end#if
  else
    if @ctrl
      Sketchup::set_status_text((db("2D Arc:"))+@zmsg+(db(" Pick Point to Fix the Other End - Toggles: Ctrl=Center+2point/3point, Alt=Arc>180°")))
    else
      Sketchup::set_status_text((db("2D Arc:"))+@zmsg+(db(" Pick a Point on the Arc - Toggles: Ctrl=Center+2point/3point")))
    end#if
  end#if
end

def create_geometry(pt1,pt2,pt3)
  if not @ctrl######################### 3point
    arc_points=[pt1,pt3,pt2]
    v1=arc_points[1]-arc_points[0]
    v2=arc_points[2]-arc_points[1]
    vz=(arc_points[0] - arc_points[1]).cross(arc_points[0] - arc_points[2])
    vz=Z_AXIS if vz==[0,0,0]
  #compute center of arc
v1m=v1.clone
v1m.length = v1.length/2.0
t=Geom::Transformation.translation v1m
mid_v1= arc_points[0].transform t
#entities.add_cpoint mid_v1
r1 = Geom::Transformation.rotation(mid_v1, vz, Math::PI/2.0)
v1mr=v1m.transform r1
v2m=v2.clone
v2m.length = v2.length/2.0
t=Geom::Transformation.translation v2m
mid_v2= arc_points[1].transform t
r2 = Geom::Transformation.rotation(mid_v2, vz, Math::PI/2.0)
v2mr=v2m.transform r2
center=Geom.intersect_line_line([mid_v1, v1mr], [mid_v2, v2mr])
#draw arc
arc_rad = center.distance arc_points[0]
@arc_angle = (arc_points[2] - center).angle_between((arc_points[0] - center))
if (pt3-pt1).angle_between(pt3-pt2) < Math::PI/2
  @arc_angle=(Math::PI*2)-@arc_angle
end#if
  Sketchup.active_model.active_entities.add_arc(center,(arc_points[0]-center), vz,arc_rad,0,@arc_angle,@segs)
  Sketchup.active_model.active_entities.add_cpoint(center)
  ###
else####### it's centered ####################################
  v1=pt2-pt1
  v2=pt3-pt1
  vz=(pt3 - pt2).cross(pt1 - pt3)
  vz=Z_AXIS if vz==[0,0,0]
  center=pt1.clone
  arc_rad=center.distance(pt2)
  @arc_angle = (pt3 - center).angle_between((pt2 - center))
  @arc_angle=360.degrees if @arc_angle==0.0
  @arc_angle=360.degrees-@arc_angle if @alt ############
  vx=(pt2-center)
  vx=(pt3-center)if @alt ##########
  ###
  Sketchup.active_model.active_entities.add_arc(center,vx, vz,arc_rad,0,@arc_angle,@segs)
  Sketchup.active_model.active_entities.add_cpoint(center)
  ###
 end#if
  Sketchup.active_model.commit_operation
end#create_geometry

end # class

end#mod
#-----------------------------------------------------------------------------
# shortcut
#def arctool2D
    #Sketchup.active_model.select_tool ArcTool2D.new
#end
######-----------------------------------------------
