Medeek Wall API

It has been a while since I’ve broached this topic but a very basic API already does exist for the Wall Plugin.

See this post from a couple years ago:

In order to regen a wall:

Medeek_Engineering_Inc_Extensions::MedeekWallPlugin::Wall::MedeekMethods.wall_regen entity

Where the entity is the wall group.

I’ve decided to keep working on this since there seems to be some interest in certain 3rd party extension developers who want to interact with the Wall Plugin. I think a dedicated thread on this topic would be easier to navigate than the huge thread already in existence for the Wall Plugin.

I will be periodically posting snippets of code and other thoughts and ideas to this new topic, stay tuned.

In order to read the basic parameters of any wall here is a small snippet of code (two methods) for doing just that. This code is not copyrighted but is heavily based on my own wall dictionary code for reading the wall parameters into my own plugins (simplified and proprietary information removed).

The wrapping and implementation is arbitrary so anyone can easily take this code and create their own methods for accessing the parameters of any of the Medeek walls within their own code. This chunk of code is primarily to provide an example of how one can access all of these parameters and to also provide a convenient and comprehensive resource delineating what parameters are available within a Medeek Wall.

To quickly demonstrate this code:

1.) Create a wall or two in SketchUp with the Medeek Wall Extension.
2.) Copy this entire block of code into the Ruby Console
3.) Select the walls created so they are highlighted
4.) Type in Mdkbim::MedeekMethods.get_wall
5.) The response for each wall will be given with some of its parameters.


# Define Module Hierarchy

module Mdkbim


	

##############################
#
# Class Methods of Plugin
#
##############################

class MedeekMethods
  	class << self


def get_wall

	# Validate Selection

      	ss = Sketchup.active_model.selection

      	if ss.empty?
        	UI.messagebox "No Wall Assembly Selected."
        	return
      	end



	for maingroup in ss

	   wallfamily = maingroup.get_attribute 'medeek_wall_param', 'WALLFAMILY', ''

	   if wallfamily == 'Rectangular'

		# Read Dictionary Attributes with method below
		MedeekMethods.read_wall_params maingroup


		@maingroup_name = maingroup.name



		# Outputs some of the wall variables to the Ruby console for inspection:
		
		puts "Wall Parameters Successfully Read:"
		puts "Wall Name: #{@Wall_name}"
		puts "Wall Type: #{@Walltype}"
		puts "Group Name of Wall: #{@maingroup_name}\n\n"


	   end

	end #End of for loop


end



def read_wall_params (gdef)

	if gdef.deleted?
		puts "Do nothing, group has been deleted."
	else

	lib = 'medeek_wall_param'
	lib2 = 'medeek_wall_param2'
	lib3 = 'medeek_wall_param3'
	lib4 = 'medeek_wall_param4'
	lib6 = 'medeek_wall_param6'
	lib7 = 'medeek_wall_param7'
	libq = 'medeek_wall_quoin'
	lib8 = 'medeek_wall_incline'

	@Wallfamily = gdef.get_attribute lib, 'WALLFAMILY', ''
	@maingrouporigin = gdef.get_attribute lib, 'MAINORIGIN', ''
	@initgrouporigin = gdef.get_attribute lib, 'INITORIGIN', '' 

	
		
		@Wall_name = gdef.get_attribute lib, 'WALL_NAME', ''
		@Walltype = gdef.get_attribute lib, 'WALLTYPE', ''
		@Wall_length = gdef.get_attribute lib, 'WALL_LENGTH', '' 
		@Walljust = gdef.get_attribute lib, 'WALLJUST', '' 
		@Wallhgt = gdef.get_attribute lib, 'WALLHGT', ''
		@Wallhdrhgt = gdef.get_attribute lib, 'WALLHDRHGT', ''
		@Stud_depth = gdef.get_attribute lib, 'STUD_DEPTH', ''
		@Stud_width = gdef.get_attribute lib, 'STUD_WIDTH', ''
		@Studspacing = gdef.get_attribute lib, 'STUDSPACING', ''
		@Studdir = gdef.get_attribute lib, 'STUDDIR', ''
		@Std_offset = gdef.get_attribute lib, 'STUDOFFSET', 0.0
		@Studply = gdef.get_attribute lib, 'STUDPLY', 1 
		@Plt_top_num = gdef.get_attribute lib, 'PLT_TOP_NUM', '' 
		@Plt_top = gdef.get_attribute lib, 'PLT_TOP', '' 
		@Plt_btm_num = gdef.get_attribute lib, 'PLT_BTM_NUM', '' 
		@Plt_btm = gdef.get_attribute lib, 'PLT_BTM', '' 
		@Plt_btm_pt = gdef.get_attribute lib, 'PLT_BTM_PT', '' 
		@Wallgroup = gdef.get_attribute lib, 'WALLGROUP', ''
		@Framingoption = gdef.get_attribute lib, 'FRAMINGOPTION', ''

		
		@Framemat = gdef.get_attribute lib, 'FRAMEMAT', 'NO'
		@Advwalloptions = gdef.get_attribute lib, 'ADVWALLOPTIONS', ''

		# Irregular Wall Options

		@Wallhgt2 = gdef.get_attribute lib, 'WALLHGT2', @Wallhgt
		@Wallhgt3 = gdef.get_attribute lib, 'WALLHGT3', (@Wallhgt+24.0)
		@Wallpitch1 = gdef.get_attribute lib, 'WALLPITCH1', 4.0
		@Wallpitch2 = gdef.get_attribute lib, 'WALLPITCH2', 4.0
		@Wallhand = gdef.get_attribute lib, 'WALLHAND', 'LEFT'
		@Wallradius = gdef.get_attribute lib, 'WALLRADIUS', 120.0

		# Staggered Studs

		@Stud_depth_ext = gdef.get_attribute lib, 'STUD_DEPTH_EXT', 3.5
		@Stud_depth_int = gdef.get_attribute lib, 'STUD_DEPTH_INT', 3.5

		# ICF

		@Insulextthk = gdef.get_attribute lib, 'INSULEXTTHK', 2.5
		@Insulintthk = gdef.get_attribute lib, 'INSULINTTHK', 2.5
		@Insulextmat = gdef.get_attribute lib, 'INSULEXTMAT', 'EPS'
		@Insulintmat = gdef.get_attribute lib, 'INSULINTMAT', 'EPS'


		# Windows

		@Windowlist = gdef.get_attribute lib, 'WINDOWLIST', ''
		if @Windowlist == 'NOWINDOWS'
			@Windowlist = []
		end

		# Doors

		@Doorlist = gdef.get_attribute lib, 'DOORLIST', ''
		if @Doorlist == 'NODOORS'
			@Doorlist = []
		end

		# Garages

		@Garagelist = gdef.get_attribute lib, 'GARAGELIST', ''
		if @Garagelist == 'NOGARAGES'
			@Garagelist = []
		end

		# Columns

		@Columnlist = gdef.get_attribute lib, 'COLUMNLIST', ''
		if @Columnlist == 'NOCOLUMNS'
			@Columnlist = []
		end

		# SSWs

		@Sswlist = gdef.get_attribute lib, 'SSWLIST', ''
		if @Sswlist == 'NOSSWS'
			@Sswlist = []
		end

		# SWs

		@Swlist = gdef.get_attribute lib, 'SWLIST', ''
		if @Swlist == 'NOSWS'
			@Swlist = []
		end

		# Wall Corner 1

		@Corner_start = gdef.get_attribute lib, 'CORNER_START', '' 
		@Cornerangle1 = gdef.get_attribute lib, 'CORNERANGLE1', '' 
		@Cornerstudthk1 = gdef.get_attribute lib, 'CORNERSTUDTHK1', '' 
		@Cornerstudqty1 = gdef.get_attribute lib, 'CORNERSTUDQTY1', '' 
		@Cornertreatment1 = gdef.get_attribute lib, 'CORNERTREATMENT1', ''
		@Corneroffset1 = gdef.get_attribute lib, 'CORNEROFFSET1', ''
		@Cornertr1 = gdef.get_attribute lib, 'CORNERTR1', 'YES'
		@Corneroff1 = gdef.get_attribute lib, 'CORNEROFF1', 0.0

		# Wall Corner 2

		@Corner_end = gdef.get_attribute lib, 'CORNER_END', '' 
		@Cornerangle2 = gdef.get_attribute lib, 'CORNERANGLE2', '' 
		@Cornerstudthk2 = gdef.get_attribute lib, 'CORNERSTUDTHK2', '' 
		@Cornerstudqty2 = gdef.get_attribute lib, 'CORNERSTUDQTY2', '' 
		@Cornertreatment2 = gdef.get_attribute lib, 'CORNERTREATMENT2', ''
		@Corneroffset2 = gdef.get_attribute lib, 'CORNEROFFSET2', ''
		@Cornertr2 = gdef.get_attribute lib, 'CORNERTR2', 'YES'
		@Corneroff2 = gdef.get_attribute lib, 'CORNEROFF2', 0.0

		# Annotations

		@Label_rot = gdef.get_attribute lib, 'LABEL_ROT', 0
		

			# Advanced Options

			@Wallsheathoption = gdef.get_attribute lib2, 'WALLSHEATHOPTION', ''  
			@Wallsheaththk = gdef.get_attribute lib2, 'WALLSHEATHTHK', ''
			@Wallsheathcorner = gdef.get_attribute lib2, 'WALLSHEATHCORNER', ''
			@Wallcladoption = gdef.get_attribute lib2, 'WALLCLADOPTION', ''
			@Wallcladthk = gdef.get_attribute lib2, 'WALLCLADTHK', ''
			@Wallcladgap = gdef.get_attribute lib2, 'WALLCLADGAP', ''
			@Wallcladcorner = gdef.get_attribute lib2, 'WALLCLADCORNER', ''
			@Wallgypsumoption = gdef.get_attribute lib2, 'WALLGYPSUMOPTION', '' 
			@Wallgypsumthk = gdef.get_attribute lib2, 'WALLGYPSUMTHK', ''
			@Wallinsuloption = gdef.get_attribute lib2, 'WALLINSULOPTION', '' 
			@Holdownoption = gdef.get_attribute lib2, 'HOLDOWNOPTION', ''
			@Wallsheathvertoffset_t = gdef.get_attribute lib2, 'WALLSHEATHVERTOFFSET_T', ''
			@Wallsheathvertoffset_b = gdef.get_attribute lib2, 'WALLSHEATHVERTOFFSET_B', ''
			@Wallcladvertoffset_t = gdef.get_attribute lib2, 'WALLCLADVERTOFFSET_T', ''
			@Wallcladvertoffset_b = gdef.get_attribute lib2, 'WALLCLADVERTOFFSET_B', ''
			@Clad_mat_offset = gdef.get_attribute lib2, 'CLADMATOFFSET', 0.0
			@Clad_mat_hoffset = gdef.get_attribute lib2, 'CLADMATHOFFSET', 0.0
			
			@Wallsheathmat = gdef.get_attribute lib2, 'WALLSHEATHMAT', ''
			@Wallcladmat = gdef.get_attribute lib2, 'WALLCLADMAT', ''
			@Wallgypsummat = gdef.get_attribute lib2, 'WALLGYPSUMMAT', ''
			@Wallinsulmat = gdef.get_attribute lib2, 'WALLINSULMAT', ''
			@Blockingoption = gdef.get_attribute lib2, 'BLOCKINGOPTION', ''
			@Trimoption = gdef.get_attribute lib2, 'TRIMOPTION', ''
			@Trimintoption = gdef.get_attribute lib2, 'TRIMINTOPTION', ''
			@Wsct_option = gdef.get_attribute lib2, 'WSCTOPTION', ''

			@Wallgypsum2option = gdef.get_attribute lib2, 'WALLGYPSUM2OPTION', 'NO' 
			@Wallgypsum2thk = gdef.get_attribute lib2, 'WALLGYPSUM2THK', 0.5
			@Wallgypsum2mat = gdef.get_attribute lib2, 'WALLGYPSUM2MAT', 'WALLGYPSUM2_MAT'
			
			@Quoin_option = gdef.get_attribute lib2, 'QUOINOPTION', 'NO'

			@Incline_option = gdef.get_attribute lib2, 'INCLINEOPTION', 'NO'

			@Wallsheath2option = gdef.get_attribute lib2, 'WALLSHEATH2OPTION', 'NO'  
			@Wallsheath2thk = gdef.get_attribute lib2, 'WALLSHEATH2THK', 0.4375
			@Wallsheath2corner = gdef.get_attribute lib2, 'WALLSHEATH2CORNER', 'FLUSH'
			@Wallsheath2mat = gdef.get_attribute lib2, 'WALLSHEATH2MAT', 'OSB'
			
			# Rain Screen Options

			@Rainscreen = gdef.get_attribute lib2, 'RAINSCREEN', 'NO'  
			@Furring_width = gdef.get_attribute lib2, 'FURRINGWIDTH', 1.5
			@Furring_spacing = gdef.get_attribute lib2, 'FURRINGSPACING', 16.0
			@Furring_offset = gdef.get_attribute lib2, 'FURRINGOFFSET', 0.0

			@Furring_dir = gdef.get_attribute lib2, 'FURRINGDIR', 'V'
			@Furring_t = gdef.get_attribute lib2, 'FURRINGT', 3.5
			@Furring_b = gdef.get_attribute lib2, 'FURRINGB', 3.5

			@Removestudlist = gdef.get_attribute lib2, 'REMOVESTUDLIST', 'empty'

				# Holdown Options
			
				@Holdowntype = gdef.get_attribute lib3, 'HOLDOWNTYPE', ''
				@Holdownvertoffset = gdef.get_attribute lib3, 'HOLDOWNVERTOFFSET', ''
				@Holdown_ab = gdef.get_attribute lib3, 'HOLDOWN_AB', ''
				@Thd_rod_length = gdef.get_attribute lib3, 'THD_ROD_LENGTH', ''
				@Holdown_location = gdef.get_attribute lib3, 'HOLDOWN_LOCATION', ''
				@Holdown_strap_loc = gdef.get_attribute lib3, 'HOLDOWN_STRAP_LOC', ''
			

				# Blocking Options
			
				@Blockinghgt = gdef.get_attribute lib4, 'BLOCKINGHGT', ''
				@Staggerblocking = gdef.get_attribute lib4, 'STAGGERBLOCKING', ''
				@Blockingnum = gdef.get_attribute lib4, 'BLOCKINGNUM', ''
				@Blockingspacing = gdef.get_attribute lib4, 'BLOCKINGSPACING', ''
			

				# Trim Options
			
				@Trimloc = gdef.get_attribute lib6, 'TRIMLOC', ''
				@Trimthk = gdef.get_attribute lib6, 'TRIMTHK', ''
				@Trimoutoption = gdef.get_attribute lib6, 'TRIMOUTOPTION', ''
				@Trimwidthout = gdef.get_attribute lib6, 'TRIMWIDTHOUT', ''
				@Triminoption = gdef.get_attribute lib6, 'TRIMINOPTION', ''
				@Trimwidthin = gdef.get_attribute lib6, 'TRIMWIDTHIN', ''
				@Walltrimmat = gdef.get_attribute lib6, 'WALLTRIMMAT', ''
				@Trimcut = gdef.get_attribute lib6, 'TRIMCUT', ''

				# Band Board

				@Trim_band = gdef.get_attribute lib6, 'TRIMBAND', ''
				@Trim_band_width = gdef.get_attribute lib6, 'TRIMBANDWIDTH', ''
				@Trim_band_thk = gdef.get_attribute lib6, 'TRIMBANDTHK', ''
				@Trim_band_cont = gdef.get_attribute lib6, 'TRIMBANDCONT', ''
				@Trim_band_hgt = gdef.get_attribute lib6, 'TRIMBANDHGT', ''

				# Frieze Board

				@Trim_frieze = gdef.get_attribute lib6, 'TRIMFRIEZE', ''
				@Trim_frieze_width = gdef.get_attribute lib6, 'TRIMFRIEZEWIDTH', ''
				@Trim_frieze_thk = gdef.get_attribute lib6, 'TRIMFRIEZETHK', ''
				@Trim_frieze_cont = gdef.get_attribute lib6, 'TRIMFRIEZECONT', ''

				# Skirt Board

				@Trim_skirt = gdef.get_attribute lib6, 'TRIMSKIRT', ''
				@Trim_skirt_width = gdef.get_attribute lib6, 'TRIMSKIRTWIDTH', ''
				@Trim_skirt_thk = gdef.get_attribute lib6, 'TRIMSKIRTTHK', ''
				@Trim_skirt_cont = gdef.get_attribute lib6, 'TRIMSKIRTCONT', ''

				# Drip Cap

				@Trim_cap = gdef.get_attribute lib6, 'TRIMCAP', ''
				@Trim_cap_height = gdef.get_attribute lib6, 'TRIMCAPHEIGHT', ''
				@Trim_cap_depth = gdef.get_attribute lib6, 'TRIMCAPDEPTH', ''	
			

				# Wainscot Options
			
				@Wsct_hgt = gdef.get_attribute lib7, 'WSCTHGT', ''
				@Wsct_thk = gdef.get_attribute lib7, 'WSCTTHK', ''
				@Wsct_gap = gdef.get_attribute lib7, 'WSCTGAP', ''
				@Wsct_corner = gdef.get_attribute lib7, 'WSCTCORNER', ''
				@Wsct_mat = gdef.get_attribute lib7, 'WSCTMAT', ''
				@Wsct_ledge = gdef.get_attribute lib7, 'WSCTLEDGE', ''
				@Wsct_ledgeheight = gdef.get_attribute lib7, 'WSCTLEDGEHEIGHT', ''
				@Wsct_ledgedepth = gdef.get_attribute lib7, 'WSCTLEDGEDEPTH', ''
				@Wsct_ledgewin = gdef.get_attribute lib7, 'WSCTLEDGEWIN', ''

				@Wsct_start = gdef.get_attribute lib7, 'WSCTSTART', ''
				@Wsct_end = gdef.get_attribute lib7, 'WSCTEND', ''

				@Wsct_mode = gdef.get_attribute lib7, 'WSCTMODE', ''
				
				@Wsct_ledgemat = gdef.get_attribute lib7, 'WSCTLEDGEMAT', @Wsct_mat
			

				# Quoin Options
			
				@Q_style = gdef.get_attribute libq, 'QSTYLE', 'A'
				@Q_l1 = gdef.get_attribute libq, 'QL1', 16.0
				@Q_l2 = gdef.get_attribute libq, 'QL2', 12.0
				@Q_hgt = gdef.get_attribute libq, 'QHGT', 12.0
				@Q_spc = gdef.get_attribute libq, 'QSPC', 2.0
				@Q_thk = gdef.get_attribute libq, 'QTHK', 1.0
				@Q_mat = gdef.get_attribute libq, 'QMAT', 'QUOIN'


				# Incline Options

				@Wallpitch_bot = gdef.get_attribute lib8, 'WALLPITCH_BOT', 4.0
				@Inclinedir = gdef.get_attribute lib8, 'INCLINEDIR', 'LEFT'
				@Inclineoffset = gdef.get_attribute lib8, 'INCLINEOFFSET', 0.0
			




	end # End of validity check of group

end	





end # << self
end # MedeekMethods Class



end # Mdkbim

Here is also another relevant post by Matt Donley on reconfiguring Jack and Kings studs:

It should be noted that anyone can add any number of additional attribute libraries and parameters to these standard Medeek Wall groups just so long as the names don’t conflict with the already established naming conventions. The plugin will simply ignore these other libraries/data and this additional data/metadata for the Wall group could be used for any number of purposes (ie. statistics, insulation, solar studies, engineering etc…) by third party plugins.

With a bit of coding one could even use the regen method given above together with additional attribute libraries (data) to create additional geometry within or encompassing the standard Medeek wall group, further augmenting it with additional features, overlays and/or geometry. The SketchUp API being what it is literally makes the possibilities endless.

Some not really topic related things...

:thinking: I think that since this is mainly for developers, it would be better to assign the topic category to [Developers] [Ruby API].

:bulb: It would be nice to use only spaces for indentation. No hard tabs. << Click on it for more…

Currently you are using it in a mixed way:

image
.

It might cause some headaches for other developers if you publish the code like this because they have to convert to “standard” indentation.

Maybe it’s worth spending some time learning a “proper” code editor… I know, it can be a hard decision if you’ve used your Windows Notepad for years…(I read before that you use it , I don’t know if it’s still the case?)

The above screenshot made after coping your code to Notepad++.

I actually use Notepad++ as my preferred editor of choice however a lot of my legacy code was written in plain old Notepad.

I’m updating the API so that one can either enter in the actual group of the wall assembly or just the instance name of the wall assembly.

In order to regen a wall:

Medeek_Engineering_Inc_Extensions::MedeekWallPlugin::Wall::MedeekMethods.wall_regen 'instance_name'

Where the instance name is the wall assembly name (ie. RECT_WALL_ASSEMBLY_2024110823301222 ).

Medeek_Engineering_Inc_Extensions::MedeekWallPlugin::Wall::MedeekMethods.wall_regen 'RECT_WALL_ASSEMBLY_2024110823301222'

I will also be adding a new API method for moving walls. Note that this method essentially fires up the move wall tool but without the interface or tool, a positive delta-y (float) moves the wall inward and a negative delta-y (float) moves the wall outward.

Medeek_Engineering_Inc_Extensions::MedeekWallPlugin::Wall::MedeekMethods.wall_move 'instance_name', delta-y

An example call might look like:

Medeek_Engineering_Inc_Extensions::MedeekWallPlugin::Wall::MedeekMethods.wall_move 'RECT_WALL_ASSEMBLY_2024110916480984', 48

Note that the delta-y is the amount to move in or out in inches.

Here is an example of moving a wall with the wall_move method using the Medeek Wall API:

wall_move_api

There is not a lot of people using the API, at least not that I am aware of, but what this does it open up the possibility for the other Medeek extensions (and any other extension) to interact with these walls and adjust them as required.

There is now a documentation page here:

Here is what I prompted ChatGPT with:

Okay, now that you have helped me actually program most of the Medeek APIs (wall, truss, foundation and floor). I would like for you to attempt to use the API to generate some ruby code I can dump into the console in order to create a simple garage (four exterior walls) with a simple fink truss roof.

I also forgot to add that this should have a slab on grade foundation that measures 24’ x 36’. The walls align with the edges of the foundation (outside of framing) and the truss roof will also be 24’ x 36’. On the one gable end will be a 16’ garage door 84" in height (default, so don’t worry about the height. On one of the long walls there should be a regular 36" x 80" door, centered 6’ from the corner. On the other long wall a 36" x 48" window (centered on wall) and on the other short wall opposite the garage door wall should also be a 36" x 48" window (centered on the wall). The fink truss roof should be a 6:12 pitch, leave everything else as default.

After one mistake (it put the roof assembly on the ground initially, not sure why it missed that but it did), it produced this piece of code, which I then copied and pasted into the console and hit enter:

model = Sketchup.active_model
ents  = model.active_entities

wall_mod  = Medeek_Engineering_Inc_Extensions::MedeekWallPlugin::Wall::MedeekMethods
truss_mod = Medeek_Engineering_Inc_Extensions::MedeekTrussPlugin::MedeekMethods
sog_mod   = Medeek_Engineering_Inc_Extensions::MedeekFoundationPlugin::Sog::MedeekMethods

# --- helper: run an API call and return the new top-level group it created ---
def capture_new_group(ents)
  before = ents.grep(Sketchup::Group)
  yield
  after  = ents.grep(Sketchup::Group)
  new_groups = after - before
  return new_groups.first
end

model.start_operation('Create Medeek Garage', true)

begin
  # ---------------------------------------------------------------------------
  # GEOMETRY
  # 24' x 36' slab/wall/truss footprint
  # Coordinates in inches
  #
  # Layout:
  #   SW = (0,0,0)
  #   SE = (432,0,0)
  #   NE = (432,288,0)
  #   NW = (0,288,0)
  #
  # Walls are drawn counterclockwise around the exterior perimeter so the
  # outside of framing aligns with the slab perimeter.
  # ---------------------------------------------------------------------------

  p0 = [0.0,   0.0,   0.0]   # SW
  p1 = [432.0, 0.0,   0.0]   # SE
  p2 = [432.0, 288.0, 0.0]   # NE
  p3 = [0.0,   288.0, 0.0]   # NW

  footprint = [p0, p1, p2, p3]

  # ---------------------------------------------------------------------------
  # 1. Slab-on-grade foundation
  # ---------------------------------------------------------------------------
  sog_group = capture_new_group(ents) do
    sog_mod.sog_draw(footprint)
  end

  # ---------------------------------------------------------------------------
  # 2. Exterior walls
  #    South wall: p0 -> p1  (36')
  #    East wall:  p1 -> p2  (24')
  #    North wall: p2 -> p3  (36')
  #    West wall:  p3 -> p0  (24')  <-- garage door wall
  # ---------------------------------------------------------------------------
  south_wall = capture_new_group(ents) do
    wall_mod.wall_draw(p0, p1, 'Rectangular', 'Int-Ext')
  end

  east_wall = capture_new_group(ents) do
    wall_mod.wall_draw(p1, p2, 'Rectangular', 'Int-Ext')
  end

  north_wall = capture_new_group(ents) do
    wall_mod.wall_draw(p2, p3, 'Rectangular', 'Int-Ext')
  end

  west_wall = capture_new_group(ents) do
    wall_mod.wall_draw(p3, p0, 'Rectangular', 'Int-Ext')
  end

  # ---------------------------------------------------------------------------
  # 3. Openings
  #
  # WEST gable wall (24' wall): centered 16' garage door
  # wall length = 288", centered opening location = 144"
  #
  # SOUTH long wall (36' wall): 36" x 80" door
  # center placed 72" from SW corner
  #
  # NORTH long wall (36' wall): centered 36" x 48" window
  # wall length = 432", centered opening location = 216"
  #
  # EAST short wall (24' wall): centered 36" x 48" window
  # wall length = 288", centered opening location = 144"
  # ---------------------------------------------------------------------------

  # 16' garage door on west wall, centered
  wall_mod.wall_garage_draw(144.0, 192.0, 84.0, 'Rectangle', west_wall)

  # 3' x 6'-8" man door on south wall, center 6' from SW corner
  wall_mod.wall_door_draw(72.0, 36.0, 80.0, 'Rectangle', south_wall)

  # Centered window on north wall
  wall_mod.wall_win_draw(216.0, 36.0, 48.0, 'Rectangle', north_wall)

  # Centered window on east wall
  wall_mod.wall_win_draw(144.0, 36.0, 48.0, 'Rectangle', east_wall)

  # ---------------------------------------------------------------------------
  # 4. Fink truss roof over same 24' x 36' footprint, 6:12 pitch
  #    FIX 1: raise roof to top of walls
  #    FIX 2: reorder points so gable orientation is rotated 90 degrees
  # ---------------------------------------------------------------------------
  wall_height = 97.125

  tp0 = [0.0,   0.0,   wall_height]   # SW
  tp1 = [0.0,   288.0, wall_height]   # NW
  tp2 = [432.0, 288.0, wall_height]   # NE
  tp3 = [432.0, 0.0,   wall_height]   # SE

  truss_footprint = [tp0, tp1, tp2, tp3]

  truss_group = capture_new_group(ents) do
    truss_mod.common_truss_draw(6.0, 'Fink', truss_footprint)
  end

  model.commit_operation

  puts 'Medeek garage created successfully.'
  puts "SOG group:   #{sog_group ? sog_group.name : 'not captured'}"
  puts "South wall:  #{south_wall ? south_wall.name : 'not captured'}"
  puts "East wall:   #{east_wall ? east_wall.name : 'not captured'}"
  puts "North wall:  #{north_wall ? north_wall.name : 'not captured'}"
  puts "West wall:   #{west_wall ? west_wall.name : 'not captured'}"
  puts "Truss group: #{truss_group ? truss_group.name : 'not captured'}"

rescue => e
  model.abort_operation
  puts "ERROR: #{e.class} - #{e.message}"
  puts e.backtrace.join("\n")
end

The result was this:


ChatGPT just built (in SketchUp) my new detached garage in under five minutes. It was even offering to modify the windows to sliders and other modifications if I needed to stray from the defaults that I had used.

These AI engines will continue to improve and eventually they may be able to do much more than design a simple four wall structure like this. Things are going to get really interesting in the next couple of years.

I’m wondering if it would be possible to setup my own specific AI engine that has trained thoroughly on the use of SketchUp and my Medeek APIs. With enough training it should be able to actually layout floor plans with interior partition walls, closets and all the windows and doors. This has really got me thinking…

If you look at the code it generates it is very well documented and organized, I am quite impressed with its output (ChatGPT 5.4 Thinking). I’ve heard that Claude is even better at this sort of thing, but either way what these things can do is starting to get impressive.

See Jack’s post in a recent topic on AI use for coding Ruby: