<?xml version="1.0" encoding="utf-8"?>
<!-- ArchiFrame element settings etc -->
<archiframe>
  <!-- Settings for elements -->
  <elem>
    <settings>
      <!-- Common settings -->
      <plank>
        <misc minlen="0.01" idstr="%s-01"></misc>
      </plank>

      <!-- Settings for new element object, also run when element gets ungrouped -->
      <newelem>
        <elemparam name="pen">1</elemparam>
        <objparam name="iShowElemType">1</objparam>
        <objparam name="iShowID2D">1</objparam>
        <objparam name="iShowID3D">1</objparam>
        <objparam name="iElemTypeIdShow"></objparam>
        <objparam name="iID2Yoff">0</objparam>
        <objparam name="iPenID">0</objparam>
      </newelem>

      <!-- Settings for new plank for element -->
      <newelemplank>
        <elemparam name="pen">1</elemparam>
        <objparam name="iShowID">0</objparam>
        <objparam name="iShowID3D">0</objparam>
        <objparam name="iPenErr">1</objparam>
        <objparam name="iPenLocked">8</objparam>
        <objparam name="iUsageId">ELEM</objparam>
        <objparam name="iColLines">3</objparam>
      </newelemplank>

      <!-- For side projection plank -->
      <newelemprojside>
        <elemparam name="pen">1</elemparam>
        <objparam name="iShowID">1</objparam>
        <objparam name="iShowLen">1</objparam>
        <objparam name="iIDPlace">-1</objparam>
        <objparam name="iXoffID">-0.1</objparam>
        <objparam name="iFontSizeBase">7</objparam>
        <objparam name="iPenErr">1</objparam>
        <objparam name="iPenLocked">8</objparam>
        <objparam name="iShowIDSep">-</objparam>
      </newelemprojside>

      <!-- For top projection plank -->
      <newelemprojtop>
        <elemparam name="pen">1</elemparam>
        <objparam name="iShowID">0</objparam>
        <objparam name="iFontSizeBase">7</objparam>
        <objparam name="iPenErr">1</objparam>
        <objparam name="iPenLocked">8</objparam>
        <objparam name="iShowIDSep">-</objparam>
      </newelemprojtop>

      <!-- Settings for free weight calculation marker, calcempty: 1=calculate empty openings as windows/doors -->
      <weightmarker libname="{FD6C137D-C647-42FD-A904-181281909443}-{9060078A-0F41-48C8-8400-8E414A838053}" text="(weight) KG" units="kg" calcempty="0">
        <settings>
          <objparam name="iFill">*25*</objparam>
          <objparam name="A">0.250</objparam>
          <objparam name="B">0.325</objparam>
          <objparam name="ZZYZX">0.325</objparam>
          <objparam name="iShow3D">1</objparam>
        </settings>
      </weightmarker>

      <!-- MULTILAYER BEG -->

      <!-- Settings for new board object -->
      <newelemboard>
        <elemparam name="pen">1</elemparam>
        <layer>AF Board</layer>
        <objparam name="iPenLocked">8</objparam>
        <objparam name="iFillFrom3D">1</objparam>
      </newelemboard>

      <!-- For side projection board -->
      <newelemboardprojside>
        <elemparam name="pen">1</elemparam>
        <objparam name="iFill">25 %</objparam>
        <objparam name="iShowID2D">1</objparam>
        <objparam name="iShowIDSep">#</objparam>
        <objparam name="iFillFrom3D">1</objparam>
      </newelemboardprojside>

      <!-- For top projection board -->
      <newelemboardprojtop>
        <elemparam name="pen">1</elemparam>
        <objparam name="iFill">25 %</objparam>
        <objparam name="iShowIDSep">#</objparam>
        <objparam name="iFillFrom3D">0</objparam>
      </newelemboardprojtop>

      <!-- When panel board is exploded into planks -->
      <boardexploded>
        <objparam name="iPanelBlock">4</objparam>
        <objparam name="iFill">0</objparam>
        <objparam name="iSawLines">15</objparam>
        <objparam name="iWire3D">1</objparam>
      </boardexploded>

      <!-- For projections: To use different pen for boards next to each other. First one is the default pen. If pen is left empty, best match is searched based on rgb. -->
      <boardpens>
        <pen r="0.55" g="0.55" b="0.55" rpen="0.45" gpen="0.45" bpen="0.45"></pen>
        <pen r="0.9" g="0.9" b="0.9" rpen="0.9" gpen="0.9" bpen="0.9"></pen>
        <pen r="0.8" g="0.8" b="0.2" rpen="0.7" gpen="0.7" bpen="0.15"></pen>
        <pen r="0.2" g="0.8" b="0.5" rpen="0.15" gpen="0.7" bpen="0.43"></pen>
      </boardpens>

      <!-- MULTILAYER END -->

      <!-- For element projection tool/section, uses object ArchiFrameDetMarker from ArchiFrame library -->
      <sectionmarker>
        <objparam name="iTypeID">8</objparam>
        <elemparam name="pen">1</elemparam>
        <elemparam name="linetype">*dash*</elemparam>
        <objparam name="iLinetype" type="attr_linetype">*dash*</objparam>
        <objparam name="iFontSize">15</objparam>
      </sectionmarker>


      <!-- Wup-cnc: Saw cut marker object defaults -->
      <sawcut routermaxlen="0.3">
        <elemparam name="pen">1</elemparam>
        <layer></layer>
      </sawcut>

      <!-- Dimension line defaults -->
      <dimlinesettings>
        <elemparam name="dimensiontype">linear</elemparam>
        <elemparam name="pen">1</elemparam>
        <elemparam name="fontname">Arial</elemparam>
        <elemparam name="fontsize">1.5</elemparam>
        <elemparam name="fontstyle"></elemparam>
        <elemparam name="markersize">2</elemparam>
        <elemparam name="markerpen">1</elemparam>
        <elemparam name="witness">1</elemparam>
      </dimlinesettings>

      <!-- Predefined dimline settings -->
      <dimsettings>
        <!-- Settings for element elevation - to be used in many element definitions -->
        <dimlines id="wall_elevation">

          <!-- Boards -->
          <dimline side="top" margin="0.25" elemvecx="1" addminmax="1" addx="1" anchorfirst="1" anchormid="0" anchorlast="1" exclude="*" include="*boarding*">
            <dimlinesettings>
            </dimlinesettings>
            <text content="BOARD" content_fin="LEVY" content_nor="SKIVA" textid="projid*20+5" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Boards offset -->
          <dimline side="top" margin="0.25" elemvecx="1" addminmax="1" addx="1" anchorfirst="1" anchormid="0" anchorlast="1" minpoints="3" exclude="*" includeelem="*boarding*,*core*" onlyelem="1">
            <dimlinesettings>
            </dimlinesettings>
            <text content="BOARD" content_fin="LEVY" content_nor="SKIVA" textid="projid*20+6" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Panel offset -->
          <dimline side="top" margin="0.25" elemvecx="1" addminmax="1" addx="1" minpoints="3" exclude="*" includeelem="*core*,*finish*" onlyelem="1">
            <dimlinesettings>
            </dimlinesettings>
            <text content="CLADDING" content_fin="VERHOILU" content_nor="PANEL" textid="projid*20+7" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Main dimension line showing just element size hor -->
          <dimline side="bottom" margin="0.75" elemvecx="1" elemvecy="0" elemvecz="0" addminmax="1" addx="0" addy="0" addz="0" exclude="*" includeelem="*core*" onlyelem="1">
            <dimlinesettings>
              <elemparam name="fontsize">2</elemparam>
            </dimlinesettings>
          </dimline>

          <!-- Dimension line for vertical posts -->
          <dimline side="bottom" margin="0.5" elemvecx="1" addminmax="1" addminplankmindistfrom="0.050" addmaxplankmindistfrom="0.050" addy="1" anchormid="1" exclude="*" include="*core*">
            <text content="STUD MID" content_fin="TOLPPA KESKI" content_nor="STENDERE SENTER" textid="projid*20+1" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Dimension line for openings horizontal -->
          <dimline side="bottom" margin="0.25" elemvecx="1" addminmax="1" addopeningmin="1" addopeningmax="1" minpoints="3" exclude="*" include="*core*,*stud*" onlyelem="1">
            <text content="OPENING" content_fin="AUKKO" content_nor="ÅPNINGER" textid="projid*20+2" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Main dimension line showing just element size vert, all omitted settings are 0 -->
          <dimline side="right" margin="1" elemvecy="1" addminmax="1" exclude="*" includeelem="*core*">
            <dimlinesettings>
              <elemparam name="fontsize">2</elemparam>
            </dimlinesettings>
          </dimline>


          <!-- Dimension line for openings vertical -->
          <dimline side="right" margin="0.25" elemvecy="1" addminmax="1" addopeningmin="1" addopeningmax="1" minpoints="3" exclude="*" include="*core*" onlyelem="1">
            <text content="OPENING" content_fin="AUKKO" content_nor="ÅPNINGER" textid="projid*20+3" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          
          <dimline side="right" margin="0.25" elemvecy="1" addminmax="1" minpoints="3" exclude="*" includeelem="*core*,*boarding*" onlyelem="1">
            <text content="BOARD" content_fin="LEVY" content_nor="SKIVA" textid="projid*20+8" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          
          <dimline side="right" margin="0.25" elemvecy="1" addminmax="1" minpoints="3" exclude="*" includeelem="*core*,*finish*" onlyelem="1">
            <text content="CLADDING" content_fin="VERHOILU" content_nor="PANEL" textid="projid*20+9" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Dimension line for gable wall top tilted planks -->
          <dimspec type="toptilted" margin="0.3" addminmax="2" anchorfirst="1" anchormid="0" anchorlast="0" ltor="0">
            <dimlinesettings>
              <elemparam name="dimensiontype">cumulative</elemparam>
              <elemparam name="markertype">5</elemparam>
            </dimlinesettings>
          </dimspec>

          <!-- Cross dimension for the element -->
          <dimspec type="cross" anchor="lb">
            <dimlinesettings>
            </dimlinesettings>
          </dimspec>
        </dimlines>

        <!-- Settings for element elevation - to be used in many element definitions -->
        <dimlines id="wall_top" script="dim_scripts" scriptcreate="TopDimLines">
          <!-- Element thickness -->
          <dimline side="right" margin="1.0" elemvecz="1" addminmax="1">
            <dimlinesettings>
              <elemparam name="fontsize">1.5</elemparam>
            </dimlinesettings>
          </dimline>

          <!-- Dimension line for vertical posts cumulative -->
          <dimline side="bottom" margin="0.5" elemvecx="1" addy="1" anchorfirst="1" exclude="*" include="*core*">
            <dimlinesettings>
              <elemparam name="dimensiontype">cumulative</elemparam>
              <elemparam name="markertype">5</elemparam>
            </dimlinesettings>
            <text content="STUD LEFT" content_fin="TOLPPA VASEN" content_nor="STENDERE VENSTRE" textid="projid*20+4" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>
        </dimlines>

        <!-- Settings for element elevation - to be used in many element definitions -->
        <dimlines id="roof_section">
          <!-- Element thickness -->
          <dimline side="right" margin="1.0" elemvecz="1" addminmax="1">
            <dimlinesettings>
              <elemparam name="fontsize">1.5</elemparam>
            </dimlinesettings>
          </dimline>

          <!-- Dimension line for vertical posts cumulative -->
          <dimline side="bottom" margin="0.5" elemvecx="1" addy="1" anchorfirst="1" exclude="intstud*,extstud*">
            <dimlinesettings>
              <elemparam name="dimensiontype">cumulative</elemparam>
              <elemparam name="markertype">5</elemparam>
            </dimlinesettings>
            <text content="RAFTER LEFT" content_fin="VASA VASEN" textid="projid*20+4" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>
        </dimlines>
		
		
        <!-- 2018_03 BEG -->
        <!-- ### 2018_03 JUST FRAMING -->
        <dimlines id="an_framing" script="dim_scripts" scriptcreate="AddCoreModules">
          <!-- Tolpat väli keskellä -->
          <dimline side="bottom" margin="1" elemvecx="1" addy="1" anchormid="1" exclude="*" include="*core*">
            <text content="STUD MID" content_fin="TOLPPA KESKI" content_nor="STENDERE SENTER" textid="projid*20+1" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Dimension line for openings horizontal -->
          <dimline side="bottom" margin="0.25" elemvecx="1" addminmax="1" addopeningmin="1" addopeningmax="1" minpoints="3" exclude="*" include="*core*,*stud*" onlyelem="1">
            <text content="OPENING" content_fin="AUKKO" content_nor="ÅPNINGER" textid="projid*20+3" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Main dimension line showing just element size hor -->
          <dimline side="bottom" margin="0.25" elemvecx="1" elemvecy="0" elemvecz="0" addminmax="1" addx="0" addy="0" addz="0" exclude="*" includeelem="*core*" onlyelem="1">
            <dimlinesettings>
              <elemparam name="fontsize">2</elemparam>
            </dimlinesettings>
          </dimline>

          <!-- Main dimension line showing just element size vert, all omitted settings are 0 -->
          <dimline side="right" margin="1" elemvecy="1" addminmax="1" exclude="*" includeelem="*core*">
            <dimlinesettings>
              <elemparam name="fontsize">2</elemparam>
            </dimlinesettings>
          </dimline>

          <!-- Dimension line for gable wall top tilted planks -->
          <dimspec type="toptilted" margin="0.3" addminmax="2" anchorfirst="0" anchormid="0" anchorlast="1" ltor="0">
            <dimlinesettings>
              <elemparam name="dimensiontype">cumulative</elemparam>
            </dimlinesettings>
          </dimspec>

          <!-- Cross dimension for the element -->
          <dimspec type="cross" anchor="lb">
            <dimlinesettings>
            </dimlinesettings>
          </dimspec>

          <!-- Openings -->
          <dimspec type="opening" include="core" vertdim="1" crossdim="0" vertanchorbot="top" vertopeningbot="1" vertopeningtop="-1">
            <dimlinesettings_vert>
              <elemparam name="dimensiontype">cumulative</elemparam>
              <elemparam name="markertype">5</elemparam>
            </dimlinesettings_vert>
            <dimlinesettings_cross>
            </dimlinesettings_cross>
          </dimspec>
        </dimlines>

        <!-- ### 2018_03 JUST FRAMING AND THEN INSULATION DIM LINE -->
        <dimlines id="an_frame_board_insu">
          <!-- Tolpat väli keskellä -->
          <dimline side="bottom" margin="0.5" elemvecx="1" addy="1" anchorfirst="1" exclude="*" include="*core*">
            <text content="STUD LEFT" content_fin="TOLPPA VASEN" content_nor="STENDERE V" textid="projid*20+1" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Tolpat juokseva -->
          <dimline side="bottom" margin="0.5" elemvecx="1" addy="1" anchorfirst="1" addminmax="2" exclude="*" include="*core*">
            <dimlinesettings>
              <elemparam name="dimensiontype">cumulative</elemparam>
              <elemparam name="markertype">5</elemparam>
            </dimlinesettings>
            <text content="STUD LEFT" content_fin="TOLPPA VASEN" content_nor="STENDERE V" textid="projid*20+2" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Dimension line for openings horizontal -->
          <dimline side="bottom" margin="0.25" elemvecx="1" addminmax="1" addopeningmin="1" addopeningmax="1" minpoints="3" exclude="*" include="*core*,*stud*" onlyelem="1">
            <text content="OPENING" content_fin="AUKKO" content_nor="ÅPNINGER" textid="projid*20+3" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Main dimension line showing just element size hor -->
          <dimline side="bottom" margin="0.25" elemvecx="1" elemvecy="0" elemvecz="0" addminmax="1" addx="0" addy="0" addz="0" exclude="*" includeelem="*core*" onlyelem="1">
            <dimlinesettings>
              <elemparam name="fontsize">2</elemparam>
            </dimlinesettings>
          </dimline>

          <!-- Main dimension line showing just element size vert, all omitted settings are 0 -->
          <dimline side="right" margin="1" elemvecy="1" addminmax="1" exclude="*" includeelem="*core*">
            <dimlinesettings>
              <elemparam name="fontsize">2</elemparam>
            </dimlinesettings>
          </dimline>

          <dimline side="right" margin="0.25" elemvecy="1" addminmax="1" minpoints="3" exclude="*" includeelem="*core*,*boarding*" onlyelem="1">
            <text content="BOARD" content_fin="LEVY" content_nor="SKIVA" textid="projid*20+7" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">2</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Dimension line for openings vertical -->
          <!--dimline side="right" margin="0.25" elemvecy="1" addminmax="1" addopeningmin="1" addopeningmax="1" minpoints="3" exclude="*" include="*core*" onlyelem="1">
            <text content="OPENING" content_fin="AUKKO" content_nor="ÅPNINGER" textid="projid*20+3" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline-->

          <!-- Dimension line for gable wall top tilted planks -->
          <dimspec type="toptilted" margin="0.3" addminmax="2" anchorfirst="1" anchormid="0" anchorlast="0" ltor="0">
            <dimlinesettings>
              <elemparam name="dimensiontype">cumulative</elemparam>
            </dimlinesettings>
          </dimspec>

          <!-- Cross dimension for the element -->
          <dimspec type="cross" anchor="lb">
            <dimlinesettings>
            </dimlinesettings>
          </dimspec>

          <!-- Openings -->
          <dimspec type="opening" include="core" vertdim="1" crossdim="0" vertanchorbot="top" vertopeningbot="1" vertopeningtop="-1">
            <dimlinesettings_vert>
              <elemparam name="dimensiontype">cumulative</elemparam>
              <elemparam name="markertype">5</elemparam>
            </dimlinesettings_vert>
            <dimlinesettings_cross>
            </dimlinesettings_cross>
          </dimspec>

          <dimline side="top" margin="0.25" elemvecx="1" addy="1" anchorfirst="1" anchorlast="1" exclude="*" include="*core*">
            <text content="INSULATION" content_fin="VILLA" content_nor="ISOLASJON" textid="projid*20+4" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <dimline side="top" margin="0.25" elemvecx="1" addminmax="1" addx="1" anchorfirst="1" anchormid="0" anchorlast="1" exclude="*" include="boarding*">
            <dimlinesettings>
            </dimlinesettings>
            <text content="BOARD" content_fin="LEVY" content_nor="SKIVA" textid="projid*20+5" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Boards offset -->
          <dimline side="top" margin="0.25" elemvecx="1" addminmax="1" addx="1" anchorfirst="1" anchormid="0" anchorlast="1" minpoints="3" exclude="*" includeelem="boarding*,core*" onlyelem="1">
            <dimlinesettings>
            </dimlinesettings>
            <text content="BOARD" content_fin="LEVY" content_nor="SKIVA" textid="projid*20+6" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>
        </dimlines>

        <!-- ### 2018_03 INTERIOR STUDDING -->
        <dimlines id="an_horframing">
          <!-- Vaakakoolaus alhaalta -->
          <dimline side="right" margin="0.5" elemvecy="1" addx="1" anchorfirst="1" minpoints="3" exclude="*" include="intstud*">
            <dimlinesettings>
              <elemparam name="dimensiontype">cumulative</elemparam>
              <elemparam name="markertype">5</elemparam>
            </dimlinesettings>
          </dimline>

          <dimline side="right" margin="0.25" elemvecy="1" addminmax="1" minpoints="3" exclude="*" includeelem="*core*,*intstud*" onlyelem="1">
          </dimline>
        </dimlines>


        <!-- ### 2018_03 FRAME + BOARD FROM OUTSIDE -->
        <dimlines id="an_frame_board_ext">
          <!-- Levyt -->
          <dimline side="top" margin="0.25" elemvecx="1" addminmax="1" addx="1" anchorfirst="1" anchormid="0" anchorlast="1" exclude="*" include="boarding_ext*">
            <dimlinesettings>
            </dimlinesettings>
            <text content="BOARD" content_fin="LEVY" content_nor="SKIVA" textid="projid*20+5" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Boards offset -->
          <dimline side="top" margin="0.25" elemvecx="1" addminmax="1" addx="1" anchorfirst="1" anchormid="0" anchorlast="1" minpoints="3" exclude="*" includeelem="boarding_ext*,core*" onlyelem="1">
            <dimlinesettings>
            </dimlinesettings>
            <text content="BOARD" content_fin="LEVY" content_nor="SKIVA" textid="projid*20+6" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Tolpat väli keskellä -->
          <dimline side="bottom" margin="1" elemvecx="1" addy="1" anchormid="1" exclude="*" include="*core*">
            <text content="STUD MID" content_fin="TOLPPA KESKI" content_nor="STENDERE SENTER" textid="projid*20+1" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Tolpat juokseva -->
          <dimline side="bottom" margin="0.5" elemvecx="1" addy="1" anchorfirst="1" addminmax="2" exclude="*" include="*core*">
            <dimlinesettings>
              <elemparam name="dimensiontype">cumulative</elemparam>
              <elemparam name="markertype">5</elemparam>
            </dimlinesettings>
            <text content="STUD LEFT" content_fin="TOLPPA VASEN" content_nor="STENDERE V" textid="projid*20+2" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Dimension line for openings horizontal -->
          <dimline side="bottom" margin="0.25" elemvecx="1" addminmax="1" addopeningmin="1" addopeningmax="1" minpoints="3" exclude="*" include="*core*,*stud*" onlyelem="1">
            <text content="OPENING" content_fin="AUKKO" content_nor="ÅPNINGER" textid="projid*20+2" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Main dimension line showing just element size hor -->
          <dimline side="bottom" margin="0.25" elemvecx="1" elemvecy="0" elemvecz="0" addminmax="1" addx="0" addy="0" addz="0" exclude="*" includeelem="*core*" onlyelem="1">
            <dimlinesettings>
              <elemparam name="fontsize">2</elemparam>
            </dimlinesettings>
          </dimline>

          <!-- Main dimension line showing just element size vert, all omitted settings are 0 -->
          <dimline side="right" margin="1" elemvecy="1" addminmax="1" exclude="*" includeelem="*core*">
            <dimlinesettings>
              <elemparam name="fontsize">2</elemparam>
            </dimlinesettings>
          </dimline>

          <!-- Dimension line for gable wall top tilted planks -->
          <dimspec type="toptilted" margin="0.3" addminmax="2" anchorfirst="1" anchormid="0" anchorlast="0" ltor="0">
            <dimlinesettings>
              <elemparam name="dimensiontype">cumulative</elemparam>
            </dimlinesettings>
          </dimspec>

          <dimspec type="opening" include="core" vertdim="1" crossdim="0" vertanchorbot="top" vertopeningbot="1" vertopeningtop="-1">
            <dimlinesettings_vert>
              <elemparam name="dimensiontype">cumulative</elemparam>
              <elemparam name="markertype">5</elemparam>
            </dimlinesettings_vert>
            <dimlinesettings_cross>
            </dimlinesettings_cross>
          </dimspec>
          
          <!-- Cross dimension for the element -->
          <dimspec type="cross" anchor="lb">
            <dimlinesettings>
            </dimlinesettings>
          </dimspec>
        </dimlines>

        <!-- ### 2018_03 RUNKO (ilmarako) + VERHOILU ULKOAPÄIN -->
        <dimlines id="an_frame_cladding">
          <!-- Tolpat väli keskellä -->
          <dimline side="bottom" margin="1" elemvecx="1" addy="1" anchormid="1" exclude="*" include="*core*">
            <text content="STUD MID" content_fin="TOLPPA KESKI" content_nor="STENDERE SENTER" textid="projid*20+1" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Dimension line for openings horizontal -->
          <dimline side="bottom" margin="0.25" elemvecx="1" addminmax="1" addopeningmin="1" addopeningmax="1" minpoints="3" exclude="*" include="*core*,*stud*" onlyelem="1">
            <text content="OPENING" content_fin="AUKKO" content_nor="ÅPNINGER" textid="projid*20+2" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Main dimension line showing just element size hor -->
          <dimline side="bottom" margin="0.25" elemvecx="1" elemvecy="0" elemvecz="0" addminmax="1" addx="0" addy="0" addz="0" exclude="*" includeelem="*core*" onlyelem="1">
            <dimlinesettings>
              <elemparam name="fontsize">2</elemparam>
            </dimlinesettings>
          </dimline>

          <dimline side="top" margin="0.25" elemvecx="1" addminmax="1" addx="1" minpoints="3" exclude="*" includeelem="*core*,*finish*" onlyelem="1">
            <dimlinesettings>
            </dimlinesettings>
            <text content="CLADDING" content_fin="VERHOILU" content_nor="PANEL" textid="projid*20+3" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Main dimension line showing just element size vert, all omitted settings are 0 -->
          <dimline side="right" margin="1" elemvecy="1" addminmax="1" exclude="*" includeelem="*core*">
            <dimlinesettings>
              <elemparam name="fontsize">2</elemparam>
            </dimlinesettings>
          </dimline>

          <dimline side="right" margin="0.25" elemvecy="1" addminmax="1" minpoints="3" exclude="*" includeelem="*core*,*finish*" onlyelem="1">
            <text content="CLADDING" content_fin="VERHOILU" content_nor="PANEL" textid="projid*20+4" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Dimension line for gable wall top tilted planks -->
          <dimspec type="toptilted" margin="0.3" addminmax="2" anchorfirst="1" anchormid="0" anchorlast="0" ltor="0">
            <dimlinesettings>
              <elemparam name="dimensiontype">cumulative</elemparam>
            </dimlinesettings>
          </dimspec>

          <dimspec type="opening" include="core" vertdim="1" crossdim="0" vertanchorbot="top" vertopeningbot="1" vertopeningtop="-1">
            <dimlinesettings_vert>
              <elemparam name="dimensiontype">cumulative</elemparam>
              <elemparam name="markertype">5</elemparam>
            </dimlinesettings_vert>
            <dimlinesettings_cross>
            </dimlinesettings_cross>
          </dimspec>
          
          <!-- Cross dimension for the element -->
          <dimspec type="cross" anchor="lb">
            <dimlinesettings>
            </dimlinesettings>
          </dimspec>
        </dimlines>


        <!-- ### LEVY -->
        <dimlines id="kw_levy">
          <dimline side="top" margin="0.25" elemvecx="1" addminmax="1" addx="1" anchorfirst="1" anchormid="0" anchorlast="1" exclude="*" include="*boarding*">
            <dimlinesettings>
            </dimlinesettings>
            <text content="BOARD" content_fin="LEVY" content_nor="SKIVA" textid="projid*20+5" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Boards offset -->
          <dimline side="top" margin="0.25" elemvecx="1" addminmax="1" addx="1" anchorfirst="1" anchormid="0" anchorlast="1" minpoints="3" exclude="*" includeelem="*boarding*,*core*" onlyelem="1">
            <dimlinesettings>
            </dimlinesettings>
            <text content="BOARD" content_fin="LEVY" content_nor="SKIVA" textid="projid*20+6" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Main dimension line showing just element size hor -->
          <!--dimline side="bottom" margin="0.75" elemvecx="1" elemvecy="0" elemvecz="0" addminmax="1" addx="0" addy="0" addz="0" exclude="*" includeelem="*boarding*">
            <dimlinesettings>
              <elemparam name="fontsize">2</elemparam>
            </dimlinesettings>
          </dimline-->

          <dimline side="right" margin="0.25" elemvecy="1" addminmax="1" minpoints="3" exclude="*" includeelem="*core*,*boarding*" onlyelem="1">
            <text content="BOARD" content_fin="LEVY" content_nor="SKIVA" textid="projid*20+8" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>
        </dimlines>

        <!-- ### 2xBOARD -->
        <dimlines id="an_board2">
          <dimline side="top" margin="0.25" elemvecx="1" addminmax="1" addx="1" anchorfirst="1" anchormid="0" anchorlast="1" exclude="*" include="*boarding*2">
            <dimlinesettings>
            </dimlinesettings>
            <text content="BOARD1" content_fin="LEVY1" textid="projid*20+5" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <dimline side="top" margin="0.25" elemvecx="1" addminmax="1" addx="1" anchorfirst="1" anchormid="0" anchorlast="1" exclude="*" include="*boarding*3">
            <dimlinesettings>
            </dimlinesettings>
            <text content="BOARD2" content_fin="LEVY2" textid="projid*20+5" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Boards offset -->
          <dimline side="top" margin="0.25" elemvecx="1" addminmax="1" addx="1" anchorfirst="1" anchormid="0" anchorlast="1" minpoints="3" exclude="*" includeelem="*boarding*,*core*" onlyelem="1">
            <dimlinesettings>
            </dimlinesettings>
            <text content="BOARD" content_fin="LEVY" content_nor="SKIVA" textid="projid*20+6" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">1.5</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>

          <!-- Main dimension line showing just element size hor -->
          <!--dimline side="bottom" margin="0.75" elemvecx="1" elemvecy="0" elemvecz="0" addminmax="1" addx="0" addy="0" addz="0" exclude="*" includeelem="*boarding*">
            <dimlinesettings>
              <elemparam name="fontsize">2</elemparam>
            </dimlinesettings>
          </dimline-->

          <dimline side="right" margin="0.25" elemvecy="1" addminmax="1" minpoints="3" exclude="*" includeelem="*core*,*boarding*" onlyelem="1">
            <text content="BOARD" content_fin="LEVY" content_nor="SKIVA" textid="projid*20+8" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">2</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>
        </dimlines>


        <!-- ### INSULATION -->
        <dimlines id="an_insu">
          <dimline side="top" margin="0.25" elemvecx="1" addy="1" anchorfirst="1" anchorlast="1" exclude="*" include="*core*">
            <text content="INSULATION" content_fin="VILLA" content_nor="ISOLASJON" textid="projid*20+1" anchor="6" marg="0.2">
              <elemparam name="pen">1</elemparam>
              <elemparam name="fontname">arial</elemparam>
              <elemparam name="fontsize">2</elemparam>
              <elemparam name="fontstyle"></elemparam>
            </text>
          </dimline>
        </dimlines>

        <!-- 2018_03 END -->

        <dimlines id="dim_wallsect_nowin_horint_10" script="dim_wallsect" scriptcreate="SectDimLines">
          <!-- Base dim lines could be added before script based -->
        </dimlines>

        <dimlines id="dim_wallsect_nowin_horint_10_cum" script="dim_wallsect" scriptcreate="SectDimLinesCum">
          <!-- Base dim lines could be added before script based -->
        </dimlines>
      </dimsettings>

      <!-- For element creation, markings in the element projections -->
      <elemmarkings>
        <elemmarking id="mark_opening">
          <opening text="#id#\n#width#\nx\n#height#">
            <elemparam name="pen">8</elemparam>
            <elemparam name="fontname">Arial</elemparam>
            <elemparam name="fontsize">1.5</elemparam>
            <elemparam name="fontstyle"></elemparam>
            <elemparam name="just">center</elemparam>
            <framelines create="0">
              <elemparam name="pen">1</elemparam>
              <elemparam name="linetype">1</elemparam>
            </framelines>
          </opening>
        </elemmarking>
      </elemmarkings>

      <!-- Predefined settings for various places -->
      <presettings>

        <!-- 2018_03 BEG -->
        <cutlist_table_an11 tab1="0.5" tab2="0.8" tab3="1.2" tab4="1.5" tab5="1.8" boards="0" sortby="len" plankid="-" boardid="#" libpart="{9056D768-6A80-423F-B548-30D0A09D857F}-{DF0D0022-EA4D-4E1B-AFC8-69E66245A8DF}" libscript="cutlist_script_an11">
          <elemparam name="pen">1</elemparam>
          <elemparam name="fontname">Arial</elemparam>
          <elemparam name="fontsize">2.5</elemparam>
          <elemparam name="fontstyle"></elemparam>
        </cutlist_table_an11>

        <cutlist_table_an_single tab1="0.5" tab2="0.8" tab3="1.2" tab4="1.5" tab5="1.8" boards="0" sortby="len" plankid="-" boardid="#" libpart="{9056D768-6A80-423F-B548-30D0A09D857F}-{DF0D0022-EA4D-4E1B-AFC8-69E66245A8DF}" libscript="cutlist_script_an_single">
          <elemparam name="pen">1</elemparam>
          <elemparam name="fontname">Arial</elemparam>
          <elemparam name="fontsize">2.5</elemparam>
          <elemparam name="fontstyle"></elemparam>
        </cutlist_table_an_single>

        <cutlist_table_an_single_boards tab1="0.5" tab2="0.8" tab3="1.2" tab4="1.5" tab5="1.8" boards="0" sortby="len" plankid="-" boardid="#" libpart="{9056D768-6A80-423F-B548-30D0A09D857F}-{DF0D0022-EA4D-4E1B-AFC8-69E66245A8DF}" libscript="cutlist_script_an_single_boards">
          <elemparam name="pen">1</elemparam>
          <elemparam name="fontname">Arial</elemparam>
          <elemparam name="fontsize">2.5</elemparam>
          <elemparam name="fontstyle"></elemparam>
        </cutlist_table_an_single_boards>

        <cutlist_script_an11 ref="elem/settings/presettings/cutlist_script_an">
          <![CDATA[
          gType="1.1"
]]>
        </cutlist_script_an11>

        <cutlist_script_an_single ref="elem/settings/presettings/cutlist_script_an">
          <![CDATA[
          gSingle=true
          gNoBoard=true
]]>
        </cutlist_script_an_single>

        <!-- Referenced from user specific folders - do not remove -->
        <cutlist_script_an_single_boards ref="elem/settings/presettings/cutlist_script_an">
          <![CDATA[
          gSingle=true
]]>
        </cutlist_script_an_single_boards>


        <cutlist_script_an_cabbf ref="elem/settings/presettings/cutlist_script_an">
          <![CDATA[
          gType="ffbc"
]]>
        </cutlist_script_an_cabbf>

        <!-- ### PRESETTINGS TO INCLUDE JUST SOME PARTS PER CUT LIST BEG ### -->

        <!-- Core all -->
        <cutlist_table_coreall libpart="{9056D768-6A80-423F-B548-30D0A09D857F}-{DF0D0022-EA4D-4E1B-AFC8-69E66245A8DF}" libscript="cutlist_script_an">
          <elemparam name="pen">1</elemparam>
          <elemparam name="fontname">Arial</elemparam>
          <elemparam name="fontsize">2.5</elemparam>
          <elemparam name="fontstyle"></elemparam>
          <luasettings>
            <![CDATA[
gListSettings={}
gListSettings.title="#id# CORE"
if gLang=="fin" then
  gListSettings.title="#id# RUNKO"
end

gListSettings.funccollect=function(plank)
  if not plank.elemtype or not string.match(plank.elemtype, "core") then
    return false
  end
  return true
end

gListSettings.addmc=1
gListSettings.addlen=1
gListSettings.cladaddmat=false     -- Must be in every item since this setting is used when the list is first time created
gListSettings.rowheight=nil        -- Use defaults
gListSettings.tablewidth=nil
]]>
          </luasettings>
        </cutlist_table_coreall>

        <!-- Core/studs -->
        <cutlist_table_corestuds libpart="{9056D768-6A80-423F-B548-30D0A09D857F}-{DF0D0022-EA4D-4E1B-AFC8-69E66245A8DF}" libscript="cutlist_script_an">
          <elemparam name="pen">1</elemparam>
          <elemparam name="fontname">Arial</elemparam>
          <elemparam name="fontsize">2.5</elemparam>
          <elemparam name="fontstyle"></elemparam>
          <luasettings>
            <![CDATA[
gListSettings={}
gListSettings.title="#id# STUDS"
if gLang=="fin" then
  gListSettings.title="#id# TOLPAT"
end

gListSettings.funccollect=function(plank)
  if not plank.elemtype or not string.match(plank.elemtype, "core") then
    return false
  end
  if plank.elemtypesort=="002" then   -- Non-vertical piece
    return false
  end
  return true
end

gListSettings.addmc=1
gListSettings.addlen=1
gListSettings.cladaddmat=false     -- Must be in every item since this setting is used when the list is first time created
gListSettings.rowheight=nil        -- Use defaults
gListSettings.tablewidth=nil
]]>
          </luasettings>
        </cutlist_table_corestuds>

        <!-- Core/studs -->
        <cutlist_table_coreothers libpart="{9056D768-6A80-423F-B548-30D0A09D857F}-{DF0D0022-EA4D-4E1B-AFC8-69E66245A8DF}" libscript="cutlist_script_an">
          <elemparam name="pen">1</elemparam>
          <elemparam name="fontname">Arial</elemparam>
          <elemparam name="fontsize">2.5</elemparam>
          <elemparam name="fontstyle"></elemparam>
          <luasettings>
            <![CDATA[
gListSettings={}
gListSettings.title="OTHERS"
if gLang=="fin" then
  gListSettings.title="MUUT"
end

gListSettings.funccollect=function(plank)
  if not plank.elemtype or not string.match(plank.elemtype, "core") then
    return false
  end
  if plank.elemtypesort~="002" then   -- Non-vertical piece
    return false
  end
  return true
end

gListSettings.addmc=1
gListSettings.addlen=1
gListSettings.cladaddmat=false     -- Must be in every item since this setting is used when the list is first time created
gListSettings.rowheight=nil        -- Use defaults
gListSettings.tablewidth=nil
]]>
          </luasettings>
        </cutlist_table_coreothers>


        <!-- Exterior boards -->
        <cutlist_table_extboards libpart="{9056D768-6A80-423F-B548-30D0A09D857F}-{DF0D0022-EA4D-4E1B-AFC8-69E66245A8DF}" libscript="cutlist_script_an">
          <elemparam name="pen">1</elemparam>
          <elemparam name="fontname">Arial</elemparam>
          <elemparam name="fontsize">2.5</elemparam>
          <elemparam name="fontstyle"></elemparam>
          <luasettings>
            <![CDATA[
gListSettings={}
gListSettings.title="BOARD EXT"
if gLang=="fin" then
  gListSettings.title="LEVY ULKO"
end

gListSettings.funccollect=function(plank)
  if not plank.elemtype or not string.match(plank.elemtype, "^boarding_ext.*") then
    return false
  end
  return true
end

gListSettings.addmc=0
gListSettings.addlen=0
gListSettings.cladaddmat=false     -- Must be in every item since this setting is used when the list is first time created
gListSettings.rowheight=nil        -- Use defaults
gListSettings.tablewidth=nil
]]>
          </luasettings>
        </cutlist_table_extboards>

        
        <!-- Exterior cladding & studding -->
        <cutlist_table_extcladstuds libpart="{9056D768-6A80-423F-B548-30D0A09D857F}-{DF0D0022-EA4D-4E1B-AFC8-69E66245A8DF}" libscript="cutlist_script_an">
          <elemparam name="pen">1</elemparam>
          <elemparam name="fontname">Arial</elemparam>
          <elemparam name="fontsize">2.5</elemparam>
          <elemparam name="fontstyle"></elemparam>
          <luasettings>
            <![CDATA[
gListSettings={}
gListSettings.title="CLADDING AND EXT STUDDING"
if gLang=="fin" then
  gListSettings.title="VERHOILU JA UP KOOLAUS"
end

gListSettings.funccollect=function(plank)
  if not plank.elemtype or (not string.match(plank.elemtype, "^finish_ext.*") and not string.match(plank.elemtype, "^extstud.*"))  then
    return false
  end
  return true
end

gListSettings.addmc=0
gListSettings.addlen=1
gListSettings.cladaddmat=false     -- Must be in every item since this setting is used when the list is first time created
gListSettings.rowheight=nil        -- Use defaults
gListSettings.tablewidth=nil
]]>
          </luasettings>
        </cutlist_table_extcladstuds>

        <!-- Just first ext studding -->
        <cutlist_table_extstuds1 libpart="{9056D768-6A80-423F-B548-30D0A09D857F}-{DF0D0022-EA4D-4E1B-AFC8-69E66245A8DF}" libscript="cutlist_script_an">
          <elemparam name="pen">1</elemparam>
          <elemparam name="fontname">Arial</elemparam>
          <elemparam name="fontsize">2.5</elemparam>
          <elemparam name="fontstyle"></elemparam>
          <luasettings>
            <![CDATA[
gListSettings={}
gListSettings.title="EXT STUDDING"
if gLang=="fin" then
  gListSettings.title="UP KOOLAUS"
end

gListSettings.funccollect=function(plank)
  if not plank.elemtype or (plank.elemtype~="extstud" and plank.elemtype~="extstud2") then
    return false
  end
  return true
end

gListSettings.addmc=0
gListSettings.addlen=1
gListSettings.cladaddmat=false     -- Must be in every item since this setting is used when the list is first time created
gListSettings.rowheight=nil        -- Use defaults
gListSettings.tablewidth=nil
]]>
          </luasettings>
        </cutlist_table_extstuds1>

        <!-- Just second ext studding -->
        <cutlist_table_extstuds2 libpart="{9056D768-6A80-423F-B548-30D0A09D857F}-{DF0D0022-EA4D-4E1B-AFC8-69E66245A8DF}" libscript="cutlist_script_an">
          <elemparam name="pen">1</elemparam>
          <elemparam name="fontname">Arial</elemparam>
          <elemparam name="fontsize">2.5</elemparam>
          <elemparam name="fontstyle"></elemparam>
          <luasettings>
            <![CDATA[
gListSettings={}
gListSettings.title="EXT STUDDING"
if gLang=="fin" then
  gListSettings.title="UP KOOLAUS"
end

gListSettings.funccollect=function(plank)
  if not plank.elemtype or plank.elemtype~="extstud3" then
    return false
  end
  return true
end

gListSettings.addmc=0
gListSettings.addlen=1
gListSettings.cladaddmat=false     -- Must be in every item since this setting is used when the list is first time created
gListSettings.rowheight=nil        -- Use defaults
gListSettings.tablewidth=nil
]]>
          </luasettings>
        </cutlist_table_extstuds2>

        <!-- Just cladding -->
        <cutlist_table_extclad libpart="{9056D768-6A80-423F-B548-30D0A09D857F}-{DF0D0022-EA4D-4E1B-AFC8-69E66245A8DF}" libscript="cutlist_script_an">
          <elemparam name="pen">1</elemparam>
          <elemparam name="fontname">Arial</elemparam>
          <elemparam name="fontsize">2.5</elemparam>
          <elemparam name="fontstyle"></elemparam>
          <luasettings>
            <![CDATA[
gListSettings={}
gListSettings.title="CLADDING"
if gLang=="fin" then
  gListSettings.title="VERHOILU"
end

gListSettings.funccollect=function(plank)
  if not plank.elemtype or not string.match(plank.elemtype, "^finish_ext.*") then
    return false
  end
  return true
end

gListSettings.addmc=0
gListSettings.addlen=1
gListSettings.cladaddmat=false     -- Must be in every item since this setting is used when the list is first time created
gListSettings.rowheight=nil        -- Use defaults
gListSettings.tablewidth=nil
]]>
          </luasettings>
        </cutlist_table_extclad>
        
        <!-- Interior boards -->
        <cutlist_table_intboards libpart="{9056D768-6A80-423F-B548-30D0A09D857F}-{DF0D0022-EA4D-4E1B-AFC8-69E66245A8DF}" libscript="cutlist_script_an">
          <elemparam name="pen">1</elemparam>
          <elemparam name="fontname">Arial</elemparam>
          <elemparam name="fontsize">2.5</elemparam>
          <elemparam name="fontstyle"></elemparam>
          <luasettings>
            <![CDATA[
gListSettings={}
gListSettings.title="BOARD INT"
if gLang=="fin" then
  gListSettings.title="LEVY SISÄ"
end

gListSettings.funccollect=function(plank)
  if not plank.elemtype or not string.match(plank.elemtype, "^boarding_int.*") then
    return false
  end
  return true
end

gListSettings.addmc=0
gListSettings.addlen=0
gListSettings.cladaddmat=false     -- Must be in every item since this setting is used when the list is first time created
gListSettings.rowheight=nil        -- Use defaults
gListSettings.tablewidth=nil
]]>
          </luasettings>
        </cutlist_table_intboards>

        <!-- Interior boards -->
        <cutlist_table_intstuds libpart="{9056D768-6A80-423F-B548-30D0A09D857F}-{DF0D0022-EA4D-4E1B-AFC8-69E66245A8DF}" libscript="cutlist_script_an">
          <elemparam name="pen">1</elemparam>
          <elemparam name="fontname">Arial</elemparam>
          <elemparam name="fontsize">2.5</elemparam>
          <elemparam name="fontstyle"></elemparam>
          <luasettings>
            <![CDATA[
gListSettings={}
gListSettings.title="STUDDING INT"
if gLang=="fin" then
  gListSettings.title="SP KOOLAUS"
end

gListSettings.funccollect=function(plank)
  if not plank.elemtype or not string.match(plank.elemtype, "^intstud.*") then
    return false
  end
  return true
end

gListSettings.addmc=0
gListSettings.addlen=0
gListSettings.cladaddmat=false     -- Must be in every item since this setting is used when the list is first time created
gListSettings.rowheight=nil        -- Use defaults
gListSettings.tablewidth=nil
]]>
          </luasettings>
        </cutlist_table_intstuds>
        <!-- ### PRESETTINGS TO INCLUDE JUST SOME PARTS PER CUT LIST END ### -->

        <cutlist_script_an>
          <![CDATA[
EPS=0.0001
gType=nil     -- Other possible values for separate cut lists: ffbc=main framing, main framing, all boards, cladding, 1.1=version 1.1 - include ext studding with cladding


function GetLang()
  local lang
  
  lang=af_request("aflang")
  if lang==nil then
    lang="eng"
  end
  return lang
end


function Len2Str(len)
  return ac_environment("ntos", len, "length", "dim")
end

-- Constructs string for col1 (may be overridden by gListSettings.col1str_plank later on)
function GetCol1Str(item)
  if item.type==4 then
    -- Board, find max size from the polygon
    local   i, count, x1, x2, y1, y2, x, y, s
    
    x1=1e10
    y1=1e10
    x2=-x1
    y2=-y1
    count=ac_objectget("iPolygon", -1)
    for i=1,count do
      x=ac_objectget("iPolygon", i, 1)
      y=ac_objectget("iPolygon", i, 2)
      if x<x1 then
        x1=x
      end
      if x>x2 then
        x2=x
      end
      if y<y1 then
        y1=y
      end
      if y>y2 then
        y2=y
      end
    end

    -- 2018_03 boards named TS 9*width*height, take just first part
    -- Allow also x:
    local i2, sep
    
    s=item.typename
    sep="*"
    i=string.find(s, "*")
    i2=string.find(s, "x")
    if not i or (i and i2 and i2<i) then
      sep="x"
      i=i2
    end
    if i then
      s=string.sub(s, 1, i-1)
    end
    return string.format("%s %s %s %s %s (%s)", s, sep, Len2Str(x2-x1), sep, Len2Str(y2-y1), item.id)
  end

  return item.idgroupshow
end


-- tblguids   in, the planks/boards to process
-- tblPlanks  out, result is saved here
function CollectPlanksBoards( vElem, tblguids, tblPlanks, elemTypeSort, isHor, bPanel )
  local i, v, plankInfo, id, s, pos, item, fillpen, idgroup, idgroupshow, elemgroup, elemTypeSortNow
  local lang
  
  lang=GetLang()
  i=1
	while true do
		v=tblguids[i]
    i=i+1
		if v==nil then
			break
		end

    if v.ispanel~=nil and v.ispanel==1 then
      -- Cladding layer made with ArchiFrameBoardPanel-object
      local tblPtrs, tbl2, i2
      
      tblPtrs=af_request("mc_explodepanel", v.ptr, nil)
      if tblPtrs then
        tbl2={}
        i2=1
        while tblPtrs[i2] do
          tbl2[i2]={}
          tbl2[i2].ptr=tblPtrs[i2]
          i2=i2+1
        end
        CollectPlanksBoards( vElem, tbl2, tblPlanks, elemTypeSort, isHor, true )
      end
    else
      -- Plank/board
		  ac_objectopen(v.ptr)
		  plankInfo=af_request("plankinfo")
      -- Skip all but planks
		  id=ac_objectget("#id")
      s="-"     -- This is the master plank not showing the short ID probably: ac_objectget("iShowIDSep")
      if plankInfo.type==4 then
        s="#"   -- board
      end
      fillpen=ac_objectget("iFillPen")
      elemgroup=ac_objectget("iElemGroup")
        
      if s and id then
        -- Skip element ID
        --pos=string.find(id, s, 1, true)   -- No reverse find in Lua
        pos=string.len(id)
        while pos>=1 do
          if string.sub(id,pos,pos)==s then
            break
          end
          pos=pos-1
        end
        if pos then
          id=string.sub(id, pos+1)
        end
      end

      if isHor then
        -- Horizontal structure
        if elemgroup==nil then
          elemgroup=""
        elseif string.match(elemgroup, "^top%a*") or string.match(elemgroup, "^2ndtop%a*") or string.match(elemgroup, "^contour_x.*") then
          elemgroup="Stud"
          if lang=="fin" then
            elemgroup="Tolppa"
          end
        elseif string.match(elemgroup, "^bottom%a*") or string.match(elemgroup, "^2ndbottom%a*") then
          elemgroup="Stud"
          if lang=="fin" then
            elemgroup="Tolppa"
          end
        elseif string.match(elemgroup, "^vertical_x%a*") or string.match(elemgroup, "^vertical_y%a*") or string.match(elemgroup, "^contourtilted_opening%a*") then
          elemgroup="Door/win"
          if lang=="fin" then
            elemgroup="Ikk/ovi"
          end
        elseif string.match(elemgroup, "^vertical%a*") then
          elemgroup="Hor"
          if lang=="fin" then
            elemgroup="Vaaka"
          end
        elseif string.match(elemgroup, "^contourtilted%a*") then
          elemgroup="Angled"
          if lang=="fin" then
            elemgroup="Vinojuoksu"
          end
        elseif string.match(elemgroup, "^balk.*") then
          elemgroup="Beam"
          if lang=="fin" then
            elemgroup="Palkki"
          end
        elseif string.match(elemgroup, "^lintel.*") then
          elemgroup="W/D beam"
          if lang=="fin" then
            elemgroup="Aukkopalkki"
          end
        elseif string.match(elemgroup, "^reinforce.*") then
          elemgroup="Reinforcement"
          if lang=="fin" then
            elemgroup="Vahvike"
          end
        else
          if elemTypeSort~="030" then     -- Not cladding
            elemgroup="? (" .. elemgroup .. ")"
          else
            elemgroup=""
          end
        end
      else
        -- Vertical structure
        if elemgroup==nil then
          elemgroup=""
        elseif string.match(elemgroup, "^top%a*") or string.match(elemgroup, "^2ndtop%a*") then
          elemgroup="Top plate"
          if lang=="fin" then
            elemgroup="Yläjuoksu"
          end
        elseif string.match(elemgroup, "^bottom%a*") or string.match(elemgroup, "^2ndbottom%a*") then
          elemgroup="Bottom plate"
          if lang=="fin" then
            elemgroup="Alajuoksu"
          end
        elseif string.match(elemgroup, "^contour_x.*") then
          elemgroup="Top/bottom plate"
          if lang=="fin" then
            elemgroup="Ylä/alajuoksu"
          end
        elseif string.match(elemgroup, "^vertical_x%a*") or string.match(elemgroup, "^contourtilted_opening%a*") then
          elemgroup="Win/door"
          if lang=="fin" then
            elemgroup="Ikk/ovi"
          end
        elseif string.match(elemgroup, "^vertical%a*") or string.match(elemgroup, "^contour_y.*") then
          elemgroup="Stud"
          if lang=="fin" then
            elemgroup="Tolppa"
          end
        elseif string.match(elemgroup, "^contourtilted%a*") then
          elemgroup="Angled"
          if lang=="fin" then
            elemgroup="Vinojuoksu"
          end
        elseif string.match(elemgroup, "^balk.*") then
          elemgroup="Beam"
          if lang=="fin" then
            elemgroup="Palkki"
          end
        elseif string.match(elemgroup, "^lintel.*") then
          elemgroup="W/D beam"
          if lang=="fin" then
            elemgroup="Aukkopalkki"
          end
        else
          if elemTypeSort~="030" then     -- Not cladding
            elemgroup="? (" .. elemgroup .. ")"
          else
            elemgroup=""
          end
        end
      end

      elemTypeSortNow=elemTypeSort
      if elemTypeSortNow=="001" then
        if math.abs(plankInfo.vecx.z-1)>EPS then
          -- Ei pysty
          elemTypeSortNow="002"
        end
      end

      if bPanel then
        -- Exploded panels without ID, forget elemgroup
        idgroup=string.format("%s %s %s %s", plankInfo.typename, Len2Str(plankInfo.width), Len2Str(plankInfo.height), Len2Str(plankInfo.len))
        idgroupshow=plankInfo.typename
      else
        idgroup=elemgroup .. " " .. plankInfo.typename .. " (" .. id .. ")"     -- Actually id is last
        idgroupshow=idgroup
      end

      if (bPanel or string.match(vElem.elemtype, "^finish.*")) and gListSettings and gListSettings.cladaddmat then
          -- Add AC 3D material name to the cladding piece
        local smat
        
        smat=" " .. ac_objectget("#matname")
        idgroup=idgroup .. smat
        idgroupshow=idgroupshow .. smat
      end

      s=string.format("%s %s", elemTypeSortNow, idgroup)
  --ac_environment("tolog", s)
      item=tblPlanks[s]
      if item==nil then
        item={}
        item.elemtypesort=elemTypeSortNow
        item.idgroup=idgroup
        item.idgroupshow=idgroupshow
        item.elemtype=vElem.elemtype
        item.id=id
        item.plankinfo=plankInfo
        item.type=plankInfo.type
        item.typename=plankInfo.typename
        item.typewidth=plankInfo.width
        item.typeheight=plankInfo.height
        item.len=plankInfo.len
        item.fillpen=fillpen
        item.tblids={}
        item.tblinfos={}
        item.count=0
        item.col1str=GetCol1Str(item)
        tblPlanks[s]=item
      end

      item.count=item.count+1
      item.tblinfos[item.count]=plankInfo
      
      ac_objectclose()
    end
  end
end


function CmpPlanks( p1, p2 )
  if p1.type~=p2.type then
    return p1.type<p2.type      -- Plank=1, 4=board, planks first
  end
  
  if p1.type==4 then
    -- For boards the sort order is: typename, height, len
    if p1.typename~=p2.typename then
      return p1.typename<p2.typename
    end

    if math.abs(p1.typewidth-p2.typewidth)>0.001 then
      -- Actually for similar type boards the thickness should be the same
      return p1.typewidth>p2.typewidth
    end
    
    if math.abs(p1.typeheight-p2.typeheight)>0.001 then
      return p1.typeheight>p2.typeheight
    end

    if math.abs(p1.len-p2.len)>0.001 then
      return p1.len>p2.len
    end
    
    return false
  end
  
  -- Owning element type
  if p1.elemtypesort~=p2.elemtypesort then
    return p1.elemtypesort<p2.elemtypesort
  end
  
  -- Bigger first
  if math.abs(p1.typewidth-p2.typewidth)>0.001 then
    return p1.typewidth>p2.typewidth
  end

  if math.abs(p1.typeheight-p2.typeheight)>0.001 then
    return p1.typeheight>p2.typeheight
  end
  
  if p1.typename~=p2.typename then
    return p1.typename<p2.typename
  end

  if math.abs(p1.len-p2.len)>0.001 then
    return p1.len>p2.len
  end
  
  return p1.idgroup<p2.idgroup
end


-- Generates info text for current piece
function GetInfoText(tblCurrPlank, bCladding)
  local i, count, res, mc, nUnknown
  local lang
  
  lang=GetLang()
  res=""
  count=ac_objectget("iMc",-1)
  nUnknown=0
  for i=1,count do
    mc=ac_objectget("iMc", i, 1)
    if mc==301 and not bCladding then
      -- Groove
      local side, x1, x2, y1, y2, width, angleDeg, tiltDeg, groType

      x1=ac_objectget("iMc", i, 2)
      y1=ac_objectget("iMc", i, 3)
      x2=ac_objectget("iMc", i, 4)
      y2=ac_objectget("iMc", i, 5)
      depth=ac_objectget("iMc", i, 6)
      width=ac_objectget("iMc", i, 7)
      angleDeg=ac_objectget("iMc", i, 8)
      side=ac_objectget("iMc", i, 9)
      tiltDeg=ac_objectget("iMc", i, 10)
      groType=ac_objectget("iMc", i, 11)

	    if (side==5 or side==6) and groType==0 and angleDeg==0 and tiltDeg==0 and x1<EPS and x2>tblCurrPlank.plankinfo.width-EPS and math.abs(y2-y1)<EPS then
		    -- Move gro to top/bottom if possible
		    if y1<EPS or y1+width+EPS>tblCurrPlank.plankinfo.height then
			    local orgSide, depthOrg

			    orgSide=side
          depthOrg=depth
			    if y1<EPS then
				    side=3
			    else
				    side=1
			    end
			    if orgSide==5 then
				    x1=depth
			    else
				    x1=tblCurrPlank.plankinfo.len
			    end
			    x2=x1
			    y1=0
			    y2=tblCurrPlank.plankinfo.width
			    depth=width
			    width=depthOrg
		    end
	    end

      if (side==3 or side==1) and groType==0 and angleDeg==0 and tiltDeg==0 and y1<EPS and y2>tblCurrPlank.plankinfo.width-EPS and math.abs(x2-x1)<EPS then
        local distBot, distTop, s
        
        distBot=x1-width
        distTop=tblCurrPlank.plankinfo.len-x1

        if res~="" then
          res=res .. ", "
        end
        
        if math.abs(distBot)<0.0004 then
          distBot=0
        end
        if math.abs(distTop)<0.0004 then
          distTop=0
        end

        if tblCurrPlank.plankinfo.vecx.z>0.999 then
          s="front"
          if side==1 then
            s="back"
          end
          if lang=="fin" then
            s="etu"
            if side==1 then
              s="taka"
            end
          end
        else
          s="bottom"
          if side==1 then
            s="top"
          end
          if lang=="fin" then
            s="ala"
            if side==1 then
              s="ylä"
            end
          end
        end

        if math.abs(distBot)<math.abs(distTop) then
          if lang=="fin" then
            s=string.format("Lovi %s %sx%s ar:sta %s", s, Len2Str(depth), Len2Str(width), Len2Str(distBot))
          else
            s=string.format("Slot %s %sx%s from bot %s", s, Len2Str(depth), Len2Str(width), Len2Str(distBot))
          end
        else
          if lang=="fin" then
            s=string.format("Lovi %s %sx%s yr:sta %s", s, Len2Str(depth), Len2Str(width), Len2Str(distTop))
          else
            s=string.format("Slot %s %sx%s from top %s", s, Len2Str(depth), Len2Str(width), Len2Str(distTop))
          end
        end
        res=res .. s
      else
        nUnknown=nUnknown+1
      end
    elseif mc==101 or mc==201 then
      -- Cut beg/end
      local a1, a2, fmt
      
      a1=ac_objectget("iMc", i, 2)
      a2=ac_objectget("iMc", i, 3)
      fmt="Angled beg"
      if mc==201 then
        fmt="Angled end"
      end
      if lang=="fin" then
        fmt="Viiste alku"
        if mc==201 then
          fmt="Viiste loppu"
        end
      end
      

      if res~="" then
        res=res .. ", "
      end
      if math.abs(a1-90)>0.4 and math.abs(a2-90)<0.4 then
        s=string.format("%s %.0f°", fmt, math.abs(a1-90))
      elseif math.abs(a1-90)<0.4 and math.abs(a2-90)>0.4 then
        if lang=="fin" then
          s=string.format("%s korksuunnassa %.1f°", fmt, math.abs(a2-90))
        else
          s=string.format("%s in height dir %.1f°", fmt, math.abs(a2-90))
        end
      else
        if lang=="fin" then
          s=string.format("%s kahteen suuntaan, katso ohje", fmt)
        else
          s=string.format("%s double angled, see detail", fmt)
        end
      end
      res=res .. s
      
    elseif mc==305 then
      -- Lengthwise cut
      local side, x1, width, depth, yoff, angle_c, angle_d, handled, w2, depth, height, plankInfo
      
      side=ac_objectget("iMc", i, 2)
      x1=ac_objectget("iMc", i, 3)
      width=ac_objectget("iMc", i, 4)
      depth=ac_objectget("iMc", i, 5)
      yoff=ac_objectget("iMc", i, 6)
      angle_c=ac_objectget("iMc", i, 7)
      angle_d=ac_objectget("iMc", i, 8)

--ac_environment("tolog", string.format("x1=%f width=%f depth=%f yoff=%f angle_c=%f angle_d=%f", x1, width, depth, yoff, angle_c, angle_d))
      w2=tblCurrPlank.plankinfo.height*0.5
      if x1<0.001 and width<0.001 and math.abs(depth)<0.001 and (side==2 or side==4) then
        if angle_c>0 and math.abs(angle_d)<0.1 then
          -- Top of the surface cut
          -- 0.017453292=PI/180
          depth=w2-yoff
		      height=depth*math.tan(angle_c*0.017453292)
        elseif angle_d>0 and math.abs(angle_c)<0.1 then
          -- Bottom of the surface cut
          depth=w2+yoff
		      height=depth*math.tan(angle_d*0.017453292)
        end
        
		    plankInfo=af_request("plankinfo")
        if depth>0 and height>0 and depth<plankInfo.height and height<plankInfo.width then
		      if res~="" then
			      res=res .. ", "
		      end
          if lang=="fin" then
            s=string.format("viiste %sx%s", Len2Str(depth), Len2Str(height))
          else
            s=string.format("lengthwise cut %sx%s", Len2Str(depth), Len2Str(height))
          end
		      res=res .. s
		      handled=true
        end
	    end
      
      if not handled then
        nUnknown=nUnknown+1
      end
    elseif mc>0 then
        nUnknown=nUnknown+1
    end
  end
  
  if nUnknown>0 and not bCladding then
    if res~="" then
      res=res .. ", "
    end
    if lang=="fin" then
      s=string.format("muita työstöjä %d kpl - katso ohje", nUnknown)
    else
      s=string.format("other cuts %d pcs - see detail", nUnknown)
    end
    res=res .. s
  end
  return res
end


function GetDist3D(c1, c2)
  local dx, dy, dz
  
  dx=c2.x-c1.x
  dy=c2.y-c1.y
  dz=c2.z-c1.z
  dx=math.sqrt(dx*dx + dy*dy + dz*dz)
  return dx
end


function IsNeighbour(item1, item2)
  if GetDist3D(item1.begc, item2.begc)>item1.width+0.001 then
    return false
  end

  if GetDist3D(item1.endc, item2.endc)>item1.width+0.001 then
    return false
  end

  if math.abs(item1.vecx.x-item2.vecx.x)>0.001 or math.abs(item1.vecx.y-item2.vecx.y)>0.001 or math.abs(item1.vecx.z-item2.vecx.z)>0.001 then
    return false
  end

  if math.abs(item1.vecz.x-item2.vecz.x)>0.001 or math.abs(item1.vecz.y-item2.vecz.y)>0.001 or math.abs(item1.vecz.z-item2.vecz.z)>0.001 then
    return false
  end
  
  return true
end


-- Creates string for studs next to each other
-- tblinfos 1-based table of plankinfos
function GetGroupedStudsStr(inStr, tblinfos)
  local i, v, res, tblGroup, tblUsed, i2, added, tblNow, i3, collected, s
  local lang=GetLang()
  
  res=inStr
  tblGroup={}   -- Index=number grouped planks, value=count of groups (not planks)
  tblUsed={}    -- Index=ptr for used planks
  i=1
  while tblinfos[i] do
    v=tblinfos[i]
    if not tblUsed[v.ptr] and v.vecx.z>0.999 and v.type==1 then
      -- Find any connecting
      local x1, x2
      tblUsed[v.ptr]=true
      
      -- Collect the group
      tblNow={}
      tblNow[1]=v
      collected=1

      repeat
        added=false
        i2=i+1
        while tblinfos[i2] do
          for i3=1,collected do
            if IsNeighbour(tblNow[i3], tblinfos[i2]) and tblUsed[tblinfos[i2].ptr]==nil then
              tblUsed[tblinfos[i2].ptr]=true
              collected=collected+1
              tblNow[collected]=tblinfos[i2]
              added=true
              break
            end
          end
          
          i2=i2+1
        end
      until not added
      
      if collected>1 then
        if tblGroup[collected]==nil then
          tblGroup[collected]=0
        end
        tblGroup[collected]=tblGroup[collected]+1
      end
    end
    i=i+1
  end
  
  for i=2,10 do
    if tblGroup[i] then
      if i==2 then
        if lang=="fin" then
          s="tuplatolppa"
        else
          s="double stud"
        end
      else
        if lang=="fin" then
          s=string.format("%d x tolppa", i)
        else
          s=string.format("%d x stud", i)
        end
      end
      
      if res~="" then
        res = res .. ", "
      end
      if lang=="fin" then
        res=res .. string.format("%d kpl %s", tblGroup[i], s)
      else
        res=res .. string.format("%d pcs %s", tblGroup[i], s)
      end
    end
  end

  return res
end


-- Collects all planks&boards related to all element layers
-- Returns it sorted
function DoTable()
	local	s, k, v, i, nElem, vElem, tblQuant, plankInfo, id, item, elemId
  local tblPlanks   -- Also boards, key="type typename length", fields: type (1=plank, 2=log object, 4=board), typename, typewidth, typeheight, len (numeric), tblids=table of plank ids with id=key, count=number of this type
  local tblElemSortToName
  local lang

  lang=GetLang()
  tblQuant=af_request("elem_quantities")

  elemId="(ID MISSING)"
  tblPlanks={}
  tblElemSortToName={}      -- Maps element type sort str -> its name (001->RUNKO, 002->SP KOOLAUS, 003->MUUT)
	for nElem,vElem in ipairs(tblQuant.tblelems) do
    if vElem.elemtype=="core" then
      elemId=vElem.id
    end

    local elemTypeSort, elemTypeName
    
    elemTypeSort="999"
    if lang=="fin" then
      elemTypeName="MUUT"
    else
      elemTypeName="OTHERS"
    end        
    
    if vElem.elemtype=="core" then
      elemTypeSort="001"
      if lang=="fin" then
        elemTypeName="TOLPAT"
      else
        elemTypeName="STUDS"
      end        
      if lang=="fin" then
        tblElemSortToName["002"]="MUUT"
      else
        tblElemSortToName["002"]="OTHERS"
      end
    elseif string.match(vElem.elemtype, "^intstud*") then
      elemTypeSort="010"
      if lang=="fin" then
        elemTypeName="SISÄKOOLAUS"
      else
        elemTypeName="INT STUDDING"
      end        
    elseif string.match(vElem.elemtype, "^extstud*") then
      elemTypeSort="020"
      if lang=="fin" then
        elemTypeName="ULKOKOOLAUS"
      else
        elemTypeName="EXT STUDDING"
      end
    elseif string.match(vElem.elemtype, "^finish_ext*") then
      elemTypeSort="030"    -- This number used not to include mc-info
      if lang=="fin" then
        elemTypeName="VERHOILU"
      else
        elemTypeName="CLADDING"
      end
    elseif string.match(vElem.elemtype, "^boarding_ext*") then
      elemTypeSort="040"
      if lang=="fin" then
        elemTypeName="LEVY ULKO"
      else
        elemTypeName="BOARD EXT"
      end
    elseif string.match(vElem.elemtype, "^boarding_int*") then
      elemTypeSort="050"
      if lang=="fin" then
        elemTypeName="LEVY SISÄ"
      else
        elemTypeName="BOARD INT"
      end
    end

    if elemTypeSort then
      local isHor
      
      isHor=false
      if vElem.templateid and (vElem.templateid=="framing_horlong" or vElem.templateid=="framinghor1") then
        isHor=true
      end
    
      tblElemSortToName[elemTypeSort]=elemTypeName
		  if vElem.tblboards and (not vElem.tblplanks or vElem.layertypenum~=2) then
        if not gNoBoard or (elemTypeSort~="040" and elemTypeSort~="050") then
          CollectPlanksBoards( vElem, vElem.tblboards, tblPlanks, elemTypeSort )
        end
      end

		  if vElem.tblplanks then
        CollectPlanksBoards( vElem, vElem.tblplanks, tblPlanks, elemTypeSort, isHor )
      end
    end
  end

  -- Sort by type, len
  local tblPlanksSort, bCladding
  
  tblPlanksSort={}
  i=0
  for k,v in pairs(tblPlanks) do
    i=i+1
    tblPlanksSort[i]=v
    
    bCladding=false
    if v.elemtypesort=="030" then
      bCladding=true
    end
    
    ac_objectopen(v.plankinfo.ptr)
    v.infotext=GetInfoText(v, bCladding)
    ac_objectclose()
  end

  table.sort( tblPlanksSort, CmpPlanks )
  return tblPlanksSort, tblElemSortToName, elemId
 end


-- nSeqNum: 0=tolpat, 1=juoksut, 2=TS-levyt, 3=verhoilu, (lopulta 4=eristeet), 4=sisäkoolaus
function DoCutList(nSeqNum, sSettingsLua)
	local	s, k, v, i, nElem, vElem, tblQuant, plankInfo, id, item
  local tblPlanks   -- Also boards, key="type typename length", fields: type (1=plank, 2=log object, 4=board), typename, typewidth, typeheight, len (numeric), tblids=table of plank ids with id=key, count=number of this type
  local tblCollElemTypes, typeName
  local addMc, addLen
  local lang=GetLang()
  local filterFunc
  
  addMc=0
  addLen=1
  gListSettings=nil
  if sSettingsLua and sSettingsLua~="" then
    -- String contains lua script that fills global gListSettings
    local f
    
--ac_environment("tolog", string.format("SETTINGS: %s", sSettingsLua))
    f=loadstring(sSettingsLua)
    if not f then
      ac_environment("tolog", string.format("Cut list: Bad settings Lua-script: %s", sSettingsLua))
    end
    f()   -- Creates gListSettings
    if gListSettings.addmc and gListSettings.addmc==1 then
      addMc=1
    end
    if gListSettings.addlen and gListSettings.addlen==0 then
      addLen=0
    end
    filterFunc=gListSettings.funccollect
  end

  if not g_tblPlanksSort then
    g_tblPlanksSort, g_tblElemSortToName, g_elemId=DoTable()
  end
  
  if not nSeqNum then
    ac_environment("tolog", "DoCutList(nSeqNum): nSeqNum missing - old program version, update ArchiFrame")
    nSeqNum=0
  end
  
  -- what to collect
  
  tblCollElemTypes={}

  typeName=g_tblElemSortToName["001"]

  if gListSettings then
    -- NOP on purpose
  elseif gType and gType=="ffbc" then
    if nSeqNum==0 then
      typeName=g_tblElemSortToName["001"]
      tblCollElemTypes["001"]=true
      tblCollElemTypes["999"]=true
      addMc=1
    elseif nSeqNum==1 then
      typeName=g_tblElemSortToName["002"]
      tblCollElemTypes["002"]=true
      addMc=1   -- Juoksuihin myös työstöt 1/2018
    elseif nSeqNum==2 then
      -- Windshield boards
      typeName=g_tblElemSortToName["040"]
      tblCollElemTypes["040"]=true
      addLen=0
    elseif nSeqNum==3 then
      if lang=="fin" then
        typeName="ULKOKOOLAUS JA VERHOILU"
      else
        typeName="EXT STUD AND CLADDING"
      end
      tblCollElemTypes["030"]=true
      tblCollElemTypes["020"]=true
    else
      ac_environment("tolog", string.format("DoCutList(nSeqNum=%d): Bad nSeqNum - nothing collected", nSeqNum))
      typeName="NONE"
    end
  elseif not gSingle then
    if nSeqNum==0 then
      typeName=g_tblElemSortToName["001"]
      tblCollElemTypes["001"]=true
      tblCollElemTypes["999"]=true
      addMc=1
    elseif nSeqNum==1 then
      typeName=g_tblElemSortToName["002"]
      tblCollElemTypes["002"]=true
      addMc=1   -- Juoksuihin myös työstöt 1/2018
    elseif nSeqNum==2 then
      -- Windshield boards
      typeName=g_tblElemSortToName["040"]
      tblCollElemTypes["040"]=true
      addLen=0
    elseif nSeqNum==3 then
      typeName=g_tblElemSortToName["030"]
      tblCollElemTypes["030"]=true
      if gType and gType=="1.1" then
        -- ext studding will be collected first
        tblCollElemTypes["020"]=true
        if lang=="fin" then
          typeName="ULKOKOOLAUS"
        else
          typeName="EXT STUDDING"
        end
      end
    elseif nSeqNum==4 then
      typeName=g_tblElemSortToName["010"]
      tblCollElemTypes["010"]=true
    elseif nSeqNum==5 then
      typeName=g_tblElemSortToName["050"]
      tblCollElemTypes["050"]=true
      addLen=0
    else
      ac_environment("tolog", string.format("DoCutList(nSeqNum=%d): Bad nSeqNum - nothing collected", nSeqNum))
      typeName="NONE"
    end
  end

  if gSingle and addMc==0 then
    -- Add mc row if it is used
    for k,v in ipairs(g_tblPlanksSort) do
      if v.infotext and v.infotext~="" then
        addMc=1
        break
      end
    end
  end

  local nRow, nHeightRows, rowHeight

  ac_objectopen(nil)      -- ### Table object opened
  
  -- Settings
  local bImperial
  
  rowHeight=0.170
  if gListSettings and gListSettings.rowheight then
    rowHeight=gListSettings.rowheight
  end
  
  ac_objectset("#pen", 1)
  bImperial=false
  nRow,s=ac_environment("units", "length", "dim")
  if nRow and nRow>2 and s~="mm" then
    bImperial=true
  end
  
  ac_objectset("iFontName", "Arial")
  ac_objectset("iRowHeight", rowHeight)
  ac_objectset("iMargin", rowHeight*0.1)
  ac_objectset("iColCount", 2+addMc+addLen)
  if addMc~=0 then
    if bImperial then
      ac_objectset("iColWidth", 0.31, 1)
      ac_objectset("iColWidth", 0.18, 2)
      ac_objectset("iColWidth", 0.06, 3)
      ac_objectset("iColWidth", 0.45, 4)
      ac_objectset("A", 5.0)
    else
      ac_objectset("iColWidth", 0.42, 1)
      ac_objectset("iColWidth", 0.10, 2)
      ac_objectset("iColWidth", 0.08, 3)
      ac_objectset("iColWidth", 0.40, 4)
      ac_objectset("A", 4.5)
    end
  else
    if addLen~=0 then
      ac_objectset("iColWidth", 0.70, 1)
      ac_objectset("iColWidth", 0.20, 2)
      ac_objectset("iColWidth", 0.10, 3)
    else
      -- Just two cols
      ac_objectset("iColWidth", 0.875, 1)
      ac_objectset("iColWidth", 0.125, 2)
    end
    ac_objectset("A", 3.5)
  end
  if gListSettings and gListSettings.tablewidth then
    ac_objectset("A", gListSettings.tablewidth)
  end
  
  if not typeName then
    typeName="(EMPTY)"
  end

  -- Title
  nRow=1
  nHeightRows=1
  if gListSettings and gListSettings.title then
    s=gListSettings.title
    s=ac_environment("strreplace", gListSettings.title, "#id#", g_elemId)
    ac_objectset("iRows", "<b><vtop><left><nolines><merge 4>" .. s, 1, 1)
  else
    if nSeqNum==0 then
      ac_objectset("iRows", "<mulheight 1><b><vtop><left><nolines><merge 4>" .. g_elemId .. " " .. typeName, 1, 1)
    else
      ac_objectset("iRows", "<b><vtop><left><nolines><merge 4>" .. typeName, 1, 1)
    end
   end
  
  -- Column headers
  nRow=nRow+1
  nHeightRows=nHeightRows+1
  if lang=="fin" then
    ac_objectset("iRows", "<b><left>Tyyppi", nRow, 1)
    ac_objectset("iRows", "<b>Pit", nRow, 2)
    ac_objectset("iRows", "<b>Kpl", nRow, 2+addLen)
    if addMc~=0 then
      ac_objectset("iRows", "<b><left>Työstöt", nRow, 4)
    end
  else
    ac_objectset("iRows", "<b><left>Type", nRow, 1)
    ac_objectset("iRows", "<b>Len", nRow, 2)
    ac_objectset("iRows", "<b>Pcs", nRow, 2+addLen)
    if addMc~=0 then
      ac_objectset("iRows", "<b><left>Cut info", nRow, 4)
    end
  end
  
  local   isFirst , prevelemtypesort
  local   tblTexts, tblCurrText, nTexts, addType
  local   str, tblPlanksNow
  
  prevelemtypesort="__not_existing__"
  addEmpty=false
  addType=false
  tblPlanksNow=g_tblPlanksSort
  
  if filterFunc then
    -- 1/2019 made mechanism: collect only needed ones now and prehaps resort
    local i2

    tblPlanksNow={}
    i2=0
    for k,v in ipairs(g_tblPlanksSort) do
      if filterFunc(v) then
        i2=i2+1
        tblPlanksNow[i2]=v
      end
    end      
  end
  
  local nResCode=0
  
  for k,v in ipairs(tblPlanksNow) do
--ac_environment("tolog", string.format("v.typename=%s\n", v.typename))
    if gSingle or tblCollElemTypes[v.elemtypesort] or filterFunc then
      nRow=nRow+1
      nHeightRows=nHeightRows+1

      if v.elemtypesort~=prevelemtypesort then
        -- Element type changes
        prevelemtypesort=v.elemtypesort
        if addEmpty then
          ac_objectset("iRows", "<nolines><merge 4>", nRow, 1)
          nRow=nRow+1
          nHeightRows=nHeightRows+1
        end

        if addType then
          -- Add material type to col1
          ac_objectset("iRows", string.format("<left><nolines><merge 4><b>%s", g_tblElemSortToName[prevelemtypesort]), nRow, 1)
          nRow=nRow+1
          nHeightRows=nHeightRows+1
        end
        addType=true
      end
    
      -- Add material type to col1
      nResCode=1
      s=""
      if false and v.fillpen and v.fillpen>0 then
        -- Material fill pen to table background color
        s=string.format("<fillrgb %d>", v.fillpen)
      end
      str=v.col1str
      if v.type==1 and gListSettings and gListSettings.col1str_plank then
        -- Plank, parse it here
        str=ac_environment("strreplace", gListSettings.col1str_plank, "#id#", v.id)
        str=ac_environment("strreplace", str, "#matwidth#", ac_environment("ntos", v.typewidth, "length", "dim"))
        str=ac_environment("strreplace", str, "#matheight#", ac_environment("ntos", v.typeheight, "length", "dim"))
        str=ac_environment("strreplace", str, "#len#", ac_environment("ntos", v.len, "length", "dim"))
      end
      ac_objectset("iRows", string.format("<left>%s%s", s, str), nRow, 1)
      
      -- Rest
      if addLen~=0 then
        ac_objectset("iRows", "<right>" .. Len2Str(v.len), nRow, 2)
      end
      ac_objectset("iRows", string.format("%d", v.count), nRow, 2+addLen)
    
      if addMc~=0 then
        str=v.infotext
        if v.elemtypesort=="001" then
          str=GetGroupedStudsStr(str, v.tblinfos)
        end
        ac_objectset("iRows", "<left>" .. str, nRow, 4)
      end
      addEmpty=true
    end
  end
  ac_objectset("B", nHeightRows*rowHeight)

  ac_objectclose()        -- ### Table object
  
  return nResCode
end

gLang=GetLang()           -- Make it global for 
]]>
        </cutlist_script_an>
        <!-- 2018_03 END -->


        <!-- Used for cutlists -->
        <cutlist tab1="0.5" tab2="0.8" tab3="1.2" tab4="1.5" tab5="1.8" boards="1" sortby="len" plankid="-" boardid="#">
          <elemparam name="pen">1</elemparam>
          <elemparam name="fontname">Arial</elemparam>
          <elemparam name="fontsize">2.5</elemparam>
          <elemparam name="fontstyle"></elemparam>
        </cutlist>

        <!-- Using table and script -->
        <cutlist_table tab1="0.5" tab2="0.8" tab3="1.2" tab4="1.5" tab5="1.8" boards="1" sortby="len" plankid="-" boardid="#" libpart="{9056D768-6A80-423F-B548-30D0A09D857F}-{DF0D0022-EA4D-4E1B-AFC8-69E66245A8DF}" libscript="cutlist_table_script">
          <elemparam name="pen">1</elemparam>
          <elemparam name="fontname">Arial</elemparam>
          <elemparam name="fontsize">2.5</elemparam>
          <elemparam name="fontstyle"></elemparam>
        </cutlist_table>


        <cutlist_table_script>
          <![CDATA[
-- tblguids   in, the planks/boards to process
-- tblPlanks  out, result is saved here
function CollectPlanksBoards( tblguids, tblPlanks )
  local i, v, plankInfo, id, s, pos, item, fillpen

  i=1
	while true do
		v=tblguids[i]
    i=i+1
		if v==nil then
			break
		end
        
		ac_objectopen(v.ptr)
		plankInfo=af_request("plankinfo")
		id=ac_objectget("#id")
    s="-"     -- This is the master plank not showing the short ID probably: ac_objectget("iShowIDSep")
    if plankInfo.type==4 then
      s="#"   -- board
    end
    fillpen=ac_objectget("iFillPen")
    ac_objectclose()
        
    if s and id then
      -- Skip element ID
      --pos=string.find(id, s, 1, true)   -- No reverse find in Lua
      pos=string.len(id)
      while pos>=1 do
        if string.sub(id,pos,pos)==s then
          break
        end
        pos=pos-1
      end
      if pos then
        id=string.sub(id, pos+1)
      end
    end

    s=string.format("%d %s %s", plankInfo.type, plankInfo.typename, ac_environment("ntos", plankInfo.len, "length", "work"))
    item=tblPlanks[s]
    if item==nil then
      item={}
      item.type=plankInfo.type
      item.typename=plankInfo.typename
      item.typewidth=plankInfo.width
      item.typeheight=plankInfo.height
      item.len=plankInfo.len
      item.fillpen=fillpen
      item.tblids={}
      item.count=0
      tblPlanks[s]=item
    end

    if item.tblids[id]==nil then
      item.tblids[id]=1
    else
      item.tblids[id]=item.tblids[id]+1
    end
    item.count=item.count+1
  end
end


function CmpPlanks( p1, p2 )
  if p1.type~=p2.type then
    return p1.type<p2.type      -- Plank=1, 4=board, planks first
  end
  
  if p1.type==4 then
    -- For boards the sort order is: typename, height, len
    if p1.typename~=p2.typename then
      return p1.typename<p2.typename
    end

    if math.abs(p1.typewidth-p2.typewidth)>0.001 then
      -- Actually for similar type boards the thickness should be the same
      return p1.typewidth>p2.typewidth
    end
    
    if math.abs(p1.typeheight-p2.typeheight)>0.001 then
      return p1.typeheight>p2.typeheight
    end

    if math.abs(p1.len-p2.len)>0.001 then
      return p1.len>p2.len
    end
    
    return false
  end
  
  -- Bigger first
  if math.abs(p1.typewidth-p2.typewidth)>0.001 then
    return p1.typewidth>p2.typewidth
  end

  if math.abs(p1.typeheight-p2.typeheight)>0.001 then
    return p1.typeheight>p2.typeheight
  end
  
  if p1.typename~=p2.typename then
    return p1.typename<p2.typename
  end

  if math.abs(p1.len-p2.len)>0.001 then
    return p1.len>p2.len
  end

  return false
end


function DoCutList()
	local	s, k, v, i, nElem, vElem, tblQuant, plankInfo, id, item, elemId
  local tblPlanks   -- Also boards, key="type typename length", fields: type (1=plank, 2=log object, 4=board), typename, typewidth, typeheight, len (numeric), tblids=table of plank ids with id=key, count=number of this type

  tblQuant=af_request("elem_quantities")

  elemId="(ID MISSING)"
  tblPlanks={}
	for nElem,vElem in ipairs(tblQuant.tblelems) do
    if vElem.elemtype=="core" then
      elemId=vElem.id
    end

		if vElem.tblboards then
      -- No boards: CollectPlanksBoards( vElem.tblboards, tblPlanks )
    end

		if vElem.tblplanks then
      CollectPlanksBoards( vElem.tblplanks, tblPlanks )
    end
  end

  -- Sort by type, len
  local tblPlanksSort
  
  tblPlanksSort={}
  i=0
  for k,v in pairs(tblPlanks) do
    i=i+1
    tblPlanksSort[i]=v
  end

  table.sort( tblPlanksSort, CmpPlanks )
  
  local nRow, nHeightRows, rowHeight

  ac_objectopen(nil)      -- ### Table object opened
  
  -- Settings
  rowHeight=0.100
  ac_objectset("#pen", 1)
  
  ac_objectset("iFontName", "Arial")
  ac_objectset("iRowHeight", rowHeight)
  ac_objectset("iMargin", rowHeight*0.1)
  ac_objectset("iColCount", 4)
  ac_objectset("iColWidth", 0.25, 1)
  ac_objectset("iColWidth", 0.25, 2)
  ac_objectset("iColWidth", 0.25, 3)
  ac_objectset("iColWidth", 0.25, 4)
  --ac_objectset("iColWidth", 0.25, 5)
  
  ac_objectset("A", 2)   -- (2.4385 m=8 feet)

  -- Title
  nRow=2
  nHeightRows=3   -- In row height
  ac_objectset("iRows", "<mulheight 2><u><b><vtop><left><nolines><merge 4>" .. elemId, 1, 1)
  ac_objectset("iRows", "<left><nolines><merge 4>", 2, 1)     -- Empty line

  -- Column headers
  nRow=nRow+1
  nHeightRows=nHeightRows+1
  ac_objectset("iRows", "MATERIAL", nRow, 1)
  ac_objectset("iRows", "PIECE", nRow, 2)
  ac_objectset("iRows", "QTY", nRow, 3)
  ac_objectset("iRows", "LENGTH", nRow, 4)
  --ac_objectset("iRows", "REMARKS", nRow, 5)
  
  -- All plank types
  local   prevtype, kid, vid, isFirst 
  
  prevtype="__not_existing__"
  addEmpty=false
  for k,v in ipairs(tblPlanksSort) do
--ac_environment("tolog", string.format("v.typename=%s\n", v.typename))
  
    nRow=nRow+1
    nHeightRows=nHeightRows+1
    if v.typename~=prevtype then
      if addEmpty then
        ac_objectset("iRows", "<nolines><merge 4>", nRow, 1)
        nRow=nRow+1
        nHeightRows=nHeightRows+1
      end

      addEmpty=true
      -- Add material type to col1
      s=""
      if v.fillpen and v.fillpen>0 then
        -- Material fill pen to table background color
        s=string.format("<fillrgb %d>", v.fillpen)
      end
      ac_objectset("iRows", string.format("%s%s", s, v.typename), nRow, 1)
      
      prevtype=v.typename
    end

    
    -- IDs
    id=""
    for kid,vid in pairs(v.tblids) do
      if id~="" then
        id=id .. " "
      end
      id=id .. kid
    end
    ac_objectset("iRows", id, nRow, 2)

    -- Rest
    ac_objectset("iRows", string.format("%d", v.count), nRow, 3)
    ac_objectset("iRows", "<right>" .. ac_environment("ntos", v.len, "length", "dim"), nRow, 4)
    ac_objectset("iRows", "~", nRow, 5)
  end
  ac_objectset("B", nHeightRows*rowHeight)

  ac_objectclose()        -- ### Table object
end
]]>
        </cutlist_table_script>

        
        <!-- Bottom wood markings -->
        <markings id="mark_default">
          <bottomwood>
            <stud line="3" id="2" idline="1" markxpos="2" markypos="1" marksize="0" marktextdir="1"></stud>
            <opening line="1" windowtext="Window [width]x[height]" doortext="Door [width]x[height]" windowtext_fin="Ikk [width]x[height]" doortext_fin="Ovi [width]x[height]" windowtext_nor="Vindu [width]x[height]" doortext_nor="Dør [width]x[height]" windowtext_swe="Fönster [width]x[height]" doortext_swe="Dörr [width]x[height]"></opening>
            <neighbour begtext="&lt;[id]" endtext="[id]&gt;" marksize="0" marktextdir="1"></neighbour>
          </bottomwood>
        </markings>

        <!-- Used for element stamp -->
        <elemstamp>
          <elemparam name="pen">1</elemparam>
          <objparam name="iFont">Arial</objparam>
          <objparam name="A">10</objparam>
          <objparam name="B">1</objparam>

          <objparam name="iName1">ID</objparam>
          <objparam name="iName2">Type</objparam>
          <objparam name="iName3">Date</objparam>
          <objparam name="iName4">Project</objparam>
          <objparam name="iName5">Designer</objparam>
          <objparam name="iName6">Project num</objparam>
          <objparam name="iName7"></objparam>
        </elemstamp>

        <freeprojections>
          <projection id="freeproj_default" name="Zero depth no dim lines" name_fin="Nollasyvyinen ilman mittoja" exclude="" boardpanels="*" depth="0" zoom="1">
          </projection>

          <projection id="freeproj_100_rot90" name="Zero depth no dim lines rotate +90" name_fin="Nollasyvyinen ilman mittoja kierto +90" exclude="" boardpanels="*" depth="0" zoom="1" rotate="90">
          </projection>

          <projection id="freeproj_100_rotm90" name="Zero depth no dim lines rotate -90" name_fin="Nollasyvyinen ilman mittoja kierto -90" exclude="" boardpanels="*" depth="0" zoom="1" rotate="-90">
          </projection>

          <projection id="wallsect_100_10" name="Zero depth with dim lines 100% v 1.0" name_fin="Nollasyvyinen mitoilla 100% v 1.0" exclude="" boardpanels="*" depth="0" zoom="1">
            <dimlines>
              <dimline ref="dim_wallsect_nowin_horint_10"></dimline>
            </dimlines>
          </projection>

          <projection id="freeproj_100_rot90d" name="Zero depth dim lines rotate +90" name_fin="Nollasyvyinen mitoilla kierto +90" exclude="" boardpanels="*" depth="0" zoom="1" rotate="90">
            <dimlines>
              <dimline ref="dim_wallsect_nowin_horint_10"></dimline>
            </dimlines>
          </projection>

          <projection id="freeproj_100_rotm90d" name="Zero depth dim lines rotate -90" name_fin="Nollasyvyinen mitoilla kierto -90" exclude="" boardpanels="*" depth="0" zoom="1" rotate="-90">
            <dimlines>
              <dimline ref="dim_wallsect_nowin_horint_10"></dimline>
            </dimlines>
          </projection>

          <projection id="wallsect_core_100_10" name="Zero depth core only with dim lines 100% v 1.0" name_fin="Nollasyvyinen pelkkä runko mitoilla 100% v 1.0" exclude="*" include="core" depth="0" zoom="1">
            <dimlines>
              <dimline ref="dim_wallsect_nowin_horint_10"></dimline>
            </dimlines>
          </projection>

          <projection id="wallsect_200_10" name="Zero depth with dim lines 200% v 1.0" name_fin="Nollasyvyinen mitoilla 200% v 1.0" exclude="" boardpanels="*" depth="0" zoom="2">
            <dimlines>
              <dimline ref="dim_wallsect_nowin_horint_10"></dimline>
            </dimlines>
          </projection>

          <projection id="wallsect_core_200_10" name="Zero depth core only with dim lines 200% v 1.0" name_fin="Nollasyvyinen pelkkä runko mitoilla 200% v 1.0" exclude="*" include="core" depth="0" zoom="2">
            <dimlines>
              <dimline ref="dim_wallsect_nowin_horint_10"></dimline>
            </dimlines>
          </projection>
        </freeprojections>
      </presettings>

      <!-- Scripts used many times -->
      <scripts>
        <script id="dim_scripts">
          <![CDATA[
-- Returns cos angle of the vectors if normalized
function CalcDot3D( x1, y1, z1, x2, y2, z2 )
	return x1 * x2 + y1 * y2 + z1 * z2;
end


-- Segment handling beg ***
-- Data is 1-based table of structs having fields x1,x2
function SegInitSingle(x1, x2)
  local tblCoords,t

  t={}
  t.x1=x1
  t.x2=x2
  tblCoords={}
  tblCoords[1]=t
  return tblCoords
end

-- Returns new segment array taking x1,x2 away from seg
function SegDifference(seg, x1, x2)
  local u1, curr1, currx1, currx2
  local tblDest, destn, t
  local eps=0.0005

  tblDest={}
  destn=0
  for u1,curr1 in ipairs(seg) do
    currx1=curr1.x1
    currx2=curr1.x2
    if currx1+eps>x2 or currx2-eps<x1 then
      -- No removing, add as whole
      t={}
      t.x1=currx1
      t.x2=currx2
      destn=destn+1
      tblDest[destn]=t
    else
      -- Perhaps overlaps, add perhaps split parts
      if currx1<x1-eps then
        t={}
        t.x1=currx1
        t.x2=x1
        destn=destn+1
        tblDest[destn]=t
      end
      
      if currx2>x2+eps then
        t={}
        t.x1=x2
        t.x2=currx2
        destn=destn+1
        tblDest[destn]=t
      end
    end
  end
  
  return tblDest
end

function SegDump(prompt, seg)
  local u1, curr1, s
  
  s=prompt
  for u1,curr1 in ipairs(seg) do
    s=s..string.format(" x1=%f x2=%f", curr1.x1, curr1.x2)
  end
  ac_environment("tolog", s)
end

-- Segment handling end ***


-- Dim line creator uses to find just first stud in stud groups
function FindCoreStudGroupsForDim()
  local i, n, s
  local tblRes, tbl, info, elemdata
  local tblProjInfo, projinfo						-- Projection infos for owning elements, key=element guid
  local typetag

  tblRes={}
  tblProjInfo={}
  n=0
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    info=af_request("plankinfo")
    tbl=ac_objectget("#af_elemdata")   -- To get typetag also
    typetag=nil
    if tbl then
      typetag=tbl.typetag
    end
    ac_objectclose()
	  if info.ownerelemguid==nil and info.masterelemguid then
		  -- Take the 3D piece
		  info=af_request("plankinfo", info.masterelemguid)
	  end
    if info.type==1 and info.ownerelemguid then   -- type 1 is plank
      --Not available since may be owned by any element object in the group: elemdata=ac_objectget("#af_elemdata")   
  	  projinfo=tblProjInfo[info.ownerelemguid]
	    if not projinfo then
		    projinfo=af_request("plankinfo", info.ownerelemguid)
		    projinfo.vecz,projinfo.vecy=projinfo.vecy, projinfo.vecz			-- Swap these for projection world
		    tblProjInfo[info.ownerelemguid]=projinfo
	    end

	    -- Get it again to get elemdata
	    info=af_request("plankinfo", info.guid, projinfo)
      elemdata=info.elemdata
      if math.abs(elemdata.x1-elemdata.x2)<0.001 and (typetag==nil or typetag=="core") then   -- and math.abs(elemdata.z1-elemdata.z2)<0.001 and elemdata.y2-elemdata.y1>0.01 and elemdata.y1<0.2 then
        tbl={}
        tbl.index=i
        tbl.anchorfirst=1
        tbl.anchormid=0
        tbl.anchorlast=0
        tbl.elemdata=elemdata
        n=n+1
        tblRes[n]=tbl
      end
    end
  end
  
  local tblRes2, i1, i2, bx2
  
  table.sort( tblRes,  function(p1, p2)
                            return p1.elemdata.bx1<p2.elemdata.bx1
                          end )

  -- Remove touching pieces
  tblRes2={}
  i2=0
  i1=1
  while i1<=n do
    i2=i2+1
    tblRes2[i2]=tblRes[i1]
    bx2=tblRes2[i2].elemdata.bx2+0.005      -- 0.005 is min space between planks set in own elem rules
    i1=i1+1
    while i1<=n do
      if tblRes[i1].elemdata.bx1>bx2+0.001 then
        break
      end
      if tblRes[i1].elemdata.bx2>bx2 then
        bx2=tblRes[i1].elemdata.bx2+0.005   -- 0.005 is min space between planks set in own elem rules
      end
      i1=i1+1
    end
  end

  return tblRes2
end


-- MODULES

function MakeTextXml(content, textid)
  local s
  s=   "<text content=\"" .. content .. "\" textid=\"" .. textid .. "\" anchor=\"6\" marg=\"0.2\">\n"
  s=s.."  <elemparam name=\"pen\">1</elemparam>\n"
  s=s.."  <elemparam name=\"fontname\">ARIAL</elemparam>\n"
  s=s.."  <elemparam name=\"fontsize\">2.5</elemparam>\n"
  s=s.."  <elemparam name=\"fontstyle\"></elemparam>\n"
  s=s.."  <layer></layer>\n"
  s=s.."</text>\n"
  return s
end


function AddModuleStuds(tblDims, ndims, tblMod, sDim)
  local t, s, i, v, tblPoints, npoints

  s=sDim .. "\n"
  s=s..MakeTextXml(tblMod.name, 19-ndims)
  s=s.."</dimline>"
  
  
  tblPoints={}
  npoints=0
  for i,v in ipairs(tblMod.planks) do
    t={}
    t.index=v
    t.anchorfirst=true
    npoints=npoints+1
    tblPoints[npoints]=t
  end
  
  t={}
  t.xmldim=s
  t.dimpoints=tblPoints
  ndims=ndims+1
  tblDims[ndims]=t
  return ndims
end


function AddModules(sInclude, tblExclude)
  local i, s, info, t
  local tblModules, elemdata

  -- First find all module names, table has module's bounding box
  tblModules={}
  for i=1,gnPlanks do
    tbl=nil
    ac_objectopen(string.format("#%d",i))
    info=af_request("plankinfo")
    if info.type==1 then   -- is it a plank?
      elemdata=ac_objectget("#af_elemdata")
      s=ac_objectget("iElemModule")
      if elemdata and math.abs(elemdata.x2-elemdata.x1)<0.0005 and s and s~="" then
		    -- It is vertical in element
        if (not sInclude or string.match(elemdata.typetag, sInclude)) and (not tblExclude or not tblExclude[elemdata.typetag]) then
			    t=tblModules[s]
			    if not t then
				    t={}
            t.nplanks=1
            t.planks={}
            t.planks[t.nplanks]=i
            t.name=s
				    t.x1=elemdata.bx1
				    t.y1=elemdata.by1
				    t.x2=elemdata.bx1
				    t.y2=elemdata.by2
				    tblModules[s]=t
			    else
            t.nplanks=t.nplanks+1
            t.planks[t.nplanks]=i
				    if elemdata.bx1<t.x1 then
					    t.x1=elemdata.bx1
				    end
				    if elemdata.by1<t.y1 then
					    t.y1=elemdata.by1
				    end
				    if elemdata.bx2>t.x2 then
					    t.x2=elemdata.bx2
				    end
				    if elemdata.by2>t.y2 then
					    t.y2=elemdata.by2
				    end
			    end
        end
      end
		end
	  ac_objectclose()
	end
  
  -- Add dim lines for each module, sort by x1
  local tblModulesSort, k, v
  
  i=0
  tblModulesSort={}
  for k,v in pairs(tblModules) do
    i=i+1
    tblModulesSort[i]=v
  end
  
	table.sort(tblModulesSort, function (n1, n2)
    return n1.x1 < n2.x1
	end)
  
  -- Then add each module
  local prevMod
  local tblDims, ndims, s2
 
  ndims=0
  tblDims={}
  for i,v in ipairs(tblModulesSort) do
    s="0"
    if not prevMod or prevMod.x2>v.x1 then
      s="0.25"
    end
    s2=string.format("<dimline side=\"bottom\" margin=\"%s\" elemvecx=\"1\">\n", s)
    s2=s2.."<dimlinesettings><elemparam name=\"dimensiontype\">cumulative</elemparam><elemparam name=\"markertype\">5</elemparam></dimlinesettings>"

    ndims=AddModuleStuds(tblDims, ndims, v, s2)
    prevMod=v
  end
  
  return tblDims
end


function AddCoreModules()
	local tblExclude
	
	tblExclude={}
	tblExclude["extstud"]=true
	tblExclude["extstud2"]=true
	tblExclude["extstud3"]=true
	tblExclude["extstud4"]=true
	tblExclude["intstud"]=true
	tblExclude["intstud2"]=true
	tblExclude["intstud3"]=true
	tblExclude["intstud4"]=true
	return AddModules("core", tblExclude)
end


function AddNoCoreModules()
	local tblExclude
	
	tblExclude={}
	tblExclude["core"]=true
	return AddModules(nil, tblExclude)
end


-- Dim line creator uses to all horizontal battens plus lowest horizontal core piece
function FindHorBattensPlusBottomFrame()
  local i, group, n, layertype, minz
  local tblRes, tbl, tblElems, info, add, tblCoreMin

  tblRes={}
  tblElems={}        -- key=guid, data=layer type
  tblCoreMin=nil
  n=0
  minz=1E100
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    info=af_request("plankinfo")
    if info.masterelemguid then
      -- Need to open the 3d piece to get element information
      ac_objectclose()
      ac_objectopen(info.masterelemguid)
      info=af_request("plankinfo")
    end

    group=ac_objectget("iElemGroup")
    ac_objectclose()
    if info and info.type==1 and info.ownerelemguid and math.abs(info.vecx.z)<0.001 and group then   -- Horizontal piece
      layertype=tblElems[info.ownerelemguid]
      if not layertype then
        local q
        
        q=af_request("elem_quantities", info.ownerelemguid, 0)
        layertype=q.tblelems[1].elemtype
        tblElems[info.ownerelemguid]=layertype
      end

      add=false
      if layertype=="core" then
        if string.match(group, "^bottom_force%.*") and info.begc.z<minz then
          minz=info.begc.z
          tblCoreMin={}
          tblCoreMin.index=i
          tblCoreMin.anchorfirst=1
          tblCoreMin.anchormid=0
          tblCoreMin.anchorlast=0
        end
      else
        -- Should be hor studding, add piece
        add=true
      end
      if add then
        tbl={}
        tbl.index=i
        tbl.anchorfirst=1
        tbl.anchormid=0
        tbl.anchorlast=0
        n=n+1
        tblRes[n]=tbl
      end
    end
  end

  if tblCoreMin then
    n=n+1
    tblRes[n]=tblCoreMin
  end
  return tblRes
end

function FindStudsInsu()
  local i, n, s
  local tblRes, tbl, info, elemdata
  local tblProjInfo, projinfo						-- Projection infos for owning elements, key=element guid
  local typetag
  local elemGuid

  tblRes={}
  tblProjInfo={}
  n=0
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    info=af_request("plankinfo")
    tbl=ac_objectget("#af_elemdata")   -- To get typetag also
    typetag=nil
    if tbl then
      typetag=tbl.typetag
    end
    ac_objectclose()
	  if info.ownerelemguid==nil and info.masterelemguid then
		  -- Take the 3D piece
		  info=af_request("plankinfo", info.masterelemguid)
	  end
    if info.type==1 and info.ownerelemguid then   -- type 1 is plank
      --Not available since may be owned by any element object in the group: elemdata=ac_objectget("#af_elemdata")   
  	  projinfo=tblProjInfo[info.ownerelemguid]
	    if not projinfo then
		    projinfo=af_request("plankinfo", info.ownerelemguid)
		    projinfo.vecz,projinfo.vecy=projinfo.vecy, projinfo.vecz			-- Swap these for projection world
		    tblProjInfo[info.ownerelemguid]=projinfo
	    end

	    -- Get it again to get elemdata
	    info=af_request("plankinfo", info.guid, projinfo)
      elemdata=info.elemdata
      if math.abs(elemdata.x1-elemdata.x2)<0.001 and (typetag==nil or typetag=="core") then   -- and math.abs(elemdata.z1-elemdata.z2)<0.001 and elemdata.y2-elemdata.y1>0.01 and elemdata.y1<0.2 then
        tbl={}
        tbl.index=i
        tbl.anchorfirst=1
        tbl.anchorfirstnextempty=1
        tbl.anchormid=0
        tbl.anchorlast=1
        tbl.elemdata=elemdata
        n=n+1
        tblRes[n]=tbl
        elemGuid=info.ownerelemguid
      end
    end
  end
  
  if elemGuid then
    -- Check if insulation weight in the layer
    local q
    
    q=af_request("elem_quantities", elemGuid, 0)
    if q and q.tblelems[1] then
      q=q.tblelems[1]
	    if q.xmlutf8 then
		    s=string.match(q.xmlutf8, " insulationkg=\"(.-)\"")
        --ac_environment("tolog", string.format("insulationkg=%s", tostring(s)))
        if s and tonumber(s)~=nil and tonumber(s)==0.0 then
          -- No insulation
          tbl={}
          return tbl
        end
	    end
    end
  end

  return tblRes
end

function IsCoreBottom(elemgroup)
  return string.match(elemgroup, "^bottom_force.*") or string.match(elemgroup, "^2ndbottom_force.*")
end

function IsCoreTop(elemgroup)
  return string.match(elemgroup, "^top_force.*") or string.match(elemgroup, "^2ndtop_force.*")
end


function LineInPoly(poly,x1,y1,x2,y2)
  local res

  res=ac_geo("linepolyx", x1, y1, x2, y2, poly.poly)
  return res
end


-- Finds place for dim line that is not covered by studs
-- width  How much space to reserve for the dim line
-- tblStuds Collected studs to avoid
function FindInsuDimPos(x1, x2, y1, y2, width, tblStuds)
  local k,v,e,orgx

  -- Dim line starts from x1 and ends to x1+width
  orgx=x1
  for k,v in ipairs(tblStuds) do
    e=v.elemdata
    if e.bx2>x1 and e.bx1<x1+width and e.by2>y1 and e.by1<y2 then
      -- Collision, move after the stud. Studs are ordered by xc so no need to reset the loop
      x1=e.bx2
      if x1>x2 then
        return orgx+width   -- Revert to x1 if no place
      end
    end
  end

  return x1+width
end


-- Makes vertical insulation dimension lines
function InsuDimLinesVert()
  local i, info, a1, a2
  local tbl, elemdata, tblVertx, nvertx, tblStuds, nstuds, tblPoly
  local tblCam=af_request("dim_camera")     -- Use camera to judge if piece is horizontal or not
  local eps=0.0005


  -- Collect all vertical planks and studs
  tblVertx={}
  nvertx=0
  tblStuds={}
  nstuds=0

  for i=1,gnPlanks do
    ac_objectopen(string.format("#!%d",i))
    info=af_request("plankinfo")
    elemdata=ac_objectget("#af_elemdata")
    
    if info.type==1 and info.ownerelemguid and elemdata then
      -- Plank in element
      tbl={}
      tbl.index=i
      tbl.info=info
      tbl.elemdata=elemdata
      
      a1=CalcDot3D(tblCam.vecx.x, tblCam.vecx.y, tblCam.vecx.z, info.vecx.x, info.vecx.y, info.vecx.z)
      a2=CalcDot3D(tblCam.vecz.x, tblCam.vecz.y, tblCam.vecz.z, info.vecz.x, info.vecz.y, info.vecz.z)
      if math.abs(a1)>0.999 and math.abs(a2)>0.999 then
        -- Horizontal piece (not a beam)
        nvertx=nvertx+1
        tblVertx[nvertx]=tbl
      elseif math.abs(a1)<0.001 then
        -- Stud
        nstuds=nstuds+1
        tblStuds[nstuds]=tbl
      end
      
      if not tblPoly then
        -- Get owner element's polygon to find openings
        tbl={}
        tbl.side=2
        tbl.givelist=1
        tblPoly=af_request("getpoly", tbl, info.ownerelemguid)
--ac_environment("tolog", string.format("poly=%s", tostring(tblPoly)))
      end
    end
    ac_objectclose()
  end

  -- Sort vertical pieces by y, x
	table.sort(tblVertx, function (n1, n2)
    local d
    
    d=n1.elemdata.by1 - n2.elemdata.by1
    if math.abs(d)>eps then
      return d<0
    end
    return n1.elemdata.bx1 < n2.elemdata.bx1
	end)

  -- Studs by x
	table.sort(tblStuds, function (n1, n2)
    return n1.elemdata.bx1 < n2.elemdata.bx1
	end)


  -- Process all collected vertical studs
  local v1,i2,v2                    -- Handled planks are marked here, key is plank index and value is true for handled ones
  local tblDims, ndims
  
  tblDims={}
  ndims=0

  for i,v1 in ipairs(tblVertx) do
    -- Find pieces above current one
    local tblSeg, tblHandled

    tblHandled={}
    tblSeg=SegInitSingle(v1.elemdata.bx1, v1.elemdata.bx2)
    i2=i+1
    while i2<=nvertx do
      v2=tblVertx[i2]
      if v2.elemdata.by1-eps<v1.elemdata.by2 then
--SegDump("PRE", tblSeg)
        tblSeg=SegDifference(tblSeg, v2.elemdata.bx1, v2.elemdata.bx2)
--SegDump(string.format("POST (diff %f %f)", v2.elemdata.bx1, v2.elemdata.bx2), tblSeg)
      else
        break     -- Sorted by y
      end
        
      i2=i2+1
    end
      
    -- Find closest upper piece from current segments (i2 is valid now)
    local kseg,vseg, i2org, x1, x2, iseg
      
    i2org=i2
    iseg=1
    while iseg<=#tblSeg do
      x1=tblSeg[iseg].x1
      x2=tblSeg[iseg].x2
      i2=i2org
      while i2<=nvertx do
        v2=tblVertx[i2]
        if x1<v2.elemdata.bx2-eps and x2>v2.elemdata.bx1+eps then
          -- There is a pair, add dim line if not at empty space
          if v2.elemdata.bx1>x1 then
            x1=v2.elemdata.bx1
          end
          if v2.elemdata.bx2<x2 then
            x2=v2.elemdata.bx2
          end
            
          local x=(x1+x2)*0.5
            
          if LineInPoly(tblPoly, x, v1.elemdata.by2, x, v2.elemdata.by1) and not tblHandled[v2.index] then
            local t, tblPts
            
            tblPts={}
            
            t={}
            t.index=v1.index
            t.anchorlast=true
            tblPts[1]=t
            
            t={}
            t.index=v2.index
            t.anchorfirst=true
            tblPts[2]=t
              
--ac_environment("tolog", string.format("DIM x1=%f x2=%f", x1, x2))

            t={}
            t.xmldim=string.format("<dimline side=\"left\" marginproj=\"%1.3f\" elemvecy=\"1\"/>", -FindInsuDimPos(x1, x2, v1.elemdata.by2, v2.elemdata.by1, 0.2, tblStuds) )
            t.dimpoints=tblPts

            ndims=ndims+1
            tblDims[ndims]=t
          end

          tblHandled[v2.index]=true
--SegDump("PRE2", tblSeg)
          tblSeg=SegDifference(tblSeg, x1, x2)
--SegDump(string.format("POST (diff %f %f)", x1, v2.elemdata.bx2), tblSeg)
          break
        end
        
        i2=i2+1
      end
      if i2>nvertx then
        iseg=iseg+1   -- No matching pair found, scan next segment
      end
    end
      
--ac_environment("tolog", string.format("iseg=%d #tblSeg=%d", iseg, #tblSeg))
  end
  
  return tblDims
end


-- margin Distance between dim lines
-- tblPrevDim, table of previous anchor x-coords (fields left and right). Skip dim if same value as previously. Also fields marginleft, marginright telling where to place next dim line
function AddTopDims(tblCore, tblNow, tblDims, ndims, lineSide, margin, tblPrevDim, flipx)
--ac_environment("tolog", string.format("%s", tblNow.typetag))

  if tblCore.first==nil or tblNow.first==nil then
    return ndims
  end

--ac_environment("tolog", "1")

  local s, t, tblPts, pt, npt, xnow, xcore
  
  -- Offset left
  xnow=tblNow.first.elemdata.bx1
  xcore=tblCore.first.elemdata.bx1
  if flipx then
    -- Need to swap x1,x2 also
    xnow=tblNow.first.elemdata.bx2
    xcore=tblCore.first.elemdata.bx2
  end
  if math.abs(xnow - xcore)>0.001 then
    tblPts={}
    npt=0

    -- Curr min
    pt={}
    pt.index=tblNow.first.index
    pt.anchorfirst=1
    npt=npt+1
    tblPts[npt]=pt

    -- Core min
    pt={}
    pt.index=tblCore.first.index
    pt.anchorfirst=1
    npt=npt+1
    tblPts[npt]=pt
    
    if tblPrevDim.left==nil or math.abs(tblPrevDim.left-xnow)>0.0005 then
      tblPrevDim.left=xnow
      s=string.format("<dimline side=\"%s\" marginproj=\"%.2f\" elemvecx=\"1\"/>", lineSide, tblPrevDim.marginleft)
      tblPrevDim.marginleft=tblPrevDim.marginleft+margin
      t={}
      t.xmldim=s
      t.dimpoints=tblPts

      ndims=ndims+1
      tblDims[ndims]=t
    end
  end
  
  -- Offset right
  xnow=tblNow.last.elemdata.bx2
  xcore=tblCore.last.elemdata.bx2
  if flipx then
    -- Need to swap x1,x2 also
    xnow=tblNow.last.elemdata.bx1
    xcore=tblCore.last.elemdata.bx1
  end
  if math.abs(xnow - xcore)>0.001 then
    tblPts={}
    npt=0

    -- Curr max
    pt={}
    pt.index=tblNow.last.index
    pt.anchorlast=1
    npt=npt+1
    tblPts[npt]=pt

--ac_environment("tolog", string.format("tblNow.typetag=%s tblNow.last.index=%d, tblNow.last.elemdata.bx1=%f, tblNow.last.elemdata.bx2=%f\ntblNow.last.elemdata.by1=%f, tblNow.last.elemdata.by2=%f", tblNow.typetag, tblNow.last.index, tblNow.last.elemdata.bx1, tblNow.last.elemdata.bx2, tblNow.last.elemdata.by1, tblNow.last.elemdata.by2))

    -- Core min
    pt={}
    pt.index=tblCore.last.index
    pt.anchorlast=1
    npt=npt+1
    tblPts[npt]=pt
    
--ac_environment("tolog", string.format("tblCore.last.index=%d tblCore.last.elemdata.bx1=%f, tblCore.last.elemdata.bx2=%f\ntblCore.last.elemdata.by1=%f, tblCore.last.elemdata.by2=%f", tblCore.last.index, tblCore.last.elemdata.bx1, tblCore.last.elemdata.bx2, tblCore.last.elemdata.by1, tblCore.last.elemdata.by2))
    if tblPrevDim.right==nil or math.abs(tblPrevDim.right-xnow)>0.0005 then
      tblPrevDim.right=xnow
      s=string.format("<dimline side=\"%s\" marginproj=\"%1.2f\" elemvecx=\"1\"/>", lineSide, tblPrevDim.marginright)
      tblPrevDim.marginright=tblPrevDim.marginright+margin
      t={}
      t.xmldim=s
      t.dimpoints=tblPts

      ndims=ndims+1
      tblDims[ndims]=t
    end
  end  
  
  return ndims
end

-- Creates offset dim lines for top projection
function TopDimLines()
  local i, a
  local tbl, info, elemdata
  local tblProjInfo, projinfo						-- Projection infos for owning elements, key=element guid
  local typetag, tblPlank
  local tblLayers                       -- key=element layer typetag, data: elem is the owner element ; parts beg and end each having fields: index, elemdata
  local tblCam=af_request("dim_camera")


  tblRes={}
  tblProjInfo={}
  tblLayers={}
  for i=1,gnPlanks do
    ac_objectopen(string.format("#!%d",i))    -- Open related master plank
    info=af_request("plankinfo")
    
    -- Include only planks which are 0/90 deg from camera's x-direction (studs or horizontal pieces)
    a=0
    if tblCam and info.type==1 then
      a=CalcDot3D(info.vecx.x, info.vecx.y, info.vecx.z, tblCam.vecx.x, tblCam.vecx.y, tblCam.vecx.z)
    end
    --ac_environment("tolog", string.format("%s: a=%f", ac_objectget("#id"), a))

    tbl=ac_objectget("#af_elemdata")   -- To get typetag also
    typetag=nil
    if tbl then
      typetag=tbl.typetag
    end
    ac_objectclose()
    
    if math.abs(a)<0.02 or math.abs(a)>0.999 then
      tblPlank={}
      tblPlank.index=i
      tblPlank.elemdata=tbl
    
      if not typetag then
        ac_environment("tolog", "TopDimLines: Unexpected missing typetag")
      else
        tbl=tblLayers[typetag]
        if tbl==nil then
          -- Construct info for this layer
          tbl={}
          tbl.elem={}
        
          tbl.elem.geo=af_request("elem_quantities", info.ownerelemguid, 0).geo
          tbl.first=tblPlank
          tbl.last=tblPlank
          tblLayers[typetag]=tbl
        else
          -- Find min&max for the layer
          if tblPlank.elemdata.bx1<tbl.first.elemdata.bx1 then
            tbl.first=tblPlank
          end
        
          if tblPlank.elemdata.bx2>tbl.last.elemdata.bx2 then
            tbl.last=tblPlank
          end
        end
      end
    end
  end
  
  tblCore=tblLayers["core"]
  if tblCore==nil then
    return nil
  end

  -- Collect all layers and sort by distance from core layer to put dim lines in order
  local tblLayersSort, k, v, x, y, z
  
  tblLayersSort={}
  i=0
  for k,v in pairs(tblLayers) do
    i=i+1
    tblLayersSort[i]=v
    tblLayersSort[i].typetag=k
        
    x=v.elem.geo.orig.x - tblCore.elem.geo.orig.x
    y=v.elem.geo.orig.y - tblCore.elem.geo.orig.y
    z=v.elem.geo.orig.z - tblCore.elem.geo.orig.z
    tblLayersSort[i].dist=CalcDot3D(tblCore.elem.geo.vecz.x, tblCore.elem.geo.vecz.y, tblCore.elem.geo.vecz.z, x, y, z)
--ac_environment("tolog", string.format("%s: tblLayersSort[i].dist=%f, tblCore.elem.geo.vecz.x=%f, tblCore.elem.geo.vecz.y=%f, tblCore.elem.geo.vecz.z=%f\nx=%f y=%f z=%f", k, tblLayersSort[i].dist, tblCore.elem.geo.vecz.x, tblCore.elem.geo.vecz.y, tblCore.elem.geo.vecz.z, x, y, z))
  end

	table.sort(tblLayersSort, function (n1, n2)
    return n1.dist<n2.dist    
	end)

  -- Find core (always found)
  local coreInd
  
  for i,v in ipairs(tblLayersSort) do
    if v.typetag=="core" then
      coreInd=i
      break
    end
  end

  -- Add dims
  local ndims, tblDims
  local tblPrevDim
  local stop, sbot, mtop, mbot, flipx
  
  ndims=0
  tblDims={}
  
  -- If camera's y-axis is opposite to element's watching dir, swap top&bottom
  stop="top"
  sbot="bottom"
  mtop=0.05
  mbot=0.13
  
  v=tblCore.elem.geo.vecz
  if tblCam and CalcDot3D(v.x, v.y, v.z, tblCam.vecy.x, tblCam.vecy.y, tblCam.vecy.z)<0 then
    stop="bottom"
    sbot="top"
    mtop=0.13
    mbot=0.05
  end

  flipx=false
  v=tblCore.elem.geo.vecx
  if tblCam and CalcDot3D(v.x, v.y, v.z, tblCam.vecx.x, tblCam.vecx.y, tblCam.vecx.z)<0 then
    flipx=true
    tblCore.first,tblCore.last=tblCore.last,tblCore.first
  end

  -- Anything before core to bottom
  tblPrevDim={}
  tblPrevDim.marginleft=mbot
  tblPrevDim.marginright=mbot
  i=coreInd
  while i>1 do
    i=i-1
    v=tblLayersSort[i]
    if flipx then
      v.first,v.last=v.last,v.first
    end
    ndims=AddTopDims(tblCore, v, tblDims, ndims, sbot, 0.13, tblPrevDim, flipx)
  end
  
  -- Anything after core to top
  tblPrevDim={}
  tblPrevDim.marginleft=mtop
  tblPrevDim.marginright=mtop
  i=coreInd
  while true do
    i=i+1
    v=tblLayersSort[i]
    if not v then
      break
    end

    if flipx then
      v.first,v.last=v.last,v.first
    end
    ndims=AddTopDims(tblCore, v, tblDims, ndims, stop, 0.13, tblPrevDim, flipx)
  end

  return tblDims
end


-- Creates cladding dim line adding all polygon points to the dim line
function CladdingDimLines()
  local i
  local tblPoints, npoints, poly, polySettings, typetag
  local t, info, elemdata, tblCam, x1, x2, y1, y2
  
  tblCam=af_request("dim_camera")
  tblPoints={}
  npoints=0
  polySettings={}
  polySettings.side=2                         -- Front side
  polySettings.givelist=1                     -- Future proof for split polygons
  polySettings.camera=tblCam
  for i=1,gnPlanks do
    typetag=nil
    poly=nil
    ac_objectopen(string.format("#!%d",i))    -- Open related master plank
    --info=af_request("plankinfo")
    t=ac_objectget("#af_elemdata")   -- To get typetag also
    if t then
      typetag=t.typetag
      if typetag and string.match(typetag,"^finish.*") then
        poly=af_request("getpoly", polySettings)
      end
    end
    ac_objectclose()
    
    if poly then
      local klist,vlist, kpoint, vpoint, kscan, vscan, found
      
      for klist,vlist in ipairs(poly.poly) do
        for kpoint,vpoint in ipairs(vlist) do
          -- Do not add if x already added
          found=false
          for kscan,vscan in ipairs(tblPoints) do
            if math.abs(vscan.x-vpoint.x)<0.0005 then
              found=true
              break
            end
          end
          
          if not found then
            t={}
            t.x=vpoint.x
            t.y=vpoint.y
            npoints=npoints+1
            tblPoints[npoints]=t
            
            if not x1 or vpoint.x<x1 then
              x1=vpoint.x
              y1=vpoint.y
            end
            if not x2 or vpoint.x>x2 then
              x2=vpoint.x
              y2=vpoint.y
            end
          end
        end
      end
    end
  end

  local ndims, tblDims
  
  ndims=0
  tblDims={}
  
  if not npoints then
    return tblDims
  end
  
  local s

  s="<dimline side=\"top\" margin=\"0.2\" elemvecx=\"1\">"
  s=s .. "<dimlinesettings>\n"
  s=s .. "  <elemparam name=\"dimensiontype\">cumulative</elemparam>\n"
  s=s .. "<elemparam name=\"markertype\">5</elemparam>\n"
  s=s .. "</dimlinesettings>\n"
  s=s.."</dimline>"
  
  t={}
  t.xmldim=s
  t.dimpoints=tblPoints
  ndims=ndims+1
  tblDims[ndims]=t

  -- Min & max
  s="<dimline side=\"top\" margin=\"0.2\" elemvecx=\"1\">"
  s=s.."</dimline>"
  
  tblPoints={}
  
  t={}
  t.x=x1
  t.y=y1
  tblPoints[1]=t

  t={}
  t.x=x2
  t.y=y2
  tblPoints[2]=t
  
  t={}
  t.xmldim=s
  t.dimpoints=tblPoints
  ndims=ndims+1
  tblDims[ndims]=t

  return tblDims
end
]]>
        </script>

        <!-- Sets values of element stamp  -->
        <script id="elemstamp">
          <![CDATA[
-- Get values from element
ac_objectopen(gGuidElem)
sId=ac_objectget("#id")
ac_objectclose()

-- Set to the stamp (only set some if not set already)
ac_objectopen(gGuidElemStamp)
ac_objectset("iStr1", sId)
ac_objectset("iStr2", gElemIdStamp)

if ac_objectget("iStr3")=="" then
  -- Check http://www.lua.org/pil/22.1.html
  d=os.date("%Y-%m-%d")
  ac_objectset("iStr3", d)
end

ac_objectset("iStr4", "<PROJECTNAME>")

if ac_objectget("iStr5")=="" then
  ac_objectset("iStr5", "<CADTECHNICIAN>")
end

ac_objectset("iStr6", "<PROJECTNUMBER>")

-- Unused: ac_objectset("iStr7", "<CUSTOM2>")

ac_objectclose()
]]>
        </script>

        <!-- Sets different pen for studs -->
        <script id="setcolours">
          <![CDATA[
gnPlankCount=0
gtblCreate = {}

-- "-" means do not create
if not gFillPen or gFillPen~="-" then
 local pen
 
 if gFillPen and gFillPen~="" then
   pen=tonumber(gFillPen)
 end
 if pen==nil then
   pen=110
 end
 
 for i=1,gnPlanks do
  ac_objectopen(string.format("#%d",i))
  
  -- Vertical (studs) with different fill
  x2=ac_objectget("iEndX")
  y2=ac_objectget("iEndY")
  if math.abs(x2)<0.001 and math.abs(y2)<0.001 then
    ac_objectset("iFillPen", pen)
    ac_objectset("iFill", "SolidNOTFOUND|50 %")
  end
  ac_objectclose()
 end
end
]]>
        </script>

        <!-- Sets different pen for studs -->
        <script id="ibeamframe">
          <![CDATA[
gnPlankCount=0
gtblCreate = {}

for i=1,gnPlanks do
  ac_objectopen(string.format("#%d",i))
  
  -- Vertical (studs) with different fill
  z2=ac_objectget("iEndZ")
  if math.abs(z2)<0.001 then
    local i2, count, tblInfo
    
    count=ac_objectget("iMc",-1)
    i2=1
    while i2<=count do
      if ac_objectget("iMc",i2,1)==0 then
        found=true
        break
      end
      i2=i2+1
    end

    tblInfo=af_request("plankinfo")
    ac_objectset("iMc", 304, i2, 1)
    ac_objectset("iMc", 0.1, i2, 2)
    ac_objectset("iMc", tblInfo.height*0.5, i2, 3)
    ac_objectset("iMc", 0, i2, 4)
    ac_objectset("iMc", tblInfo.height - 0.096, i2, 5)
    ac_objectset("iMc", 0.018, i2, 6)
    ac_objectset("iMc", 2, i2, 7)
    ac_objectset("iMc", 1, i2, 8)
    ac_objectset("iMc", 1, i2, 9)
    ac_objectset("iMcStr", "", i2)
  end
  ac_objectclose()
 end
]]>
        </script>

        <!-- Lintels all -->
        <script id="lintels">
          <![CDATA[
function DoLintelNoLoad()
  gnPlankCount=0
  gtblCreate = {}     -- Need to have but not used

  -- From widest to narrowest
  tblLens={}

  -- >= 2 m
  item={}
  item.minwidth=2
  item.mat="L 90x225"
  item.front=1
  item.back=0
  item.delorg=1
  item.extorg=0
  item.cutabove=1
  item.studs=1
  tblLens[1] = item

  af_request("lintels", tblLens)
end


function DoLintelLoad()
  gnPlankCount=0
  gtblCreate = {}     -- Need to have but not used

  -- From widest to narrowest
  tblLens={}

  -- >= 1800 mm
  item={}
  item.minwidth=1.8
  item.mat="L 90x225"
  item.front=1
  item.back=0
  item.delorg=1
  item.extorg=0
  item.cutabove=1
  item.studs=1
  tblLens[1] = item

  item={}
  item.minwidth=1.2
  item.mat="48x223"
  item.front=2
  item.back=0
  item.delorg=1
  item.extorg=0
  item.cutabove=1
  item.studs=1
  tblLens[2] = item

  item={}
  item.minwidth=0.6
  item.mat="48x198"
  item.front=2
  item.back=0
  item.delorg=1
  item.extorg=0
  item.cutabove=1
  item.studs=1
  tblLens[3] = item

  item={}
  item.minwidth=0.1
  item.mat="48x98"
  item.front=2
  item.back=0
  item.delorg=1
  item.extorg=0
  item.cutabove=1
  item.studs=1
  tblLens[4] = item

  af_request("lintels", tblLens)
end


gtblSettings=nil

-- Uses global gtblSettings for optins
-- Returns: true=ok, false=canceled from settings dlg
function DoLintelCustom()
  local defMatId, defMat
  
  gnPlankCount=0
  gtblCreate = {}     -- Need to have but not used

  -- Settings
        
  tblMat=af_request("matlist")
  s=""
  strSep=""
      
  -- Select always element's default material
  defMatId=af_request("elem_getstudmat")
  if defMatId==nil then
    defMatId=""
  end
  defMat=1
  tblSorted={}
  for id,v in pairs(tblMat) do
    tblSorted[v.index]=v
    if v.id==defMatId then
      defMat=v.index
    end
  end

  for i,v in ipairs(tblSorted) do
    s=string.format("%s%s\"%s:%s (%s)\"", s, strSep, i, v.name, v.id)
    strSep=","
  end

  -- For options to handle creating multiple lintels with single click
  if gtblSettings==nil then
    gtblSettings={}
    gtblSettings[1]			={}
    gtblSettings[1].cfgonly	=0
    gtblSettings[1].type		=1
    gtblSettings[1].prompt	="Material"
    gtblSettings[1].key		="mat"
    gtblSettings[1].valuelist=s
    gtblSettings[1].defvalue	=defMat
    --gtblSettings[1].value 	=defMat

    gtblSettings[2]			={}
    gtblSettings[2].cfgonly	=1
    gtblSettings[2].type		=2
    gtblSettings[2].prompt	="Use element's material as default (affects prev setting)"
    gtblSettings[2].key		="usedefault"
    gtblSettings[2].defvalue	=1

    gtblSettings[3]			={}
    gtblSettings[3].cfgonly	=0
    gtblSettings[3].type		=3
    gtblSettings[3].prompt	="Thickness if not fixed"
    gtblSettings[3].key		="thickness"
    gtblSettings[3].defvalue	=0.050

    gtblSettings[4]			={}
    gtblSettings[4].cfgonly	=0
    gtblSettings[4].type		=3
    gtblSettings[4].prompt	="Height if not fixed"
    gtblSettings[4].key		="height"
    gtblSettings[4].defvalue	=0.100

    gtblSettings[5]			={}
    gtblSettings[5].cfgonly	=0
    gtblSettings[5].type		=4
    gtblSettings[5].prompt	="Beams to front side"
    gtblSettings[5].key		="beam_front"
    gtblSettings[5].defvalue	=1

    gtblSettings[6]			={}
    gtblSettings[6].cfgonly	=0
    gtblSettings[6].type		=4
    gtblSettings[6].prompt	="Beams to back side"
    gtblSettings[6].key		="beam_back"
    gtblSettings[6].defvalue	=0

    gtblSettings[7]			={}
    gtblSettings[7].cfgonly	=0
    gtblSettings[7].type		=2
    gtblSettings[7].prompt	="Remove original piece"
    gtblSettings[7].key		="delorg"
    gtblSettings[7].defvalue	=0

    gtblSettings[8]			={}
    gtblSettings[8].cfgonly	=0
    gtblSettings[8].type		=2
    gtblSettings[8].prompt	="Extend original piece"
    gtblSettings[8].key		="extorg"
    gtblSettings[8].defvalue	=0

    gtblSettings[9]			={}
    gtblSettings[9].cfgonly	=0
    gtblSettings[9].type		=2
    gtblSettings[9].prompt	="Cut studs above lintel (grooves if not)"
    gtblSettings[9].key		="cutabove"
    gtblSettings[9].defvalue	="0"

    gtblSettings[10]			={}
    gtblSettings[10].cfgonly	=0
    gtblSettings[10].type		=4
    gtblSettings[10].prompt	="Number of additional studs"
    gtblSettings[10].key		="numstuds"
    gtblSettings[10].defvalue	="1"

    gtblSettings[11]			={}
    gtblSettings[11].cfgonly	=0
    gtblSettings[11].type		=2
    gtblSettings[11].prompt	="Place below top plate"
    gtblSettings[11].key		="totop"
    gtblSettings[11].defvalue	=0

    gHelpAnchor="afdlgelemlintel"
    bRes,sErr=ac_optiondlg("LDEL", nil, gtblSettings)
    
    if gtblSettings[2].value and gtblSettings[2].value==1 then
      gtblSettings[1].value 	=defMat
    else
      gtblSettings[1].value 	=nil
    end
    
    bRes,sErr=ac_optiondlg("LDEL", "Lintel settings", gtblSettings)
    gHelpAnchor=nil
    if not bRes then
      return false
    end
  end
      
  mat=tblSorted[gtblSettings[1].value]
  thickness=mat.thickness
  height=mat.height
  if thickness==0.0 then
    thickness=gtblSettings[2].value
  end
  if height==0.0 then
    height=gtblSettings[3].value
  end

  -- Fill the lintel settings to single item
  tblLens={}

  item={}
  item.minwidth =0
  item.mat      =tblSorted[gtblSettings[1].value].id
  item.thickness=gtblSettings[3].value
  item.height   =gtblSettings[4].value
  item.front    =tonumber(gtblSettings[5].value)
  item.back     =tonumber(gtblSettings[6].value)
  item.delorg   =gtblSettings[7].value
  item.extorg   =gtblSettings[8].value

  item.cutabove =gtblSettings[9].value
  item.studs    =tonumber(gtblSettings[10].value)
  item.totop    =gtblSettings[11].value

  tblLens[1] = item
  af_request("lintels", tblLens)
  return true
end
]]>
        </script>


        <!-- Creates/removes second top&bottom wood -->
        <script id="doubletopbot">
          <![CDATA[
-- For planks to be created
gnPlankCount=0
gtblCreate = {}

gbJoinSources=true   -- Set to true if you want single piece from automatic cut top/bottom


-- Formats message so that calling program shows just the msg
-- Message can be empty - nothing is showed then (if operation canceled)
function RaiseError(msg)
	msg="###>" ..  msg .. "<###"
	error( msg )
end


gtblSelPlanks=nil
gAddAllStuds=false      -- Set to true if making reinforcement (and grooves to every stud)

function FindConnStuds(tblCurr, bTop)
  local tblRes, tblFind
  local x1, x2, y1, y2, dy, nRes
  
  tblRes={}
  nRes=0
  
  if gAddAllStuds then
    for nPlank=1,gnPlanks do
      ac_objectopen(string.format("#%d", nPlank))
      s=ac_objectget("iElemGroup")
      if string.match(s, "vertical_%a*") then
        nRes=nRes+1
        tblRes[nRes]=nPlank
      end
      ac_objectclose()
    end

    return tblRes
  end
  
  dy=tblCurr.thickness

  y1=tblCurr.tblElemData.y1-dy*0.5
  y2=y1+dy
  x1=tblCurr.tblElemData.x1 - 0.001
  x2=tblCurr.tblElemData.x2 + 0.001
  if x1>x2 then
    x1,x2=x2,x1
  end
  
  for nPlank=1,gnPlanks do
    ac_objectopen(string.format("#%d", nPlank))
    s=ac_objectget("iElemGroup")
    if string.match(s, "^vertical_%a*") then
      tblFind=ac_objectget("#af_elemdata")

      -- 0.0051 comes from 5 mm grooves
      if ((bTop==true and math.abs(y1 - tblFind.y2)<0.0051) or (bTop==false and math.abs(y2 - tblFind.y1)<0.0051)) and x1<tblFind.x2 and x2>tblFind.x2 then
        nRes=nRes+1
        tblRes[nRes]=nPlank
      end
    end
    ac_objectclose()
  end

  return tblRes
end


function GetThickness()
	local	width
	
	width=ac_objectget("iWidth")
	if width==nil or width==0.0 then
		width=ac_objectget("A")
	end
   return width
end


-- justCheck  true=do not connect, just check if there are split pieces
-- Returns: New number of planks
function DoJoin(tblPlanks, nPlanks)
  local i, firstInd, x1, y1, x2, y2, hasX, dist1, len1, dist2, len2, lenCurr, dx, dy, dest

  if nPlanks<2 then
    return nPlanks
  end
  
  table.sort( tblPlanks,  function(p1, p2)
                            return p1.tblElemData.x1<p2.tblElemData.x1
                          end )

  -- Join all connecting ones to the first piece
  firstInd=1
  dest=1
  for i=2,#tblPlanks do
    local currPlank, v, joined
  
    currPlank=tblPlanks[firstInd]
    v=tblPlanks[i]
    x1=currPlank.tblElemData.x1
    y1=currPlank.tblElemData.y1
    x2=currPlank.tblElemData.x2
    y2=currPlank.tblElemData.y2

    hasX=ac_geo("linex", x1, y1, x2, y2, v.tblElemData.x1, v.tblElemData.y1, v.tblElemData.x2, v.tblElemData.y2)
    dist1,len1 = ac_geo("linedist", x1, y1, x2, y2, v.tblElemData.x1, v.tblElemData.y1)
    dist2,len2 = ac_geo("linedist", x1, y1, x2, y2, v.tblElemData.x2, v.tblElemData.y2)
    
    joined=false
    if not hasX and math.abs(dist1)<0.0001 and math.abs(dist2)<0.0001 and math.abs(currPlank.plankinfo.width-v.plankinfo.width)<0.0001 and math.abs(currPlank.plankinfo.height-v.plankinfo.height)<0.0001 and currPlank.matid==v.matid then
      -- Parallel and same material
      if len2<len1 then
        len1,len2=len2,len1
      end
    
      dx=x2-x1
      dy=y2-y1
      lenCurr=math.sqrt(dx*dx+dy*dy)
      if len2>-0.001 and len1<lenCurr+0.001 then
        -- Join to this
        dx=dx/lenCurr
        dy=dy/lenCurr
        if len1<0 then
          -- Move beg
          currPlank.tblElemData.x1=currPlank.tblElemData.x1+dx*len1
          currPlank.tblElemData.y1=currPlank.tblElemData.y1+dy*len1
          currPlank.plankinfo.len=currPlank.plankinfo.len-len1
        end
        if len2>lenCurr then
          -- Move end
          currPlank.tblElemData.x2=currPlank.tblElemData.x2+dx*(len2-lenCurr)
          currPlank.tblElemData.y2=currPlank.tblElemData.y2+dy*(len2-lenCurr)
          currPlank.plankinfo.len=currPlank.plankinfo.len+(len2-lenCurr)
        end
        
        -- Studs
        local stud
        
        for stud=1,#v.tblStuds do
          currPlank.tblStuds[#currPlank.tblStuds+1]=v.tblStuds[stud]
        end

        currPlank.lastjoinedptr=v.ptr
        joined=true
      end
    end
    
    if not joined then
      tblPlanks[dest]=tblPlanks[firstInd]
      dest=dest+1
      firstInd=i
    end
  end
  return dest
end


-- Creates table of matching planks
-- Table fields: index, thickness, matid, tblElemData, tblStuds
-- Returns table, number of items
function FindPlanks(sGroup, bTop)
  local tblPlanks, nPlanks

  tblPlanks,nPlanks = FindPlanksInt(sGroup, bTop)
  if tblPlanks and gbJoinSources then
    -- Join cut planks if same dir, material
    nPlanks=DoJoin(tblPlanks,nPlanks)
  end
  return tblPlanks,nPlanks
end


function FindPlanksInt(sGroup, bTop)
  local nPlank,s
  local tblRes, tblNow, tblInfo
  local nRes, i, v
  
  nRes=0
  tblRes={}
  if gtblSelPlanks then
    -- Check if selection contains wanted group and use it if yes
    for i,v in pairs(gtblSelPlanks) do
      ac_objectopen(v)
      s=ac_objectget("iElemGroup")
      
      tblNow=nil
      tblInfo=af_request("plankinfo")
      if s~=nil and s==sGroup and tblInfo and not tblInfo.del then
        tblNow={}
        tblNow.ptr=tblInfo.ptr
        tblNow.plankinfo=tblInfo
        tblNow.elemgroup=s
        tblNow.thickness=GetThickness()
        tblNow.matid=ac_objectget("iMatId")
        tblNow.tblElemData=ac_objectget("#af_elemdata")
        if tblNow.tblElemData then      -- If selected from multiple elements - will return data only if related to current element
        tblNow.index=tblNow.tblElemData.index
          tblNow.index=tblNow.tblElemData.index
          nRes=nRes+1
        tblRes[nRes]=tblNow
       else
          tblNow=nil
       end
      end
      ac_objectclose()

      if tblNow~=nil then
        tblNow.tblStuds=FindConnStuds(tblNow, bTop)
      end
    end

    if nRes>0 then
      return tblRes,nRes
    end
  end

  for nPlank=1,gnPlanks do
    ac_objectopen(string.format("#%d", nPlank))
    s=ac_objectget("iElemGroup")
    tblNow=nil
    tblInfo=af_request("plankinfo")
    if s==sGroup and tblInfo and not tblInfo.del then
      nRes=nRes+1
      tblNow={}
      tblNow.ptr=tblInfo.ptr
      tblNow.plankinfo=tblInfo
      tblNow.elemgroup=s
      tblNow.thickness=GetThickness()
      tblNow.matid=ac_objectget("iMatId")
      tblNow.tblElemData=ac_objectget("#af_elemdata")
      tblNow.index=tblNow.tblElemData.index
      tblRes[nRes]=tblNow
    end
    ac_objectclose()

    if tblNow~=nil then
      tblNow.tblStuds=FindConnStuds(tblNow, bTop)
    end
  end

  return tblRes,nRes
end


-- bAdd true=adding, false=deleting, nil=on/off
-- Globals: g_matidorg, g_matiddouble: Set to non-nil if forced materials
-- g_zofforg, g_zoffdouble: Z-offset for original and double piece
function DoDoubleTopBot(bTop, sTopBotGroup, sDoubleGroup, bAdd)
  local nPlank,s, strXmlOp
  local tblDouble, tblTop   -- Fields: index, guid, thickness, matid, tblElemData, tblStuds
  local nDouble, nTop, nTopIndex

  gxmlOperations=nil
  gbJoinSources=true
  gtblSelPlanks=af_request("getselplanks")
  tblDouble,nDouble=FindPlanks(sDoubleGroup, bTop)
  tblTop,nTop=FindPlanks(sTopBotGroup, bTop)
  if nTop==0 then
    -- No error msg if from option dlg
    if gbTop==nil then
    RaiseError("CANNOT FIND TOP/BOTTOM PLANK")
    end
    return
  end

  if bAdd~=nil then
    if bAdd then
      if nDouble>0 then
        return
      end
    else
      -- Removing
      if nDouble==0 then
        return
      end
    end
  end

  strXmlOp=""
  if nDouble>0 then
    -- Remove, match studs to top
    gbJoinSources=false
    tblDouble,nDouble=FindPlanks(sDoubleGroup, bTop)
    tblTop,nTop=FindPlanks(sTopBotGroup, bTop)

    for nPlank=1,nDouble do
      for i,v in ipairs(tblDouble[nPlank].tblStuds) do
        for nTopIndex=1,nTop do
          strXmlOp = string.format( 
              "%s" ..
              "<jointo target=\"#%d\" operator=\"#%d\">\n" ..
              "    <cut jointgap=\"0.000\"></cut>\n" ..
              "</jointo>\n",
              strXmlOp, v, tblTop[nTopIndex].index
            )
        end
      end
      
      -- Set zero length to be cleaned away
      ac_objectopen(string.format("#%d", tblDouble[nPlank].index))
      af_request("delplank")
      ac_objectclose()
    end

  else
    -- Add new
    local tblNew, tblTopNow, side

    side="down"
    if bTop then
      side="up"
    end
    
    for nPlank=1,nTop do
      local t2, matOrg
      
      tblTopNow=tblTop[nPlank]
      ac_objectopen(tblTopNow.ptr)
      matOrg=ac_objectget("iMatId")
      ac_objectclose()
      
      if g_matidorg~=nil then
        -- Edit original, move and set new material
        local tblEdit, dx, dy, len, t3
        
        tblEdit={}
        tblEdit.guid=tblTopNow.ptr
        tblEdit.mat=g_matidorg
        tblEdit.elemdata=tblTopNow.tblElemData
        
        -- Assume rotangle=0
        dy=-tblEdit.elemdata.x2-tblEdit.elemdata.x1
        dx=tblEdit.elemdata.y2-tblEdit.elemdata.y1
        if (bTop and dy>0) or (not bTop and dy<0) then
          dx=-dx
          dy=-dy
        end
        len=math.sqrt(dx*dx+dy*dy)
        if len>0.0001 then
          dx=dx/len
          dy=dy/len
          t3=af_request("singlemat", g_matidorg).thickness
          t2=(t3-tblTopNow.thickness)*0.5
          tblTopNow.thickness=t3

          tblEdit.elemdata.x1=tblEdit.elemdata.x1+dx*t2
          tblEdit.elemdata.y1=tblEdit.elemdata.y1+dy*t2
          tblEdit.elemdata.x2=tblEdit.elemdata.x2+dx*t2
          tblEdit.elemdata.y2=tblEdit.elemdata.y2+dy*t2
          tblEdit.elemdata.z1=g_zofforg
          tblEdit.elemdata.z2=g_zofforg

          af_request("editplank", tblEdit)
        end
      end
      
      tblNew={}
      tblNew.guidsettings=tblTopNow.ptr
      tblNew.group=sDoubleGroup
      tblNew.x1=tblTopNow.tblElemData.x1
      tblNew.x2=tblTopNow.tblElemData.x2
      t2=tblTopNow.thickness*0.5
      if bTop then
        t2=-t2
      end
      tblNew.y1=tblTopNow.tblElemData.y1+t2
      tblNew.y2=tblTopNow.tblElemData.y2+t2

      tblNew.id=g_matiddouble
      if g_matiddouble==nil then
        tblNew.id=matOrg
      end
      t2=af_request("singlemat", tblNew.id).thickness*0.5
      if bTop then
        t2=-t2
      end
      tblNew.y1=tblNew.y1+t2
      tblNew.y2=tblNew.y2+t2

      tblNew.rotAngle=0
      tblNew.zoff=g_zoffdouble
      tblNew.force=3

      gnPlankCount=gnPlankCount+1
      gtblCreate[gnPlankCount] = tblNew

      for i,v in ipairs(tblTopNow.tblStuds) do
        for nTopIndex=1,nTop do
          strXmlOp = string.format( 
              "%s" ..
              "<jointo target=\"#%d\" operator=\"#%d\">\n" ..
              "    <cut jointgap=\"0.000\" extendmaxlen=\"0.000\" removepart=\"%s\"></cut>\n" ..
              "</jointo>\n",
              strXmlOp, v, gnPlanks+nTopIndex, side
            )
        end
      end
    end

  end

  -- Add xml-operations to be run after new planks are initialized
  if strXmlOp~="" then
    gxmlOperations=string.format("<operations>\n%s</operations>", strXmlOp)
  end
  return strXmlOp
end



-------------------------
-- FOR OPTION DLG

--Set these:
--gbTop
--gsTopBotGroup
--gsDoubleGroup


-- Returns: -1=Not known/no planks, 0=nope, 1=has
function Has()
  af_request("elem_getpoly")
  if gnPlanks==0 then
    return -1
  end
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    s=ac_objectget("iElemGroup")
    if string.match(s, "^" .. gsDoubleGroup .. ".*") then
      ac_objectclose()
      return 1
    end
    ac_objectclose()
  end
  return 0
end


function Set(sSettings)
  gnPlankCount=0
  gtblCreate = {}

  gxmlOperations=nil
  af_request("elem_getpoly")
  if gnPlanks==0 then
    return
  end

  if sSettings~=nil then
    res, errStr=pcall(ParseSettings, sSettings)
    if res then
      default=false
    end
  end

  if default then
    -- Default settings
    GetDefaults()
  end  

  res=DoDoubleTopBot(gbTop, gsTopBotGroup, gsDoubleGroup, true)
  af_request("elem_createplanks")
end


function Reset()
  local res

  gxmlOperations=nil
  gnPlankCount=0
  gtblCreate = {}

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return false
  end

  res=DoDoubleTopBot(gbTop, gsTopBotGroup, gsDoubleGroup, false)
  af_request("elem_createplanks")     -- To adjust the studs
  return res
end


-- FOR OPTION DLG
-------------------------

-------------------------
-- SETTINGS


-- Asks for the material to use
-- sSettings may be nil, otherwise matfront=xxx\nmatback=xxx
-- Returns two values: matfront, matback, ""=use default material
-- g_zofforg, g_zoffdouble  are handled as globals
function AskMat(sSettings)
  local	tblSettings, bRes, sErr, s, s2, n, strSep, tblSorted
  local tblMat, i, id, v, thickness, height, mat
    
    
  tblMat=af_request("matlist")
  s=""
  strSep=""

  tblSorted={}
  
  tblSorted[1]={}
  tblSorted[1].name="No change/Same as the top or bottom"
  tblSorted[1].id=""
  tblSorted[1].index=1

  i=2
  for id,v in pairs(tblMat) do
    if v.thickness>0.001 then
		  tblSorted[i]=v
		  i=i+1
	  end
  end

	table.sort(tblSorted, function (n1, n2)
    return n1.index < n2.index
	end)

  for i,v in ipairs(tblSorted) do
    if v.id~="" then
      s=string.format("%s%s\"%s:%s (%s)\"", s, strSep, i, v.name, v.id)
    else
      s=string.format("%s%s\"%s:%s\"", s, strSep, i, v.name)
    end
    strSep=","
  end

	tblSettings={}
	tblSettings[1]			={}
	tblSettings[1].cfgonly	=0
	tblSettings[1].type		=1
	tblSettings[1].prompt	="Material original"
	tblSettings[1].key		="matorg"
	tblSettings[1].valuelist=s
	tblSettings[1].value	=1

	tblSettings[2]			={}
	tblSettings[2].cfgonly	=0
	tblSettings[2].type		=1
	tblSettings[2].prompt	="Material double"
	tblSettings[2].key		="matdouble"
	tblSettings[2].valuelist=s
	tblSettings[2].value	=1

	tblSettings[3]			={}
	tblSettings[3].cfgonly	=0
	tblSettings[3].type		=3
	tblSettings[3].prompt	="Distance from front original"
	tblSettings[3].key		="distorg"

	tblSettings[4]			={}
	tblSettings[4].cfgonly	=0
	tblSettings[4].type		=3
	tblSettings[4].prompt	="Distance from front double"
	tblSettings[4].key		="distdouble"

  GetDefaults()
  if sSettings~=nil and sSettings~="" then
    local res, err
    res,err=pcall(ParseSettings, sSettings)
    if res then
      -- Had saved settings
      for i=1,#tblSorted do
        if tblSorted[i].id==g_matidorg then
          tblSettings[1].value=i
        end
        if tblSorted[i].id==g_matiddouble then
          tblSettings[2].value=i
        end
      end
    else
      ac_environment( "tolog", string.format("AskMat/parse settings failed: %s", tostring(err)) )
    end
  end

	tblSettings[3].value	=g_zofforg
	tblSettings[4].value	=g_zoffdouble

	bRes,sErr=ac_optiondlg("LDDB", "Double top/bottom materials", tblSettings)
	if not bRes then
    return
  end

  s=""
  if tblSettings[1].value>0 then
	  s=tblSorted[tblSettings[1].value].id
  end
  s2=""
  if tblSettings[2].value>0 then
	  s2=tblSorted[tblSettings[2].value].id
  end
  
	g_zofforg     =tblSettings[3].value
	g_zoffdouble  =tblSettings[4].value

  return s, s2
end




-- Gets value from key=value\n string
function GetVal(data, keyName)
  local k,v

	for k, v in string.gmatch(data, "([^ \r\n]+)=([^\r\n]+)") do
    --ac_environment("tolog", string.format("#%s=%s\n", k, v))
		if k == keyName then
			return v
		end
	end
  return nil
end


-- Called with pcall(), sets globals: g_matidorg, g_matiddouble (nil if use default)
function ParseSettings(sSettings)
  local s, mat
  
  GetDefaults()
  mat=GetVal(sSettings, "matorg")
  if mat and mat~="" then
    g_matidorg=af_request("singlemat", mat).id
	  string.format("%s", g_matidorg)		-- Will cause error if bad syntax
  end
  
  mat=GetVal(sSettings, "matdouble")
  if mat and mat~="" then
    g_matiddouble=af_request("singlemat", mat).id
	  string.format("%s", g_matiddouble)		-- Will cause error if bad syntax
  end

  s=GetVal(sSettings, "zofforg")
  if s and s~="" then
    g_zofforg=tonumber(s)
	  string.format("%f", g_zofforg)
  end

  s=GetVal(sSettings, "zoffdouble")
  if s and s~="" then
    g_zoffdouble=tonumber(s)
	  string.format("%f", g_zoffdouble)
  end
end


function GetDefaults()
  g_matidorg=nil
  g_zofforg=0
  g_matiddouble=nil
  g_zoffdouble=0
  return true
end


-- Return: nil=canceled, ""=clear settings/use defaults, str=settings str
function Settings(sSettings)
  -- Ask material
  local m1, m2

  m1, m2 = AskMat(sSettings)
  if m1==nil then
    return nil
  end

  s=string.format("matorg=%s\nmatdouble=%s\nzofforg=%.4f\nzoffdouble=%.4f", m1, m2, g_zofforg, g_zoffdouble)
  return s
end


-- SETTINGS
-------------------------

g_reinforceOverEnd=0.010      -- Oversize towards stud end
g_reinforceOverIn=0.002       -- Other dir
g_reinforceOverSide=0.001     -- For sides
g_reinforceDist=0             -- Distance from top/bottom

-- Adds reinforcement plank next to top/bottom sill and to front or/and back
function DoReinforce(bTop, sTopBotGroup, sDoubleGroup, sTiltedGroup, sMatId, bFront, sGroupName)
  local nPlank,s
  local tblDouble, tblTop   -- Fields: index, guid, thickness, matid, tblElemData, tblStuds
  local nDouble, nTop, nTopIndex, matInfo, tblTilt, nTilt

  gAddAllStuds=true
  gtblSelPlanks=af_request("getselplanks")
  tblTop,nTop=FindPlanks(sDoubleGroup, bTop)
  if nTop==0 then
    tblTop,nTop=FindPlanks(sTopBotGroup, bTop)
  end
  if sTiltedGroup~=nil then
    -- Handling also tilted (gable walls), add those
    tblTilt, nTilt=FindPlanks(sTiltedGroup, bTop)
    if nTilt>0 then
      -- Merge
      for nTopIndex=1,nTilt do
        nTop=nTop+1
        tblTop[nTop] = tblTilt[nTopIndex]
      end
    end
  end
  
  if nTop==0 then
    RaiseError("CANNOT FIND TOP/BOTTOM PLANK")
    return
  end
  
  if sMatId==nil or sMatId=="" then
    sMatId=af_request("elem_getstudmat")
  end
  
  matInfo=af_request("singlemat", sMatId)
  if matInfo==nil then
    RaiseError(string.format("CANNOT FIND MATERIAL ID=%s", sMatId))
    return
  end
  
  strXmlOp=""
  -- Add new
  local tblNew, tblTopNow, dx, dy, xOff, yOff, len, offset, sStuds
  
  for nPlank=1,nTop do
    tblTopNow=tblTop[nPlank]
      
    tblNew={}
    tblNew.id=sMatId
    tblNew.guidsettings=tblTopNow.ptr
    tblNew.group=sGroupName
    dx=tblTopNow.tblElemData.x2 - tblTopNow.tblElemData.x1
    dy=tblTopNow.tblElemData.y2 - tblTopNow.tblElemData.y1
    len=math.sqrt(dx*dx + dy*dy)
    
    if len>0.001 then
      len=1/len
      dx=dx*len
      dy=dy*len
      offset=tblTopNow.thickness*0.5+g_reinforceDist
      dx,dy=-dy,dx        -- For bottom (comes ok if plank goes from left to right)
      if dy<0 then
        dx=-dx
        dy=-dy
      end
      if bTop then
        offset=offset+matInfo.height
        offset=-offset
      end
      tblNew.x1=tblTopNow.tblElemData.x1+offset*dx
      tblNew.y1=tblTopNow.tblElemData.y1+offset*dy
      tblNew.x2=tblTopNow.tblElemData.x2+offset*dx
      tblNew.y2=tblTopNow.tblElemData.y2+offset*dy
      tblNew.zoff=matInfo.thickness*0.5
      if not bFront then
        tblNew.zoff=af_request("elemcorethickness") - matInfo.thickness*0.5
      end

      tblNew.rotangle=90   -- refline at bottom
      tblNew.mayturn=1
      --tblNew.xmlsettings="<s><objparam name=\"iCnc\">0</objparam></s>"
      
      -- May have been joined pieces
      local endptr
      
      endptr=tblTopNow.lastjoinedptr
      if endptr==nil then
        endptr=tblTopNow.ptr
      end

      tblNew.postlua=
string.format(
"<s>\n" ..
"ac_objectopen(\"%s\")\n" ..
"planeBeg=af_request(\"getbegendplane\", \"beg\")\n" ..
"ac_objectclose()\n" ..
"ac_objectopen(\"%s\")\n" ..
"planeEnd=af_request(\"getbegendplane\", \"end\")\n" ..
"ac_objectclose()\n" ..
"ac_objectopen(\"#%d\")\n" ..
"af_request(\"adjustbegend\", \"beg\", planeBeg)\n" ..
"af_request(\"adjustbegend\", \"end\", planeEnd)\n" ..
"ac_objectclose()\n" ..
"</s>",
tblTopNow.ptr,
endptr,
gnPlanks+gnPlankCount+1 )

      gnPlankCount=gnPlankCount+1
      gtblCreate[gnPlankCount] = tblNew

      -- Grooves from this plank
      sStuds=""
      for i,v in ipairs(tblTopNow.tblStuds) do
        -- Set oversize to top&bottom, other side will be cutting air (and makes sure the groove goes all the way to the plank's end
        if sStuds~="" then
          sStuds=sStuds .. ","
        end
        sStuds=sStuds .. v
      end
      if sStuds~="" then
        local overbot, overtop
        
        -- Plank is always bottom down
        overbot=g_reinforceOverEnd
        overtop=g_reinforceOverIn
        if bTop then
          overbot=g_reinforceOverIn
          overtop=g_reinforceOverEnd
        end
        strXmlOp = string.format( 
            "%s" ..
            "<groove target=\"#%s\" operator=\"#%d\">\n" ..
            "    <groove overtop=\"%.3f\" overbot=\"%.3f\" overside=\"%.3f\" overlen=\"0.1\" force90=\"1\"></groove>\n" ..
            "</groove>\n",
            strXmlOp, sStuds, gnPlanks+gnPlankCount, overtop, overbot, g_reinforceOverSide
          )
      end
    end
  end

  -- Join tilted planks together, NOPE ADJUST
  if false then
    strXmlOp = string.format( 
        "%s" ..
        "<joinends target=\"%s\" operator=\"%s\">\n" ..
        "    <joinends conntype=\"linex\" jointgap=\"0\"></joinends>\n" ..
        "</joinends>\n",
        strXmlOp, sGroupName, sGroupName )
  end

  -- Add xml-operations to be run after new planks are initialized
  if strXmlOp~="" then
    if gxmlOperations==nil then
      gxmlOperations=string.format("<operations>\n%s</operations>", strXmlOp)
    else
      gxmlOperations=string.format("%s\n%s</operations>", string.sub(gxmlOperations, 1, string.len(gxmlOperations)-13), strXmlOp)
    end
  end
end
]]>
        </script>


        <!-- Splits to two pieces/joints back top&bottom woods -->
        <script id="splittopbot">
          <![CDATA[
-- For planks to be created
gnPlankCount=0
gtblCreate = {}


-- Formats message so that calling program shows just the msg
-- Message can be empty - nothing is showed then (if operation canceled)
function RaiseError(msg)
	msg="###>" ..  msg .. "<###"
	error( msg )
end


gtblSelPlanks=nil

function GetThickness()
	local	width
	
	width=ac_objectget("iWidth")
	if width==nil or width==0.0 then
		width=ac_objectget("A")
	end
   return width
end

function GetHeight()
	local	width
	
	width=ac_objectget("iHeight")
	if width==nil or width==0.0 then
		width=ac_objectget("B")
	end
   return width
end

-- Creates table of matching planks
-- Table fields: index, thickness, height, matid, tblElemData
-- Returns table, number of items
function FindPlanks(sGroup, bTop)
  local nPlank,s
  local tblRes, tblNow, tblInfo
  local nRes, i, v
  
  nRes=0
  tblRes={}
  if gtblSelPlanks then
    -- Check if selection contains wanted group and use it if yes
    for i,v in pairs(gtblSelPlanks) do
      ac_objectopen(v)
      s=ac_objectget("iElemGroup")
      
      tblNow=nil
      if s~=nil and s==sGroup then
        tblInfo=af_request("plankinfo")
        if tblInfo.del~=true then
          tblNow={}
          tblNow.ptr=tblInfo.ptr
          tblNow.thickness=GetThickness()
          tblNow.height=GetHeight()
          tblNow.matid=ac_objectget("iMatId")
          tblNow.tblElemData=ac_objectget("#af_elemdata")
          if tblNow.tblElemData then      -- If selected from multiple elements - will return data only if related to current element
            tblNow.index=tblNow.tblElemData.index
            nRes=nRes+1
            tblRes[nRes]=tblNow
          else
            tblNow=nil
          end

        end
      end
      ac_objectclose()

    end

    if nRes>0 then
      return tblRes,nRes
    end
  end

  for nPlank=1,gnPlanks do
    ac_objectopen(string.format("#%d", nPlank))
    s=ac_objectget("iElemGroup")
    tblNow=nil
    if s==sGroup then
      tblInfo=af_request("plankinfo")
      if tblInfo.del~=true then
        nRes=nRes+1
        tblNow={}
        tblNow.ptr=tblInfo.ptr
        tblNow.thickness=GetThickness()
        tblNow.height=GetHeight()
        tblNow.matid=ac_objectget("iMatId")
        tblNow.tblElemData=ac_objectget("#af_elemdata")
        tblNow.index=tblNow.tblElemData.index
        tblRes[nRes]=tblNow
      end
    end
    ac_objectclose()
  end

  return tblRes,nRes
end


function ChangeMat(guidPlank, matId, bTop)
  local tblMat, level, prevThick

  tblMat=af_request("singlemat", matId)
  ac_objectopen(guidPlank)
  prevThick=GetThickness()
  ac_objectset("iMatId", matId)
  ac_objectset("iWidth", tblMat.thickness)
  ac_objectset("iHeight", tblMat.height)

  level=ac_objectget("#level")
  if bTop then
    level=level+(tblMat.thickness-prevThick)*0.5
  else
    level=level-(tblMat.thickness-prevThick)*0.5
  end

  ac_objectset("#level", level)
  ac_objectclose()
end


-- bAdd true=adding, false=deleting, nil=on/off
function DoSplitTopBot(bTop, sTopBotGroup, sDoubleGroup, bAdd, idSplitFront, idSplitBack)
  local nPlank,s
  local tblDouble, tblTop   -- Fields: index, guid, thickness, matid, tblElemData
  local nDouble, nTop, nTopIndex
  local thicknessSplit


  --idSplitFront="42x98"
  --idSplitBack="42x42"

  gtblSelPlanks=af_request("getselplanks")
  tblDouble,nDouble=FindPlanks(sDoubleGroup, bTop)
  tblTop,nTop=FindPlanks(sTopBotGroup, bTop)
  
  if nTop==0 then
    -- No error msg if from option dlg
    if gbTop==nil then
      RaiseError("CANNOT FIND TOP/BOTTOM PLANK")
    end
    return
  end

  if bAdd~=nil then
    if bAdd then
      if nDouble>0 then
        return
      end
    else
      -- Removing
      if nDouble==0 then
        return
      end
    end
  end

  strXmlOp=""
  if nDouble>0 then
    -- Remove
    for nPlank=1,nDouble do
      -- Set zero length to be cleaned away
      ac_objectopen(string.format("#%d", tblDouble[nPlank].index))
      af_request("delplank")
      ac_objectclose()
    end
    
    -- Change material to default
    local matId
    
    matId=af_request("elem_getstudmat")
    for nPlank=1,nTop do
      tblTopNow=tblTop[nPlank]
      ChangeMat(string.format("#%d", tblTopNow.index), matId, bTop)
    end

  else
    -- Change existing to smaller and add new
    local tblNew, tblTopNow, tblMat, level

    for nPlank=1,nTop do
      tblTopNow=tblTop[nPlank]
      
      -- Back piece
      tblMat=af_request("singlemat", idSplitBack)

      tblNew={}
      tblNew.guidsettings=tblTopNow.ptr
      tblNew.group=sDoubleGroup
      tblNew.x1=tblTopNow.tblElemData.x1
      tblNew.x2=tblTopNow.tblElemData.x2
      if bTop then
        tblNew.y1=tblTopNow.tblElemData.y1+(tblMat.thickness-tblTopNow.thickness)*0.5
        tblNew.y2=tblTopNow.tblElemData.y2+(tblMat.thickness-tblTopNow.thickness)*0.5
      else
        tblNew.y1=tblTopNow.tblElemData.y1-(tblMat.thickness-tblTopNow.thickness)*0.5
        tblNew.y2=tblTopNow.tblElemData.y2-(tblMat.thickness-tblTopNow.thickness)*0.5
      end

      tblNew.zoff=tblTopNow.height-tblMat.height
      tblNew.id=idSplitBack
      tblNew.rotAngle=0

      gnPlankCount=gnPlankCount+1
      gtblCreate[gnPlankCount] = tblNew

      -- Change front piece material
      ChangeMat(string.format("#%d", tblTopNow.index), idSplitFront, bTop)
    end
  end

  return ""
end



-------------------------
-- FOR OPTION DLG

--Set these:
--gbTop
--gsTopBotGroup
--gsSplitGroup


-- Returns: -1=Not known/no planks, 0=nope, 1=has
function Has()
  af_request("elem_getpoly")
  if gnPlanks==0 then
    return -1
  end
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    s=ac_objectget("iElemGroup")
    if string.match(s, "^" .. gsSplitGroup .. ".*") then
      ac_objectclose()
      return 1
    end
    ac_objectclose()
  end
  return 0
end


function Set(sSettings)
  local default, res, errStr

  gnPlankCount=0
  gtblCreate = {}

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return
  end
  
  default=true
  if sSettings~=nil then
    res, errStr=pcall(ParseSettings, sSettings)
    if res then
      default=false
    end
  end

  if default then
    -- Default settings
    GetDefaults()
  end  

--ac_environment("tolog", string.format("g_matidfront=%s, g_matidback=%s", tostring(g_matidfront), tostring(g_matidback)) )
  res=DoSplitTopBot(gbTop, gsTopBotGroup, gsSplitGroup, true, g_matidfront, g_matidback)

  af_request("elem_createplanks")
end


function Reset()
  local res

  gnPlankCount=0
  gtblCreate = {}

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return false
  end

  res=DoSplitTopBot(gbTop, gsTopBotGroup, gsSplitGroup, false, nil, nil)
  af_request("elem_createplanks")     -- To adjust the studs
  return res
end


function dump(o)
  if type(o) == 'table' then
    local s = '{ '
    for k,v in pairs(o) do
      if type(k) ~= 'number' then k = '"'..k..'"' end
      s = s .. '['..k..'] = ' .. dump(v) .. ','
    end
    return s .. '} '
  else
    return tostring(o)
  end
end


-- Asks for the material to use
-- sSettings may be nil, otherwise matfront=xxx\nmatback=xxx
-- Returns two values: matfront, matback
function AskMat(sSettings)
  local	tblSettings, bRes, sErr, s, n, strSep, tblSorted
  local tblMat, i, id, v, thickness, height, mat
    
    
  tblMat=af_request("matlist")
  s=""
  strSep=""

--ac_environment("tolog", dump(tblMat))
  tblSorted={}
  i=1
  for id,v in pairs(tblMat) do
    if v.thickness>0.001 then
  		tblSorted[i]=v
	  	i=i+1
	  end
  end

	table.sort(tblSorted, function (n1, n2)
    return n1.index < n2.index
	end)

  for i,v in ipairs(tblSorted) do
    s=string.format("%s%s\"%s:%s (%s)\"", s, strSep, i, v.name, v.id)
    strSep=","
  end

	tblSettings={}
	tblSettings[1]			={}
	tblSettings[1].cfgonly	=0
	tblSettings[1].type		=1
	tblSettings[1].prompt	="Material front"
	tblSettings[1].key		="matfront"
	tblSettings[1].valuelist=s
	tblSettings[1].defvalue	=1

	tblSettings[2]			={}
	tblSettings[2].cfgonly	=0
	tblSettings[2].type		=1
	tblSettings[2].prompt	="Material back"
	tblSettings[2].key		="matback"
	tblSettings[2].valuelist=s
	tblSettings[2].defvalue	=1

  
  if sSettings~=nil and sSettings~="" then
    local res, err
    res,err=pcall(ParseSettings, sSettings)
    if res then
      -- Had saved settings
      for i=1,#tblSorted do
        if tblSorted[i].id==g_matidfront then
          tblSettings[1].value=i
        end
        if tblSorted[i].id==g_matidback then
          tblSettings[2].value=i
        end
      end
    else
      ac_environment( "tolog", string.format("AskMat/parse settings failed: %s", tostring(err)) )
    end
  end

	bRes,sErr=ac_optiondlg("LDSB", "Split materials", tblSettings)
	if not bRes then
    return
  end
    
  return tblSorted[tblSettings[1].value], tblSorted[tblSettings[2].value]
end




-- Gets value from key=value\n string
function GetVal(data, keyName)
  local k,v

	for k, v in string.gmatch(data, "([^ \r\n]+)=([^\r\n]+)") do
    --ac_environment("tolog", string.format("#%s=%s\n", k, v))
		if k == keyName then
			return v
		end
	end
  return nil
end


-- Called with pcall(), sets globals: g_matidfront, g_matidback
function ParseSettings(sSettings)
  local s, mat
  
  --ac_environment("tolog", string.format("sSettings=%s\n", sSettings) )

  mat=GetVal(sSettings, "matfront")
  g_matidfront=af_request("singlemat", mat).id
  mat=GetVal(sSettings, "matback")
  g_matidback=af_request("singlemat", mat).id

  -- Will cause error if bad syntax
  s = string.format("%s, %s", g_matidfront, g_matidback)
end


function GetDefaults()
  g_matidfront="42x42"
  g_matidback="42x42"
  return true
end


-- Return: nil=canceled, ""=clear settings/use defaults, str=settings str
function Settings(sSettings)
  if sSettings==nil or sSettings=="" then
    if GetDefaults() then
      sSettings=string.format("matfront=%s\nmatback=%s", g_matidfront, g_matidback)
    end
  end
  -- Ask material
  local matfront, matback

  matfront, matback = AskMat(sSettings)
  if matfront==nil then
    return nil
  end

  s=string.format("matfront=%s\nmatback=%s", matfront.id, matback.id)
  return s
end


-- FOR OPTION DLG
-------------------------

]]>
        </script>

        <!-- Adds top beam  -->
        <script id="balktop">
          <![CDATA[
-- Lua script, see ArchiFrame manual

-- For planks to be created
gnPlankCount=0
gtblCreate = {}


function dump(o)
  if type(o) == 'table' then
    local s = '{ '
    for k,v in pairs(o) do
      if type(k) ~= 'number' then k = '"'..k..'"' end
      s = s .. '['..k..'] = ' .. dump(v) .. ','
    end
    return s .. '} '
  else
    return tostring(o)
  end
end


-- Asks for the material to use
-- sSettings may be nil, otherwise mat=xxx\nthickness=x\nheight=x\ntopoff=x
-- Returns five values: matid, thickness, height, top offset, number of planks
function AskMat(sSettings)
	local	tblSettings, bRes, sErr, s, n, strSep, tblSorted
  local tblMat, i, id, v, thickness, height, mat
    
    
  tblMat=af_request("matlist")
  s=""
  strSep=""
    
  tblSorted={}
  for id,v in pairs(tblMat) do
    tblSorted[v.index]=v
  end

  for i,v in ipairs(tblSorted) do
    s=string.format("%s%s\"%s:%s (%s)\"", s, strSep, i, v.name, v.id)
    strSep=","
  end

	tblSettings={}
	tblSettings[1]			={}
	tblSettings[1].cfgonly	=0
	tblSettings[1].type		=1
	tblSettings[1].prompt	="Material"
	tblSettings[1].key		="balkmat"
	tblSettings[1].valuelist=s
	tblSettings[1].defvalue	=1

	tblSettings[2]			={}
	tblSettings[2].cfgonly	=0
	tblSettings[2].type		=3
	tblSettings[2].prompt	="Thickness if not fixed"
	tblSettings[2].key		="thickness"
	tblSettings[2].defvalue	=0.050

	tblSettings[3]			={}
	tblSettings[3].cfgonly	=0
	tblSettings[3].type		=3
	tblSettings[3].prompt	="Height if not fixed"
	tblSettings[3].key		="height"
	tblSettings[3].defvalue	=0.100

	tblSettings[4]			={}
	tblSettings[4].cfgonly	=0
	tblSettings[4].type		=3
	tblSettings[4].prompt	="Balk distance from element top (top wood thickness)"
	tblSettings[4].key		="topoff"
	tblSettings[4].defvalue	=0.041
  
	tblSettings[5]			={}
	tblSettings[5].cfgonly	=0
	tblSettings[5].type		=1
	tblSettings[5].prompt	="Number of planks to add"
	tblSettings[5].key		="numplanks"
	tblSettings[5].valuelist="\"1:1\",\"2:2\",\"3:3\""
	tblSettings[5].defvalue	=1

  if sSettings~=nil and sSettings~="" then
    local res, err
    res,err=pcall(ParseSettings, sSettings)
    if res then
      -- Had saved settings
      for i=1,#tblSorted do
        if tblSorted[i].id==g_mat.id then
          tblSettings[1].value=i
          break
        end
      end
      tblSettings[2].value=g_thickness
      tblSettings[3].value=g_height
      tblSettings[4].value=g_topOff
      tblSettings[5].value=g_numPlanks
    else
      ac_environment( "tolog", string.format("AskMat/parse settings failed: %s", tostring(err)) )
    end
  end

	bRes,sErr=ac_optiondlg("LDEM", "Top balk material", tblSettings)
	if not bRes then
    return
  end
    
  mat=tblSorted[tblSettings[1].value]
  thickness=mat.thickness
  height=mat.height
  if thickness==0.0 then
    thickness=tblSettings[2].value
  end
  if height==0.0 then
    height=tblSettings[3].value
  end


  return mat, thickness, height, tblSettings[4].value, tblSettings[5].value
end


-- Adds top balk(s) below the upper with group names:
-- balktop Horizontal balk
-- balktopinclined  Inclined one
-- nZoff  -100=to front side, 100=to back side, others=value to use
-- nOffsetToIn  Move inwards from edge with this value, nil=use mat thickness
-- nMatThickness, nMatHeight If generic "block", "round" etc type. nil if defined by strMatId
-- sInOut "in", "out" or nil=""
-- numPlanks  Number of planks to add, nil=1
-- Returns two values:
-- 1. join gable planks togeteher operations without <operations>-tag or "" if none
-- 2. table of innest added piece in format "#num", empty tbl=not added
function DoTopBelow( strMatId, nZoff, nOffsetToIn, nMatThickness, nMatHeight, sInOut, numPlanks )
  local i, v, tblNew, nx, ny, len, dist, lastContour, i2, edgeNew, edgeOp, x, y, nPlank, thickness
  local nNewCount, preNewCount, tblNewEdges, strXmlOp, tblMat, tblLastAdded, nLastAdded
  
  if sInOut==nil then
    sInOut=""
  end

  if numPlanks==nil then
    numPlanks=1
  end

  nNewCount=0
  tblNewEdges={}
  gxmlOperations=nil
  strXmlOp=""
  tblLastAdded={}
  nLastAdded=0

  -- Actually not used always
  tblMat=af_request( "singlemat", strMatId )
  if tblMat==nil then
    error( string.format("Material %s not found", strMatId) )
  end
  
  thickness=tblMat.thickness
  if nMatThickness then
    if nMatThickness>0 then
      thickness=nMatThickness
    end
  end

  if nZoff>99 then
    -- Assume the element has same material as top balk, back side
    nZoff=tblMat.height - 0.5 * thickness
  end
  if nZoff<-99 then
    -- Assume the element has same material as top balk, front side
    nZoff=0.5 * thickness
  end
  if nOffsetToIn==nil then
    nOffsetToIn=thickness
  end
 
  lastContour=#gtblEdges      -- #=Number of items in tbl
  for nPlank=1,numPlanks do
    preNewCount=nNewCount

    for i,v in ipairs(gtblEdges) do
  --ac_environment("tolog", dump(v))
  --ac_msgbox(string.format("v.holeindex=%d v.x1=%.3f v.y1=%.3f v.x2=%.3f v.y2=%.3f", v.holeindex, v.x1, v.y1, v.x2, v.y2))

      -- Process only contour line
      if v.holeindex~=0 then
        lastContour=i-1
        break
      end

      if math.abs(v.x1-v.x2)>0.010 and af_hasedgex(i, 0, 1)==false then
        -- Topmost edge, add to temporary tbl and apply offset
        -- Calc normal to left
        nx=-(v.y2-v.y1)
        ny=v.x2-v.x1
        len=math.sqrt(nx*nx + ny*ny)
        if len>0.001 then
          nx=nOffsetToIn*nx/len
          ny=nOffsetToIn*ny/len

          tblNew={}
          if v.tblPlankNums~=nil then
            -- need to set to have projections updated ok
            tblNew.guidsettings=v.ptr
          else
            -- Comes ok 12/2017: ac_environment("tolog", "Lua Warning: Created plank not in projections - please update element manually\n" )
          end

          tblNew.group=string.format("balktop%s", sInOut)
          if math.abs(v.y1-v.y2)>0.001 then
            tblNew.group=string.format("balktop%sinclined", sInOut)
          end
      
          tblNew.id=strMatId
          tblNew.thickness=nMatThickness
          tblNew.height=nMatHeight
          tblNew.zoff=nZoff
          if sInOut=="in" then
            tblNew.zoff=tblNew.zoff-(nPlank-1)*thickness
          else
            tblNew.zoff=tblNew.zoff+(nPlank-1)*thickness
          end
          tblNew.rotangle=90
          tblNew.orgx1=v.x1
          tblNew.orgy1=v.y1
          tblNew.orgx2=v.x2
          tblNew.orgy2=v.y2
        
          -- Apply offset
          tblNew.x1=v.x1+nx
          tblNew.y1=v.y1+ny
          tblNew.x2=v.x2+nx
          tblNew.y2=v.y2+ny

          -- To calcl connections later
          tblNew.orgIndex=i
          tblNew.begHandled=false
          tblNew.endHandled=false

          nNewCount=nNewCount+1
          tblNewEdges[nNewCount]=tblNew
          
          if nPlank==numPlanks then
            nLastAdded=nLastAdded+1
            tblLastAdded[nLastAdded]=string.format("#%d", gnPlanks+nNewCount)
          end
        end
      end
    end

    -- Adjust end points for connected planks (remember ccw direction for edges)
    local i2
    for i=preNewCount+1,nNewCount+1 do
      i2=i+1
      if i2>nNewCount then
        i2=preNewCount+1
      end
      if tblNewEdges[i]~=nil and i2<=nNewCount then
        if math.abs(tblNewEdges[i].orgx2-tblNewEdges[i2].orgx1)<0.001 and math.abs(tblNewEdges[i].orgy2-tblNewEdges[i2].orgy1)<0.001 then

          -- Curr end connected to next beg, adjust
          nx,ny=ac_geo("linex", tblNewEdges[i].x1, tblNewEdges[i].y1, tblNewEdges[i].x2, tblNewEdges[i].y2, tblNewEdges[i2].x1, tblNewEdges[i2].y1, tblNewEdges[i2].x2, tblNewEdges[i2].y2)
          if nx~=nil then
            -- has intersection, check if deleted totally
            dist,len=ac_geo("linedist", tblNewEdges[i].x1, tblNewEdges[i].y1, tblNewEdges[i].x2, tblNewEdges[i].y2, nx, ny)
            if len<0.001 then
              -- deleted totally
              tblNewEdges[i]=nil
            else
              -- Adjust
              tblNewEdges[i].x2=nx
              tblNewEdges[i].y2=ny
              tblNewEdges[i].endHandled=true
            end
          
            -- Check next edge
            dist,len,lineLen=ac_geo("linedist", tblNewEdges[i2].x2, tblNewEdges[i2].y2, tblNewEdges[i2].x1, tblNewEdges[i2].y1, nx, ny)
            if len<0.001 then
              -- deleted totally
              tblNewEdges[i2]=nil
            else
              -- Adjust
              tblNewEdges[i2].x1=nx
              tblNewEdges[i2].y1=ny
              tblNewEdges[i2].begHandled=true
            end
          end
        end
      end

      if tblNewEdges[i]~=nil then
        -- Finally add
        gnPlankCount=gnPlankCount+1
        gtblCreate[gnPlankCount]=tblNewEdges[i]
        gtblCreate[gnPlankCount].mayturn=true
      
        if tblNewEdges[i2]~=nil then
          -- Adjust these two together
          strXmlOp = string.format( 
              "%s" ..
              "<joinends target=\"#%d\" operator=\"#%d\">\n" ..
              "    <joinends conntype=\"endtoend\" jointgap=\"0\"></joinends>\n" ..
              "</joinends>\n",
              strXmlOp, gnPlanks+i, gnPlanks+i2
            )
        end
      end
    end
  
    -- Extend at corner edges to contour studs
    for i=preNewCount+1,nNewCount do
      if tblNewEdges[i]~=nil then
        if tblNewEdges[i].begHandled==false then
          -- Connect beg with previous edge
          i2=tblNewEdges[i].orgIndex-1
          if i2==0 then
             i2=lastContour
          end

          if gtblEdges[i2].tblPlankNums~=nil then
            edgeNew=tblNewEdges[i]
            edgeOp=gtblEdges[i2]
            x,y=ac_geo( "linex", edgeNew.x1, edgeNew.y1, edgeNew.x2, edgeNew.y2, edgeOp.x1, edgeOp.y1, edgeOp.x2, edgeOp.y2 )
            if x~=nil then
              -- Adjust end pt to the crossing to make it clear of which end to save in jointo-operation
              edgeNew.x1=x
              edgeNew.y1=y
            end

            strXmlOp = string.format( 
                "%s" ..
                "<jointo target=\"#%d\" operator=\"#%d\">\n" ..
                "    <cut toend=\"1\"></cut>\n" ..
                "</jointo>\n",
                strXmlOp, gnPlanks+i, gtblEdges[i2].tblPlankNums[1]
              )
          end
        end

        if tblNewEdges[i].endHandled==false then
          -- Connect beg with previous edge
          i2=tblNewEdges[i].orgIndex+1
          if i2>lastContour then
             i2=1
          end

          if gtblEdges[i2].tblPlankNums~=nil then
            edgeNew=tblNewEdges[i]
            edgeOp=gtblEdges[i2]
            x,y=ac_geo( "linex", edgeNew.x1, edgeNew.y1, edgeNew.x2, edgeNew.y2, edgeOp.x1, edgeOp.y1, edgeOp.x2, edgeOp.y2 )
            if x~=nil then
              -- Adjust end pt to the crossing to make it clear of which end to save in jointo-operation
              edgeNew.x2=x
              edgeNew.y2=y
            end

            strXmlOp = string.format( 
                "%s" ..
                "<jointo target=\"#%d\" operator=\"#%d\">\n" ..
                "    <cut toend=\"1\"></cut>\n" ..
                "</jointo>\n",
                strXmlOp, gnPlanks+i, gtblEdges[i2].tblPlankNums[1]
              )
          end
        end
      end
    end
    
  end

  -- Add xml-operations to be run after new planks are initialized
  if strXmlOp~="" then
    gxmlOperations=string.format("<operations>\n%s</operations>", strXmlOp)
  end

  return strXmlOp, tblLastAdded
end


-------------------------
-- FOR OPTION DLG

--Set these:
--gOptGroupName="balktopin"
--gOptInOut="in"



-- Gets value from key=value\n string
function GetVal(data, keyName)
  local k,v

	for k, v in string.gmatch(data, "([^ \r\n]+)=([^\r\n]+)") do
    --ac_environment("tolog", string.format("#%s=%s\n", k, v))
		if k == keyName then
			return v
		end
	end
  return nil
end


-- Called with pcall(), sets globals: g_mat, g_thickness, g_height, g_topOff
function ParseSettings(sSettings)
  local s, mat, val
  
  --ac_environment("tolog", string.format("sSettings=%s\n", sSettings) )

  mat=GetVal(sSettings, "mat")
  g_mat=af_request("singlemat", mat)
  g_thickness=g_mat.thickness
  g_height=g_mat.height
  if g_thickness==0.0 then
    g_thickness=tonumber(GetVal(sSettings, "thickness"))
  end
  if g_height==0.0 then
    g_height=tonumber(GetVal(sSettings, "height"))
  end
  g_topOff=tonumber(GetVal(sSettings, "topoff"))
  
  val=GetVal(sSettings, "numplanks")
  g_numPlanks=1
  if val then
    g_numPlanks=tonumber(val)
  end

  -- Will cause error if bad syntax
  s = string.format("%s, thickness=%f, height=%f, topOff=%f, numPlanks=%d\n", g_mat.id, g_thickness, g_height, g_topOff, g_numPlanks)
end


-- Top balk options
function GetDefaults()
  local mat, i, secondWidth, tblInfo, s, nPlanks
  
  mat=af_request("elem_getstudmat")
  if mat==nil then
    return false
  end

  g_mat=af_request("singlemat", mat)
  if g_mat==nil then
    return false
  end

  g_thickness=g_mat.thickness
  g_height=g_mat.height
  
  -- Look for "top_force" plank
  g_topOff=nil
  secondWidth=0
  nPlanks=gnPlanks
  if not nPlanks then
    nPlanks=0
  end
  for i=1,nPlanks do
    ac_objectopen(string.format("#%d",i))
    s=ac_objectget("iElemGroup")
    if string.match(s, "^top_force.*") or string.match(s, "^contourtilted.*") then
      tblInfo=af_request("plankinfo")
      g_topOff=tblInfo.width
    elseif string.match(s, "^2ndtop_force.*") then
      tblInfo=af_request("plankinfo")
      if not tblInfo.del then
        secondWidth=tblInfo.width
      end
    end
    ac_objectclose()
  end

  if g_topOff==nil then
    g_topOff=g_thickness
  else
    g_topOff=g_topOff+secondWidth
  end

  g_numPlanks=1
  return true
end


-- Returns: -1=Not known/no planks, 0=nope, 1=has
function Has()
  local i

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return -1
  end
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    s=ac_objectget("iElemGroup")
    if string.match(s, "^" .. gOptGroupName .. ".*") then
      ac_objectclose()
      return 1
    end
    ac_objectclose()
  end
  return 0
end


-- Return: nil=canceled, ""=clear settings/use defaults, str=settings str
function Settings(sSettings)
  if sSettings==nil or sSettings=="" then
    if GetDefaults() then
      sSettings=string.format("mat=%s\nthickness=%f\nheight=%f\ntopoff=%f\nnumplanks=%d", g_mat.id, g_thickness, g_height, g_topOff, g_numPlanks)
    end
  end
  -- Ask material
  local mat, thickness, height, topOff, numPlanks
  mat, thickness, height, topOff, numPlanks = AskMat(sSettings)
  if mat==nil then
    return nil
  end

  s=string.format("mat=%s\nthickness=%f\nheight=%f\ntopoff=%f\nnumplanks=%d", mat.id, thickness, height, topOff, numPlanks)
  return s
end


function Set(sSettings)
  local default, res, errStr, zoff, tblLastAdded, i, v, s, overL, overR, thickness
  
  gnPlankCount=0
  gtblCreate = {}

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return
  end

  default=true
  if sSettings~=nil then
    res, errStr=pcall(ParseSettings, sSettings)
    if res then
      default=false
    end
  end

  if default then
    -- Default settings
    GetDefaults()
  end

  elemThick=af_request("elemcorethickness")
  custThick=nil
  thickness=g_mat.thickness
  if g_mat.thickness==0.0 then
    custThick=g_thickness
    thickness=g_thickness
  end

  custHeight=nil
  if g_mat.height==0.0 then
    custHeight=g_height
  end

  zoff=g_thickness*0.5
  if gOptInOut=="in" then
    zoff=elemThick-zoff
  end
  res, tblLastAdded=DoTopBelow( g_mat.id, zoff, g_topOff, custThick, custHeight, gOptInOut, g_numPlanks )
  
  if gxmlOperations==nil then
    gxmlOperations=""
  end

  -- Single groove for the deepest plank
  overL=0
  overR=0
  if g_numPlanks>1 then
    if gOptInOut=="in" then
      overR=overR+thickness*(g_numPlanks-1)
    else
      overL=overL+thickness*(g_numPlanks-1)
    end
  end
  
  s=""
  for i,v in ipairs(tblLastAdded) do
    s=string.format(
      "%s" ..
      "  <groove target=\"vertical_y*|vertical_spacing|vertical_force\" operator=\"%s\">\n" ..
      "    <groove overtop=\"0.000\" overbot=\"0.010\" overleft=\"%.3f\" overright=\"%.3f\" overlen=\"0.1\"></groove>\n" ..
      "  </groove>\n",
      s, v, overL, overR )
      
  end

  gxmlOperations = string.format( "<operations>%s%s</operations>", res, s )

  af_request("elem_createplanks")
end


function Reset()
  res=false
  af_request("elem_getpoly")
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    s=ac_objectget("iElemGroup")
    if string.match(s, "^" .. gOptGroupName .. ".*") then
      s=af_request("delplank")
      res=true
    end
    ac_objectclose()
  end
  return res
end


function GetName(sSettings, baseName)
  if sSettings~=nil then
    res, errStr=pcall(ParseSettings, sSettings)
    if res then
      if g_mat.thickness~=0 then
        baseName=string.format("%s %s", baseName, g_mat.id)
      else
        baseName=string.format("%s %sx%s", baseName, ac_environment("ntos", g_thickness, "length", "work"), ac_environment("ntos", g_height, "length", "work"))
      end
      
      if g_numPlanks>1 then
        baseName=string.format("%s %d pcs", baseName, g_numPlanks)
      end
    end
  end
  return baseName
end

-- FOR OPTION DLG
-------------------------


]]>
        </script>

        <!-- Creates/removes grooves top/bottom -->
        <script id="grotopbot">
          <![CDATA[
-- For planks to be created
gnPlankCount=0
gtblCreate = {}
gnGroDepth=0.002


-- Returns string of ptrs for rotateted studs (to be excluded for making grooves)
function FindRotStuds()
  local i, rotStuds, s, v

  rotStuds=""
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    s=ac_objectget("iElemGroup")
    v=ac_objectget("#af_elemdata")
    if string.match(s, "^vertical_%a*") and math.abs(v.rotangle)>1 and math.abs(v.rotangle-180)>1 then
      if rotStuds~="" then
        rotStuds=rotStuds .. ","
      end
      rotStuds=rotStuds .. v.ptr
    end

    ac_objectclose()
  end
  return rotStuds
end



function RemoveGrooves(bSave)
  local tblInfo, tblGroPlanks, nGroPlanks, bRes, bFoundGro, tblOps, k, v, klink, vlink, s

  -- To know which is top and which is bottom
  tblInfo=af_request("elem_getinfo")
  if gOptGroTop then
    -- Set vecy to point outside of top/bottom wood
    tblInfo.vecy.x=-tblInfo.vecy.x
    tblInfo.vecy.y=-tblInfo.vecy.y
    tblInfo.vecy.z=-tblInfo.vecy.z
  end
  
  -- Find top/bottom planks (having grooves)
  bFoundGro=false
  tblGroPlanks={}
  nGroPlanks=0
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    s=ac_objectget("iElemGroup")
    if gOptGroTop then
      bRes=(string.match(s, "^top.*") or string.match(s, "^2ndtop.*") or string.match(s, "^contourtilted.*"))
    else
      bRes=(string.match(s, "^bottom.*") or string.match(s, "^2ndbottom.*"))
    end

    tblOps=nil
    if bRes then
--ac_environment("tolog", string.format("s=%s", s))
      tblOps=af_request("op_get")
    end
    ac_objectclose()

    if tblOps~=nil and #tblOps>0 then
      -- Check if related planks are vertical*
      for k,v in pairs(tblOps) do
        if v.typenum==7 and #v.tbllinks>0 then
          for klink,vlink in pairs(v.tbllinks) do
            ac_objectopen(vlink.guid)
            s=ac_objectget("iElemGroup")
            if string.match(s, "^vertical.*") then
              bFoundGro=true
              if bSave then
                -- Delete male operation
                af_request("op_del", vlink.opid)
              else
                ac_objectclose()
                break
              end
            end
           ac_objectclose()
          end
        end
      end
    end   -- if

  end
  return bFoundGro
end


-- Returns: -1=Not known/no planks, 0=nope, 1=has
function Has()
  af_request("elem_getpoly")
  if gnPlanks==0 then
    return -1
  end
  
  if RemoveGrooves(false) then
    return 1
  end
  return 0
end


function Set(sSettings)
  local rotStuds

  gnPlankCount=0
  gtblCreate = {}

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return
  end
  
  rotStuds=FindRotStuds()
  if gOptGroTop then
      gxmlOperations=
    "<operations>\n" ..  
    string.format("<jointo target=\"vertical_y*|vertical_spacing|vertical_force\" targetskip=\"%s\" operator=\"top*|2ndtop*|contourtilted\">\n", rotStuds) ..
    string.format("<cut jointgap=\"-%.4f\" extendmaxlen=\"0.0\" expandopfind=\"0.001\" endshape=\"angleddelfirst\"></cut>\n", gnGroDepth) ..
    "</jointo>\n" ..
    string.format("<groove target=\"top*|2ndtop*|contourtilted\" operator=\"vertical_y*|vertical_spacing|vertical_force\"> operatorskip=\"%s\"\n", rotStuds) ..
    string.format("<groove overtop=\"0.001\" overbot=\"0.001\" overside=\"0.001\" forcedepth=\"%.4f\" force90=\"1\"></groove>\n", gnGroDepth) ..
    "</groove>\n" ..
    "</operations>"
  else
    local i, skipOp, s, v, info
  
      -- Take only pieces less than 1 m from element bottom (try to skip door tops)
    skipOp=""
    for i=1,gnPlanks do
      ac_objectopen(string.format("#%d",i))
      v=ac_objectget("#af_elemdata")
      if math.abs(v.y1-v.y2)<0.001 and v.y1>1 then
        s=ac_objectget("iElemGroup")
        if string.match(s, "^bottom%a*") then
          info=af_request("plankinfo")
          if skipOp~="" then
            skipOp=skipOp .. ","
          end
          skipOp=skipOp .. info.ptr
        end
      end
      ac_objectclose()
    end

    if skipOp~="" then
      skipOp=string.format(" operatorskip=\"%s\"", skipOp) 
    end
    
      gxmlOperations=
    "<operations>\n" ..  
    string.format("<jointo target=\"vertical_y*|vertical_spacing|vertical_force\" targetskip=\"%s\" operator=\"bottom*|2ndbottom*\"" .. skipOp ..">\n", rotStuds) ..
    string.format("<cut jointgap=\"-%.4f\" extendmaxlen=\"0.0\" expandopfind=\"0.001\" endshape=\"angleddelfirst\"></cut>\n", gnGroDepth) ..
    "</jointo>\n" ..
    string.format("<groove target=\"bottom*|2ndbottom*\" operator=\"vertical_y*|vertical_spacing|vertical_force\" operatorskip=\"%s\">\n", rotStuds) ..
    string.format("<groove overtop=\"0.001\" overbot=\"0.001\" overside=\"0.001\" forcedepth=\"%.4f\" force90=\"1\"></groove>\n", gnGroDepth) ..
    "</groove>\n" ..
    "</operations>"
  end
  
  af_request("elem_createplanks")
end


function Reset()
  gnPlankCount=0
  gtblCreate = {}

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return
  end

  -- Remove operations
  RemoveGrooves(true)

  if gOptGroTop then
      gxmlOperations=
    "<operations>\n" ..  
    "<jointo target=\"vertical_y*|vertical_spacing|vertical_force\" operator=\"top*|2ndtop*|contourtilted\">\n" ..
    string.format("<cut jointgap=\"0.000\" extendmaxlen=\"0.0\" expandopfind=\"%.4f\" endshape=\"angleddelfirst\"></cut>\n", gnGroDepth+0.0001) ..
    "</jointo>\n" ..
    "</operations>"
  else
      gxmlOperations=
    "<operations>\n" ..  
    "<jointo target=\"vertical_y*|vertical_spacing|vertical_force\" operator=\"bottom*|2ndbottom*\">\n" ..
    string.format("<cut jointgap=\"0.000\" extendmaxlen=\"0.0\" expandopfind=\"%.4f\" endshape=\"angleddelfirst\"></cut>\n", gnGroDepth+0.0001)  ..
    "</jointo>\n" ..
    "</operations>"
  end

  af_request("elem_createplanks")
end


-- FOR OPTION DLG
-------------------------

]]>
        </script>

        <script id="markingslines">
          <![CDATA[
g_bottomline  =1
g_bottomid    =0
g_topside     =0      -- 0=default, 1-N=force it
g_botside     =0
g_topline     =1
g_topid       =0
g_topside     =0
g_posbot      =3
g_postop      =3
g_markopenings=0
g_markneig    =0


-- Returns: -1=Not known/no planks, 0=nope, 1=has
function Has()
  local res, i, s, row, rows, mc, t, col, strOp
  
  af_request("elem_getpoly")
  
  res=-1
  if gnPlanks>0 then
    res=0
  end

  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    
    rows=ac_objectget("iMc",-1)
    for row=1,rows do
      mc=ac_objectget("iMc",row,1)
      if mc==303 then
        t=ac_objectget("iMc",row,11)    -- flags
        if (t % 2)==1 then
          ac_objectclose()
          res=1
          break
        end
      end
    end

    ac_objectclose()
  end

  return res
end


function Set(sSettings)
  local i, markid, sXml, bot, top, default, bot2, lang

  lang=af_request("aflang")
  if lang==nil then
    lang="eng"
  end
  gnPlankCount=0
  gtblCreate = {}
  
  default=true
  if sSettings~=nil then
    res, errStr=pcall(ParseSettings, sSettings)
    if res then
      default=false
    end
  end

  if default then
    -- Default settings
    GetDefaults()
  end  
  

 -- "    <stud line=\"3\" id=\"2\" idline=\"3\" markxpos=\"2\" markypos=\"1\" marksize=\"1.5\" marktextdir=\"0\"></stud>\n" ..
  bot=""
  if g_botside>=1 and g_botside<=6 then
    bot=bot .. string.format("forceside=\"%d\"", g_botside)
  end
  if g_bottomline==1 then
    bot=bot .. "line=\"3\""
  else
    bot=bot .. "line=\"0\""
  end
  if g_bottomid==1 then
    bot=bot .. string.format(" id=\"2\" idline=\"%d\" markxpos=\"2\" markypos=\"1\" marksize=\"1.5\" marktextdir=\"0\"", g_posbot)
  end
  
  bot2=""
  if g_markopenings==1 then
    if lang=="nor" then
      bot2=bot2 .. "<opening line=\"0\" windowtext=\"Vindu [width]x[height]\" doortext=\"Dør [width]x[height]\" marksize=\"1.5\"></opening>\n"
    elseif lang=="fin" then
      bot2=bot2 .. "<opening line=\"0\" windowtext=\"Ikk [width]x[height]\" doortext=\"Ovi [width]x[height]\" marksize=\"1.5\"></opening>\n"
    elseif lang=="swe" then
      bot2=bot2 .. "<opening line=\"0\" windowtext=\"Fönster [width]x[height]\" doortext=\"Dörr [width]x[height]\" marksize=\"1.5\"></opening>\n"
    else
    bot2=bot2 .. "<opening line=\"0\" windowtext=\"Win [width]x[height]\" doortext=\"Door [width]x[height]\" marksize=\"1.5\"></opening>\n"
  end
  end
  if g_markneig==1 then
    bot2=bot2 .. "<neighbour begtext=\"&lt;[id]\" endtext=\"[id]&gt;\" marksize=\"1.5\" marktextdir=\"1\"></neighbour>\n"
  end

  top=""
  if g_topside>=1 and g_topside<=6 then
    top=top .. string.format("forceside=\"%d\"", g_topside)
  end

  if g_topline==1 then
    top=top .. "line=\"3\""
  else
    top=top .. "line=\"0\""
  end
  if g_topid==1 then
    top=top .. string.format(" id=\"2\" idline=\"%d\" markxpos=\"2\" markypos=\"1\" marksize=\"1.5\" marktextdir=\"0\"", g_postop)
  end

  sXml="<markings>"
  if bot~="" then
    sXml=string.format("%s\n<bottomwood>\n<stud %s/>\n%s</bottomwood>", sXml, bot, bot2)
  elseif bot2~="" then
    sXml=string.format("%s\n<bottomwood>\n%s</bottomwood>", sXml, bot2)
  end
  if top~="" then
    sXml=string.format("%s\n<topwood>\n<stud %s/>\n</topwood>", sXml, top)
  end
  
  sXml=sXml .. "\n</markings>"

  af_request("elem_domarkings", sXml)
end


function Reset()
  local i, s, row, rows, mc, t, col, strOp

  gnPlankCount=0
  gtblCreate = {}

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return false
  end
  
  -- Remove any marking which is maintained by ArchiFrame
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    
    rows=ac_objectget("iMc",-1)
    for row=1,rows do
      mc=ac_objectget("iMc",row,1)
      if mc==303 then
        t=ac_objectget("iMc",row,11)    -- flags
        if (t % 2)==1 then
          for col=1,16 do
            ac_objectset("iMc", 0, row, col)
          end
          ac_objectset("iMcStr", "", row)
        end
      end
    end

    ac_objectclose()
  end

  return 0
end


-------------------------
-- OPTIONS


-- Asks for the material to use
-- sSettings may be nil, otherwise mat=xxx\nthickness=x\nheight=x\ntopoff=x
-- Returns: true=ok, false=canceled
function RunSettingsDlg(sSettings)
  local  tblSettings, bRes, sErr, s, n, strSep, tblSorted
  local tblMat, i, id, v, thickness, height, mat

  tblSettings={}
  tblSettings[1]      ={}
  tblSettings[1].cfgonly  =0
  tblSettings[1].type   =2
  tblSettings[1].prompt ="Lines bottom"
  tblSettings[1].key    ="bottomlines"
  tblSettings[1].defvalue  =1

  tblSettings[2]      ={}
  tblSettings[2].cfgonly  =0
  tblSettings[2].type   =2
  tblSettings[2].prompt ="Stud ID bottom"
  tblSettings[2].key    ="bottomstudids"
  tblSettings[2].defvalue  =0

  tblSettings[3]      ={}
  tblSettings[3].cfgonly  =0
  tblSettings[3].type   =2
  tblSettings[3].prompt ="Lines top"
  tblSettings[3].key    ="toplines"
  tblSettings[3].defvalue  =1

  tblSettings[4]      ={}
  tblSettings[4].cfgonly  =0
  tblSettings[4].type   =2
  tblSettings[4].prompt ="Stud ID top"
  tblSettings[4].key    ="topstudids"
  tblSettings[4].defvalue  =0

	tblSettings[5]			={}
	tblSettings[5].cfgonly	=0
	tblSettings[5].type		=1
	tblSettings[5].prompt	="Stud ID bottom placement"
	tblSettings[5].key		="numplanks"
	tblSettings[5].valuelist="\"1:1 Left\",\"2:2 Right\",\"3:3 Calculate position not to be under any stud\""
	tblSettings[5].defvalue	=3

	tblSettings[6]			={}
	tblSettings[6].cfgonly	=0
	tblSettings[6].type		=1
	tblSettings[6].prompt	="Stud ID top placement"
	tblSettings[6].key		="numplanks"
	tblSettings[6].valuelist="\"1:1 Left\",\"2:2 Right\",\"3:3 Calculate position not to be under any stud\""
	tblSettings[6].defvalue	=3

  tblSettings[7]      ={}
  tblSettings[7].cfgonly  =0
  tblSettings[7].type   =2
  tblSettings[7].prompt ="Mark openings to bottom"
  tblSettings[7].key    ="openings"
  tblSettings[7].defvalue  =0

  tblSettings[8]      ={}
  tblSettings[8].cfgonly  =0
  tblSettings[8].type   =2
  tblSettings[8].prompt ="Mark neighbours to bottom"
  tblSettings[8].key    ="neig"
  tblSettings[8].defvalue  =0
  
	tblSettings[9]			={}
	tblSettings[9].cfgonly	=0
	tblSettings[9].type		=1
	tblSettings[9].prompt	="Force side top"
	tblSettings[9].key		="topside"
	tblSettings[9].valuelist="\"1:1 Automatic\",\"2:2 Top\",\"3:3 Front\",\"4:4 Bottom\",\"5:5 Back\""
	tblSettings[9].defvalue	=1
  
	tblSettings[10]			={}
	tblSettings[10].cfgonly	=0
	tblSettings[10].type		=1
	tblSettings[10].prompt	="Force side bottom"
	tblSettings[10].key		="botside"
	tblSettings[10].valuelist="\"1:1 Automatic\",\"2:2 Top\",\"3:3 Front\",\"4:4 Bottom\",\"5:5 Back\""
	tblSettings[10].defvalue	=1
  
  if sSettings~=nil and sSettings~="" then
    local res, err
    res,err=pcall(ParseSettings, sSettings)
    if res then
      -- Had saved settings
      tblSettings[1].value=g_bottomline
      tblSettings[2].value=g_bottomid
      tblSettings[3].value=g_topline
      tblSettings[4].value=g_topid
      tblSettings[5].value=g_posbot
      tblSettings[6].value=g_postop
      tblSettings[7].value=g_markopenings
      tblSettings[8].value=g_markneig
      tblSettings[9].value=g_topside+1
      tblSettings[10].value=g_botside+1
    else
      ac_environment( "tolog", string.format("RunSettingsDlg/parse settings failed: %s", tostring(err)) )
    end
  end

  bRes,sErr=ac_optiondlg("LDML", "Markings settings", tblSettings)
  if not bRes then
    return false
  end

  g_bottomline  =tblSettings[1].value
  g_bottomid    =tblSettings[2].value
  g_topline     =tblSettings[3].value
  g_topid       =tblSettings[4].value
  g_posbot      =tblSettings[5].value
  g_postop      =tblSettings[6].value
  g_markopenings=tblSettings[7].value
  g_markneig    =tblSettings[8].value
  g_topside     =tblSettings[9].value-1
  g_botside  =tblSettings[10].value-1

  return true
end



-- Gets value from key=value\n string
function GetVal(data, keyName)
  local k,v

  for k, v in string.gmatch(data, "([^ \r\n]+)=([^\r\n]+)") do
    --ac_environment("tolog", string.format("#%s=%s\n", k, v))
    if k == keyName then
      return v
    end
  end
  return nil
end


-- Called with pcall(), sets globals
function ParseSettings(sSettings)
  local s
  
  g_bottomline  =tonumber(GetVal(sSettings, "bottomline"))
  g_bottomid    =tonumber(GetVal(sSettings, "bottomid"))
  g_topline     =tonumber(GetVal(sSettings, "topline"))
  g_topid       =tonumber(GetVal(sSettings, "topid"))

  g_posbot      =3
  g_postop      =3
  
  s=GetVal(sSettings, "posbot")
  if s then
    g_posbot=tonumber(s)
  end
  s=GetVal(sSettings, "postop")
  if s then
    g_postop=tonumber(s)
  end

  s=GetVal(sSettings, "opening")
  if s then
    g_markopenings=tonumber(s)
  end
  s=GetVal(sSettings, "neig")
  if s then
    g_markneig=tonumber(s)
  end
  
  s=GetVal(sSettings, "topside")
  if s then
    g_topside=tonumber(s)
  end
  s=GetVal(sSettings, "botside")
  if s then
    g_botside=tonumber(s)
  end

  -- Will cause error if bad syntax
  s = string.format("bottomline=%d\nbottomid=%d\ntopline=%d\ntopid=%d\nposbot=%d\npostop=%d\nopening=%d\nneig=%d\ntopside=%d\nbotside=%d\n", g_bottomline, g_bottomid, g_topline, g_topid, g_posbot, g_postop, g_markopenings, g_markneig, g_topside, g_botside)
end


function GetDefaults()
  g_bottomline  =1
  g_bottomid    =0
  g_topline     =1
  g_topid       =0
  g_posbot      =3
  g_postop      =3
  g_markopenings=0
  g_markneig    =0
  g_topside     =0
  g_botside     =0
  return true
end



-- Return: nil=canceled, ""=clear settings/use defaults, str=settings str
function Settings(sSettings)
  if sSettings==nil or sSettings=="" then
    if GetDefaults() then
      sSettings=string.format("bottomline=%d\nbottomid=%d\ntopline=%d\ntopid=%d\nposbot=%d\npostop=%d\nopening=%d\nneig=%d\ntopside=%d\nbotside=%d\n", g_bottomline, g_bottomid, g_topline, g_topid, g_posbot, g_postop, g_markopenings, g_markneig, g_topside, g_botside)
    end
  end

  if RunSettingsDlg(sSettings)==false then
    return nil
  end

  sSettings=string.format("bottomline=%d\nbottomid=%d\ntopline=%d\ntopid=%d\nposbot=%d\npostop=%d\nopening=%d\nneig=%d\ntopside=%d\nbotside=%d\n", g_bottomline, g_bottomid, g_topline, g_topid, g_posbot, g_postop, g_markopenings, g_markneig, g_topside, g_botside)
  return sSettings
end
]]>
        </script>


        <script id="markingsgro">
          <![CDATA[
g_grodepth=0.005
g_groover=0.001
gnDoTop=1
gnDoBot=1
gnDoOpening=1

function DoGroXml(isTop)
  local xmlOp, skipOpTop, tblVertx, nVertx, tblVerty, nVerty, tbl, skipOpVertx
  local i, ix, s, v, info, x, y, d, rotStuds

  -- Take only pieces less than 1 m from element bottom (try to skip door tops)
  -- Also make table of all vertical_x-planks (at opening top&bottom) and vertical_y not to make grooves for lintel support pieces
  rotStuds=""
  skipOpTop=""
  tblVertx={}
  nVertx=0
  tblVerty={}
  nVerty=0

--ac_environment("tolog", string.format("gnPlanks=%d", gnPlanks))
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    v=ac_objectget("#af_elemdata")
    s=ac_objectget("iElemGroup")
    if math.abs(v.y1-v.y2)<0.001 and v.y1>1 and string.match(s, "^bottom%a*") then
      info=af_request("plankinfo")
      if skipOpTop~="" then
        skipOpTop=skipOpTop .. ","
      end
      skipOpTop=skipOpTop .. info.ptr
    elseif s=="vertical_x" or s=="vertical_y" then
      tbl={}
      tbl.elemdata=v
      tbl.plankinfo=af_request("plankinfo")
        
--ac_environment("tolog", string.format("%s x1=%f x2=%f", s, tbl.elemdata.x1, tbl.elemdata.x2))
      if s=="vertical_x" then
        tbl.minx=0
        tbl.maxx=tbl.plankinfo.len
        nVertx=nVertx+1
        tblVertx[nVertx]=tbl
      else
        nVerty=nVerty+1
        tblVerty[nVerty]=tbl
      end
    end
    if string.match(s, "^vertical_%a*") and math.abs(v.rotangle)>1 and math.abs(v.rotangle-180)>1 then
      if rotStuds~="" then
        rotStuds=rotStuds .. ","
      end
      rotStuds=rotStuds .. v.ptr
    end
    ac_objectclose()
  end

  -- Find all vertical_y to skip for matching vertical_x (lintel supports). First adjust minx, maxx for each vertical_x
  local changed, changedNow, dummy

  skipOpVertx=""
  for ix=1,nVertx do
    -- Need to rescan if minx/maxx changed
    repeat
      changed=false
      for i=1,nVerty do
        x,y=ac_geo("linex", tblVertx[ix].elemdata.x1, tblVertx[ix].elemdata.y1, tblVertx[ix].elemdata.x2, tblVertx[ix].elemdata.y2, tblVerty[i].elemdata.x1, tblVerty[i].elemdata.y1, tblVerty[i].elemdata.x2, tblVerty[i].elemdata.y2)
        if x and y then
          -- Intersection must be at the end of vertical_y
          dummy,d=ac_geo("linedist", tblVerty[i].elemdata.x1, tblVerty[i].elemdata.y1, tblVerty[i].elemdata.x2, tblVerty[i].elemdata.y2, x, y)
--ac_environment("tolog", string.format("verty: x=%f y=%f d=%f", x, y, d))
          if math.abs(d-tblVerty[i].plankinfo.len-tblVertx[ix].plankinfo.width*0.5)<0.001 then
            -- vertical_y adjusted to the bottom of vertical_x, check if intersects with vertical_x
            dummy,d=ac_geo("linedist", tblVertx[ix].elemdata.x1, tblVertx[ix].elemdata.y1, tblVertx[ix].elemdata.x2, tblVertx[ix].elemdata.y2, x, y)
--ac_environment("tolog", string.format("vertx: d=%f", d))
            changedNow=false
            if d>tblVertx[ix].minx and d<tblVertx[ix].minx+tblVerty[i].plankinfo.width*0.5+0.010 then
              tblVertx[ix].minx=d+tblVerty[i].plankinfo.width*0.5
              changedNow=true
--ac_environment("tolog", string.format("minx=%f d=%f", tblVertx[ix].minx, d))
            elseif d<tblVertx[ix].maxx and d>tblVertx[ix].maxx-tblVerty[i].plankinfo.width*0.5-0.010 then
              tblVertx[ix].maxx=d-tblVerty[i].plankinfo.width*0.5
              changedNow=true
--ac_environment("tolog", string.format("maxx=%f d=%f", tblVertx[ix].maxx, d))
            end

            if changedNow then
              changed=true
              if skipOpVertx~="" then
                skipOpVertx=skipOpVertx .. ","
              end
              skipOpVertx=skipOpVertx .. tblVerty[i].plankinfo.ptr
            end

          end
        end
      end
    until not changed
  end

  xmlOp=""
  if isTop then
    if gnDoTop==1 then
      xmlOp=
      string.format("<jointo target=\"vertical_y*|vertical_spacing|vertical_force\" targetskip=\"%s\" operator=\"top*|2ndtop*|contourtilted\">\n", rotStuds) ..
      string.format("<cut jointgap=\"-%.4f\" extendmaxlen=\"0.0\" expandopfind=\"0.001\" endshape=\"angleddelfirst\"></cut>\n", g_grodepth) ..
      "</jointo>\n" ..
      string.format("<groove target=\"top*|2ndtop*|contourtilted\" operator=\"vertical_y*|vertical_spacing|vertical_force\" operatorskip=\"%s\">\n", rotStuds) ..
      string.format("<groove overtop=\"%.4f\" overbot=\"%.4f\" overside=\"%.4f\" forcedepth=\"%.4f\" force90=\"1\"></groove>\n", g_groover, g_groover, g_groover, g_grodepth) ..
      "</groove>\n"
    end
  else
    if gnDoBot==1 then
      if skipOpTop~="" then
        skipOpTop=string.format(" operatorskip=\"%s\"", skipOpTop) 
      end

      xmlOp=
      string.format("<jointo target=\"vertical_y*|vertical_spacing|vertical_force\" targetskip=\"%s\" operator=\"bottom*|2ndbottom*\"" .. skipOpTop ..">\n", rotStuds) ..
      string.format("<cut jointgap=\"-%.4f\" extendmaxlen=\"0.0\" expandopfind=\"0.001\" endshape=\"angleddelfirst\"></cut>\n", g_grodepth) ..
      "</jointo>\n" ..
      string.format("<groove target=\"bottom*|2ndbottom*\" operator=\"vertical_y*|vertical_spacing|vertical_force\" operatorskip=\"%s\">\n", rotStuds) ..
      string.format("<groove overtop=\"%.4f\" overbot=\"%.4f\" overside=\"%.4f\" forcedepth=\"%.4f\" force90=\"1\"></groove>\n", g_groover, g_groover, g_groover, g_grodepth) ..
      "</groove>\n"
    end
  end

  
  if gnDoOpening==1 then
    -- Also studs to vertical_x -planks
    s=""
    if skipOpVertx~="" then
      s=string.format(" targetskip=\"%s\"", skipOpVertx) 
      skipOpVertx=string.format(" operatorskip=\"%s\"", skipOpVertx) 
    
      -- Add rotated studs to skip items
      if rotStuds~="" then
        s=string.format("%s,%s", s, rotStuds)
        skipOpVertx=string.format("%s,%s", skipOpVertx, rotStuds)
      end
    end
    
    xmlOp=xmlOp ..
    "<jointo target=\"vertical_y*|vertical_spacing|vertical_force\" operator=\"vertical_x|contourtilted_opening\"" .. s ..">\n" ..
    string.format("<cut jointgap=\"-%.4f\" extendmaxlen=\"0.0\" expandopfind=\"0.001\" endshape=\"angleddelfirst\" conntype=\"linex\" maxdisttoend=\"0.010\"></cut>\n", g_grodepth) ..
    "</jointo>\n" ..
    "<groove target=\"vertical_x|contourtilted_opening\" operator=\"vertical_y*|vertical_spacing|vertical_force\"" .. skipOpVertx ..">\n" ..
    string.format("<groove overtop=\"%.4f\" overbot=\"%.4f\" overside=\"%.4f\" forcedepth=\"%.4f\" force90=\"1\" conntype=\"linex\" maxdisttoendop=\"0.010\"></groove>\n", g_groover, g_groover, g_groover, g_grodepth) ..
    "</groove>\n"

    -- Opening top&bottom to vertical_y
    xmlOp=xmlOp ..
    "<jointo target=\"vertical_x|contourtilted_opening\" operator=\"vertical_y*|vertical_spacing|vertical_force\">\n" ..
    string.format("<cut jointgap=\"-%.4f\" extendmaxlen=\"0.0\" expandopfind=\"0.001\" endshape=\"angleddelfirst\" conntype=\"linex\" maxdisttoend=\"0.010\"></cut>\n", g_grodepth) ..
    "</jointo>\n" ..
    "<groove target=\"vertical_y*|vertical_spacing|vertical_force\" operator=\"vertical_x|contourtilted_opening\">\n" ..
    string.format("<groove overtop=\"%.4f\" overbot=\"%.4f\" overside=\"%.4f\" forcedepth=\"%.4f\" force90=\"1\" conntype=\"linex\" mindisttoend=\"0.025\"></groove>\n", g_groover, g_groover, g_groover, g_grodepth) ..
    "</groove>\n"
  end

  return xmlOp
end


function RemoveGrooves(isTop, bSave)
  local tblInfo, tblGroPlanks, nGroPlanks, bRes, bFoundGro, tblOps, k, v, klink, vlink, s

  -- To know which is top and which is bottom
  tblInfo=af_request("elem_getinfo")
  if isTop then
    -- Set vecy to point outside of top/bottom wood
    tblInfo.vecy.x=-tblInfo.vecy.x
    tblInfo.vecy.y=-tblInfo.vecy.y
    tblInfo.vecy.z=-tblInfo.vecy.z
  end
  
  -- Find top/bottom planks (having grooves)
  bFoundGro=false
  tblGroPlanks={}
  nGroPlanks=0
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    s=ac_objectget("iElemGroup")
    if isTop then
      bRes=(string.match(s, "^top.*") or string.match(s, "^2ndtop.*") or string.match(s, "^contourtilted.*"))
    else
      bRes=(string.match(s, "^bottom.*") or string.match(s, "^2ndbottom.*"))
    end
    
    if not bRes then
      bRes=(s=="vertical_x")        -- Opening top/bottom
    end

    tblOps=nil
    if bRes then
--ac_environment("tolog", string.format("s=%s", s))
      tblOps=af_request("op_get")
    end
    ac_objectclose()

    if tblOps~=nil and #tblOps>0 then
      -- Check if related planks are vertical*
      for k,v in pairs(tblOps) do
        if v.typenum==7 and #v.tbllinks>0 then
          for klink,vlink in pairs(v.tbllinks) do
            ac_objectopen(vlink.guid)
            s=ac_objectget("iElemGroup")
            if string.match(s, "^vertical.*") then
              bFoundGro=true
              if bSave then
                -- Delete male operation
                af_request("op_del", vlink.opid)
              else
                ac_objectclose()
                break
              end
            end
           ac_objectclose()
          end
        end
      end
    end   -- if

  end
  return bFoundGro
end


-- Returns: -1=Not known/no planks, 0=nope, 1=has
function Has()
  local res
  
  af_request("elem_getpoly")
  
  res=-1
  if RemoveGrooves(true, false) then
    res=1
  elseif RemoveGrooves(true, false) then
    res=1
  elseif gnPlanks>0 then
    res=0
  end

  return res
end


function Set(sSettings)
  local res, errStr, strOp

  gnPlankCount=0
  gtblCreate = {}
  gxmlOperations=nil

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return false
  end

  res=false
  if sSettings~=nil then
    res=pcall(ParseSettings, sSettings)
  end

  if not res then
    GetDefaults()
  end

  strOp=""
  strOp=DoGroXml(true)

  strOp=strOp .. DoGroXml(false)
  
  if strOp~="" then
    gxmlOperations= "<operations>" ..  strOp .. "</operations>"
  end

  af_request("elem_createplanks")
end


function Reset()
  local i, s, row, rows, mc, t, col, strOp

  gnPlankCount=0
  gtblCreate = {}
  gxmlOperations=nil

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return false
  end
  
  RemoveGrooves(true, true)
  RemoveGrooves(false, true)
  
  strOp=
  "<jointo target=\"vertical_y*|vertical_spacing|vertical_force\" operator=\"top*|2ndtop*|contourtilted\">\n" ..
  "<cut jointgap=\"0.000\" extendmaxlen=\"0.0\" expandopfind=\"0.0051\" endshape=\"angleddelfirst\"></cut>\n" ..
  "</jointo>\n"
    
  strOp=strOp ..
    "<jointo target=\"vertical_y*|vertical_spacing|vertical_force\" operator=\"bottom*|2ndbottom*\">\n" ..
    "<cut jointgap=\"0.000\" extendmaxlen=\"0.0\" expandopfind=\"0.0051\" endshape=\"angleddelfirst\"></cut>\n" ..
    "</jointo>\n"

  strOp=strOp ..
    "<jointo target=\"vertical_spacing\" operator=\"vertical_x\">\n" ..
    "<cut jointgap=\"0.000\" extendmaxlen=\"0.0\" expandopfind=\"0.0051\" endshape=\"angleddelfirst\"></cut>\n" ..
    "</jointo>\n"

  -- If there is angled joint in top piece and connecting to opening horizontal piece
  strOp=strOp ..
    "<jointo target=\"vertical_y\" operator=\"vertical_x\">\n" ..
    "<cut jointgap=\"0.000\" extendmaxlen=\"0.0\" expandopfind=\"0.0051\" endshape=\"angleddelfirst\" conntype=\"linex\" maxdisttoend=\"0.010\"></cut>\n" ..
    "</jointo>\n"

  strOp=strOp ..
    "<jointo target=\"vertical_x\" operator=\"vertical_y*|vertical_force\">\n" ..
    "<cut jointgap=\"0.000\" extendmaxlen=\"0.0\" expandopfind=\"0.0051\" endshape=\"angleddelfirst\" conntype=\"linex\" maxdisttoend=\"0.010\"></cut>\n" ..
    "</jointo>\n"

  if strOp~="" then
    gxmlOperations= "<operations>" ..  strOp .. "</operations>"
  end
  
  af_request("elem_createplanks")
  return 0
end


-------------------------
-- OPTIONS


-- Asks for the material to use
-- sSettings may be nil, otherwise mat=xxx\nthickness=x\nheight=x\ntopoff=x
-- Returns: true=ok, false=canceled
function RunSettingsDlg(sSettings)
  local  tblSettings, bRes, sErr, s, n, strSep, tblSorted
  local tblMat, i, id, v, thickness, height, mat

  tblSettings={}
  tblSettings[1]      ={}
  tblSettings[1].cfgonly  =0
  tblSettings[1].type    =3
  tblSettings[1].prompt  ="Grooves depth"
  tblSettings[1].key    ="grodepth"
  tblSettings[1].defvalue  =0.005

  tblSettings[2]      ={}
  tblSettings[2].cfgonly  =0
  tblSettings[2].type    =3
  tblSettings[2].prompt  ="Grooves oversize to each side"
  tblSettings[2].key    ="gro_over"
  tblSettings[2].defvalue  =0.001

  tblSettings[3]      ={}
  tblSettings[3].cfgonly  =0
  tblSettings[3].type    =2
  tblSettings[3].prompt  ="Grooves to top"
  tblSettings[3].key    ="gro_top"
  tblSettings[3].defvalue  =1

  tblSettings[4]      ={}
  tblSettings[4].cfgonly  =0
  tblSettings[4].type    =2
  tblSettings[4].prompt  ="Grooves to bottom"
  tblSettings[4].key    ="gro_bot"
  tblSettings[4].defvalue  =1

  tblSettings[5]      ={}
  tblSettings[5].cfgonly  =0
  tblSettings[5].type    =2
  tblSettings[5].prompt  ="Grooves to opening pieces"
  tblSettings[5].key    ="gro_opening"
  tblSettings[5].defvalue  =1

  if sSettings~=nil and sSettings~="" then
    local res, err
    res,err=pcall(ParseSettings, sSettings)
    if res then
      -- Had saved settings
      tblSettings[1].value=g_grodepth
      tblSettings[2].value=g_groover
      tblSettings[3].value=gnDoTop
      tblSettings[4].value=gnDoBot
      tblSettings[5].value=gnDoOpening
    else
      --ac_environment( "tolog", string.format("RunSettingsDlg/parse settings failed: %s", tostring(err)) )
    end
  end

  bRes,sErr=ac_optiondlg("LDMA", "Markings settings", tblSettings)
  if not bRes then
    return false
  end

  g_grodepth  =tblSettings[1].value
  g_groover   =tblSettings[2].value
  gnDoTop     =tblSettings[3].value
  gnDoBot     =tblSettings[4].value
  gnDoOpening =tblSettings[5].value
  return true
end



-- Gets value from key=value\n string
function GetVal(data, keyName)
  local k,v

  for k, v in string.gmatch(data, "([^ \r\n]+)=([^\r\n]+)") do
    --ac_environment("tolog", string.format("#%s=%s\n", k, v))
    if k == keyName then
      return v
    end
  end
  return nil
end


-- Called with pcall(), sets globals: g_mat, g_thickness, g_height
function ParseSettings(sSettings)
  local s
  
  GetDefaults()
  g_grodepth=tonumber(GetVal(sSettings, "grodepth"))
  
  -- Settings added later
  s=GetVal(sSettings, "groover")
  if s then
    g_groover=tonumber(s)
  end

  s=GetVal(sSettings, "grotop")
  if s then
    gnDoTop=tonumber(s)
  end
  
  s=GetVal(sSettings, "grobot")
  if s then
    gnDoBot=tonumber(s)
  end
  
  s=GetVal(sSettings, "groopening")
  if s then
    gnDoOpening=tonumber(s)
  end

  -- Will cause error if bad syntax
  s = string.format("%.4f %f %d %d %d", g_grodepth, g_groover, gnDoTop, gnDoBot, gnDoOpening)
end


function GetDefaults()
  g_grodepth=0.005
  g_groover=0.001
  gnDoTop=1
  gnDoBot=1
  gnDoOpening=1
  return true
end



-- Return: nil=canceled, ""=clear settings/use defaults, str=settings str
function Settings(sSettings)
  if sSettings==nil or sSettings=="" then
    if GetDefaults() then
      sSettings=string.format("grodepth=%.4f", g_grodepth)
    end
  end

  if RunSettingsDlg(sSettings)==false then
    return nil
  end

  sSettings=string.format("grodepth=%.4f\ngroover=%.4f\ngrotop=%d\ngrobot=%d\ngroopening=%d", g_grodepth, g_groover, gnDoTop, gnDoBot, gnDoOpening)
  return sSettings
end
]]>
        </script>


        <!-- Norwegian opening -->
        <script id="openingsides">
          <![CDATA[
-- Lua script, see ArchiFrame manual

-- For planks to be created
gnPlankCount=0
gtblCreate = {}


gOptGroupName="vertical_y_openingside"


function dump(o)
  if type(o) == 'table' then
    local s = '{ '
    for k,v in pairs(o) do
      if type(k) ~= 'number' then k = '"'..k..'"' end
      s = s .. '['..k..'] = ' .. dump(v) .. ','
    end
    return s .. '} '
  else
    return tostring(o)
  end
end


-- Asks for the material to use
-- sSettings may be nil, otherwise mat=xxx\nthickness=x\nheight=x\ntopoff=x
-- Returns three values: matid, thickness, height
function AskMat(sSettings)
	local	tblSettings, bRes, sErr, s, n, strSep, tblSorted
  local tblMat, i, id, v, thickness, height, mat
    
    
  tblMat=af_request("matlist")
  s=""
  strSep=""
    
  tblSorted={}
  for id,v in pairs(tblMat) do
    tblSorted[v.index]=v
  end

  for i,v in ipairs(tblSorted) do
    s=string.format("%s%s\"%s:%s (%s)\"", s, strSep, i, v.name, v.id)
    strSep=","
  end

	tblSettings={}
	tblSettings[1]			={}
	tblSettings[1].cfgonly	=0
	tblSettings[1].type		=1
	tblSettings[1].prompt	="Material"
	tblSettings[1].key		="balkmat"
	tblSettings[1].valuelist=s
	tblSettings[1].defvalue	=1

	tblSettings[2]			={}
	tblSettings[2].cfgonly	=0
	tblSettings[2].type		=3
	tblSettings[2].prompt	="Thickness if not fixed"
	tblSettings[2].key		="thickness"
	tblSettings[2].defvalue	=0.050

	tblSettings[3]			={}
	tblSettings[3].cfgonly	=0
	tblSettings[3].type		=3
	tblSettings[3].prompt	="Height if not fixed"
	tblSettings[3].key		="height"
	tblSettings[3].defvalue	=0.100

  if sSettings~=nil and sSettings~="" then
    local res, err
    res,err=pcall(ParseSettings, sSettings)
    if res then
      -- Had saved settings
      for i=1,#tblSorted do
        if tblSorted[i].id==g_mat.id then
          tblSettings[1].value=i
          break
        end
      end
      tblSettings[2].value=g_thickness
      tblSettings[3].value=g_height
    else
      ac_environment( "tolog", string.format("AskMat/parse settings failed: %s", tostring(err)) )
    end
  end

	bRes,sErr=ac_optiondlg("LDOS", "Side planks material", tblSettings)
	if not bRes then
    return
  end
    
  mat=tblSorted[tblSettings[1].value]
  thickness=mat.thickness
  height=mat.height
  if thickness==0.0 then
    thickness=tblSettings[2].value
  end
  if height==0.0 then
    height=tblSettings[3].value
  end

  return mat, thickness, height
end


-- Scans edges table and returns table of edges for given holeIndex (1...N)
-- Returns: nil=no such opening, tbl=1-based table of edges
function GetOpening(holeIndex)
  local i,v
  local tblRes, nres
  
  nres=0
  tblRes={}
  for i,v in ipairs(gtblEdges) do
    -- Process only contour line
    if v.holeindex==holeIndex then
      nres=nres+1
      tblRes[nres]=v
    end
  end
  
  if nres==0 then
    return nil
  end

  return tblRes
end


-- Forget bottom joining for now
function DoJoinTopBotXml(plankNum)
  local s

  s=string.format("<jointo target=\"#%d\" operator=\"top*|2ndtop*|contourtilted\"><cut jointgap=\"0.000\" endshape=\"angleddelfirst\" extendmaxlen=\"0.100\" removepart=\"up\"></cut></jointo>", plankNum)
  return s
end


-- Adds top balk(s) below the upper with group names:
-- nMatThickness, nMatHeight If generic "block", "round" etc type. nil if defined by strMatId
function DoOpeningSides( strMatId, nMatThickness, nMatHeight )
  local nOpening, tblOpening, edge, vEdge, tblEdit, dx, tblSides, nSides, i, v
  local plank, strXmlOp
  local tblLimitOpenings


  gnPlankCount=0
  gtblCreate = {}
  tblLimitOpenings = nil   -- If non-nil, contains true value for every opening index to be handled, for example opening 1: [1]=true
  
  if gAdjustElems then
    -- From options tool palette, may limit openings with selection. Check if selected planks related to any openig
    local tblSel, guid, tblSelGuids

    tblSel=af_request("getselplanks")
    if tblSel then
    
      tblSelGuids={}
      for i,v in pairs(tblSel) do
        tblSelGuids[v]=true
      end

      nOpening=1
      while true do
        tblOpening=GetOpening(nOpening)
        if tblOpening==nil then
          break
        end
        
        for edge,vEdge in ipairs(tblOpening) do
          if vEdge.ptr then
            ac_objectopen(vEdge.ptr)
            guid=ac_objectget("#guid")
            ac_objectclose()
            if tblSelGuids[guid]~=nil then
              if tblLimitOpenings==nil then
                tblLimitOpenings={}
              end
          
              tblLimitOpenings[nOpening]=true
            end
          end
        end
        
        nOpening=nOpening+1
      end
    end
  end

  nOpening=1
  strXmlOp=""
  while true do
    tblOpening=GetOpening(nOpening)
    if tblOpening==nil then
      break
    end
    nOpening=nOpening+1

    if #tblOpening==4 and (tblLimitOpenings==nil or tblLimitOpenings[nOpening-1]) then 
      -- Find vertical pieces (openings are ccw as the main contour)
      nSides=0
      tblSides={}
      for edge,vEdge in ipairs(tblOpening) do
        if math.abs(vEdge.x2-vEdge.x1)<0.001 then
          -- Vertical, inside element is at the right hand side
          if vEdge.ptr then
            dx=nMatThickness
            if vEdge.y1>vEdge.y2 then
              dx=-dx
            end
            
            nSides=nSides+1
            tblSides[nSides]={}
            tblSides[nSides].edge=vEdge
            tblSides[nSides].dx=dx

            tblEdit={}
            tblEdit.guid=vEdge.ptr
          
  --ac_environment("tolog", dump(vEdge))

            ac_objectopen(tblEdit.guid)
            tblEdit.elemdata=ac_objectget("#af_elemdata")
            ac_objectclose()
          
            tblEdit.elemdata.x1=tblEdit.elemdata.x1+dx
            tblEdit.elemdata.x2=tblEdit.elemdata.x2+dx

            af_request("editplank", tblEdit)
            strXmlOp=strXmlOp .. DoJoinTopBotXml(tblEdit.elemdata.index)

            plank={}
            plank.guidsettings=tblEdit.guid
            plank.group=gOptGroupName
            plank.id=strMatId
            plank.thickness=nMatThickness
            plank.height=nMatHeight

            plank.x1=vEdge.x1+dx*0.5
            plank.y1=vEdge.y1
            plank.x2=plank.x1
            plank.y2=vEdge.y2
            --plank.extendtoelem=1
            gnPlankCount=gnPlankCount+1
            gtblCreate[gnPlankCount]=plank

          end
        end
      end   -- for edge,vEdge

      for edge,vEdge in ipairs(tblOpening) do
        if math.abs(vEdge.y2-vEdge.y1)<0.001 then
          -- Horizontal
          if vEdge.ptr then

            tblEdit={}
            tblEdit.guid=vEdge.ptr
          
            ac_objectopen(tblEdit.guid)
            tblEdit.elemdata=ac_objectget("#af_elemdata")
            ac_objectclose()
            
            for i,v in ipairs(tblSides) do
              if math.abs(v.edge.x1-tblEdit.elemdata.x1)<0.001 then
                tblEdit.elemdata.x1=tblEdit.elemdata.x1+v.dx
              elseif math.abs(v.edge.x1-tblEdit.elemdata.x2)<0.001 then
                tblEdit.elemdata.x2=tblEdit.elemdata.x2+v.dx
              end
            end

            af_request("editplank", tblEdit)
          end
        end
      end   -- for edge,vEdge
    end

  end
  
  if strXmlOp~="" then
    gxmlOperations=string.format("<operations>\n%s</operations>", strXmlOp)
  end
  
end


-------------------------
-- FOR OPTION DLG


-- Gets value from key=value\n string
function GetVal(data, keyName)
  local k,v

	for k, v in string.gmatch(data, "([^ \r\n]+)=([^\r\n]+)") do
    --ac_environment("tolog", string.format("#%s=%s\n", k, v))
		if k == keyName then
			return v
		end
	end
  return nil
end


-- Called with pcall(), sets globals: g_mat, g_thickness, g_height
function ParseSettings(sSettings)
  local s, mat, val
  
  --ac_environment("tolog", string.format("sSettings=%s\n", sSettings) )

  mat=GetVal(sSettings, "mat")
  g_mat=af_request("singlemat", mat)
  g_thickness=g_mat.thickness
  g_height=g_mat.height
  if g_thickness==0.0 then
    g_thickness=tonumber(GetVal(sSettings, "thickness"))
  end
  if g_height==0.0 then
    g_height=tonumber(GetVal(sSettings, "height"))
  end

  -- Will cause error if bad syntax
  s = string.format("%s, thickness=%f, height=%f", g_mat.id, g_thickness, g_height)
end


-- Finds nice material
function GetDefaults()
  local mat, tblMat, i, secondWidth, tblInfo, s
  
  mat=af_request("elem_getstudmat")
  if mat==nil then
    return false
  end

  tblMat=af_request("singlemat", mat)
  if tblMat==nil then
    return false
  end

  g_thickness=0.022     -- 22 mm by default
  g_height=tblMat.height -- Studding height here
  
  g_mat=af_request("singlemat", "block")
  return true
end


-- Returns: -1=Not known/no planks, 0=nope, 1=has
function Has()
  local i

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return -1
  end
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    s=ac_objectget("iElemGroup")
    if string.match(s, "^" .. gOptGroupName .. ".*") then
      ac_objectclose()
      return 1
    end
    ac_objectclose()
  end
  return 0
end


-- Return: nil=canceled, ""=clear settings/use defaults, str=settings str
function Settings(sSettings)
  if sSettings==nil or sSettings=="" then
    if GetDefaults() then
      sSettings=string.format("mat=%s\nthickness=%f\nheight=%f", g_mat.id, g_thickness, g_height)
    end
  end
  -- Ask material
  local mat, thickness, height, topOff, numPlanks
  mat, thickness, height = AskMat(sSettings)
  if mat==nil then
    return nil
  end

  s=string.format("mat=%s\nthickness=%f\nheight=%f", mat.id, thickness, height)
  return s
end


function Set(sSettings)
  local default, res, errStr, zoff, tblLastAdded, i, v, s, overL, overR, thickness
  
  gnPlankCount=0
  gtblCreate = {}

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return
  end

  default=true
  if sSettings~=nil then
    res, errStr=pcall(ParseSettings, sSettings)
    if res then
      default=false
    end
  end

  if default then
    -- Default settings
    GetDefaults()
  end
  
  if g_mat.thickness>0 then
    g_thickness=g_mat.thickness
  end

  if g_mat.height>0 then
    g_height=g_mat.height
  end

  DoOpeningSides( g_mat.id, g_thickness, g_height )
  
  af_request("elem_createplanks")
end


function Reset()
  local i, elemDel, infoDel, elemNow, infoNow, nOpening, tblOpening, vEdgeOpening, edgeDir, y, y1, y2, e, v, x, tblEdit
  local strXmlOp

  gnPlankCount=0
  gtblCreate = {}

  res=false
  strXmlOp=""
  af_request("elem_getpoly")
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    s=ac_objectget("iElemGroup")
    if string.match(s, "^" .. gOptGroupName .. ".*") then
      elemDel=ac_objectget("#af_elemdata")
      infoDel=af_request("plankinfo")
      af_request("delplank")
      ac_objectclose()

      -- Find opening edge related to this piece
      y1=elemDel.y1
      y2=elemDel.y2
      if y1>y2 then
        y1,y2=y2,y1
      end

      nOpening=1
      while true do
        tblOpening=GetOpening(nOpening)
        if tblOpening==nil then
          break
        end
        nOpening=nOpening+1
        for e,v in ipairs(tblOpening) do
          y=(v.y1+v.y2)*0.5
          if math.abs(v.x1-v.x2)<0.001 and y1<y and y2>y then
            vEdgeOpening=nil
            if math.abs(v.x1-elemDel.x1-infoDel.width*0.5)<0.001 then
              -- On left side
              vEdgeOpening=v
              x=elemDel.x1-infoDel.width*0.5
              edgeDir=-1
            elseif math.abs(elemDel.x1-v.x2-infoDel.width*0.5)<0.001 then
              -- On right side
              vEdgeOpening=v
              edgeDir=1
              x=elemDel.x1+infoDel.width*0.5
            end

            if vEdgeOpening~=nil then
              -- Find stud next to plank to be deleted. x set to the edge of deleted plank next to stud. Also process opening top & bottom
              for e=1,gnPlanks do
                ac_objectopen(string.format("#%d",e))
                elemNow=ac_objectget("#af_elemdata")
                infoNow=af_request("plankinfo")
                ac_objectclose()
                
--ac_environment("tolog", string.format("x=%f elemNow=%s", x,dump(elemNow)))

                if elemNow.y1<y2 and elemNow.y2>y1 and math.abs(elemNow.x1-elemNow.x2)<0.001 and math.abs(elemNow.x1-edgeDir*infoNow.width*0.5-x)<0.001 then
                  -- Affected stud found, move
                  tblEdit={}
                  tblEdit.guid=infoNow.ptr
                  tblEdit.elemdata=elemNow
                  tblEdit.elemdata.x1=tblEdit.elemdata.x1-edgeDir*infoDel.width
                  tblEdit.elemdata.x2=tblEdit.elemdata.x1
                  af_request("editplank", tblEdit)
                  strXmlOp=strXmlOp .. DoJoinTopBotXml(tblEdit.elemdata.index)
                end
                
                if math.abs(elemNow.y2-elemNow.y1)<0.001 and (math.abs(elemNow.y1+infoNow.width*0.5-y1)<0.001 or math.abs(elemNow.y1-infoNow.width*0.5-y2)<0.001) then
                  -- Y-coordinate matches, check if left or right
                  if math.abs(x-elemNow.x1)<0.001 then
                    tblEdit={}
                    tblEdit.guid=infoNow.ptr
                    tblEdit.elemdata=elemNow
                    tblEdit.elemdata.x1=tblEdit.elemdata.x1-edgeDir*infoDel.width
                    af_request("editplank", tblEdit)
                  elseif math.abs(x-elemNow.x2)<0.001 then
                    tblEdit={}
                    tblEdit.guid=infoNow.ptr
                    tblEdit.elemdata=elemNow
                    tblEdit.elemdata.x2=tblEdit.elemdata.x2-edgeDir*infoDel.width
                    af_request("editplank", tblEdit)
                  end
                end
              end
            end
          end
        end
      end

      res=true
    end
    ac_objectclose()
  end
  
  if strXmlOp~="" then
    gxmlOperations=string.format("<operations>\n%s</operations>", strXmlOp)
    af_request("elem_createplanks")   -- Will process operations
  end

  return res
end


function GetName(sSettings, baseName)
  if sSettings~=nil then
    res, errStr=pcall(ParseSettings, sSettings)
    if res then
      if g_mat.thickness~=0 then
        baseName=string.format("%s %s", baseName, g_mat.id)
      else
        baseName=string.format("%s %sx%s", baseName, ac_environment("ntos", g_thickness, "length", "work"), ac_environment("ntos", g_height, "length", "work"))
      end
    end
  end
  return baseName
end

-- FOR OPTION DLG
-------------------------


]]>
        </script>

        <!-- Double studs for opening sides -->
        <script id="openingdouble">
          <![CDATA[
-- Lua script, see ArchiFrame manual

-- For planks to be created
gnPlankCount=0
gtblCreate = {}


gOptGroupName="vertical_y_openingdouble"


function dump(o)
  if type(o) == 'table' then
    local s = '{ '
    for k,v in pairs(o) do
      if type(k) ~= 'number' then k = '"'..k..'"' end
      s = s .. '['..k..'] = ' .. dump(v) .. ','
    end
    return s .. '} '
  else
    return tostring(o)
  end
end


-- Asks for the material to use
-- sSettings may be nil, otherwise width=x
-- Returns single val: minumum width
function SettingsDlg(sSettings)
	local	tblSettings, bRes, sErr, s, n, strSep, tblSorted
  local tblMat, i, id, v, thickness, height, mat
    
    

	tblSettings={}

	tblSettings[1]			={}
	tblSettings[1].cfgonly	=0
	tblSettings[1].type		=3
	tblSettings[1].prompt	="Minimum width to add double stud"
	tblSettings[1].key		="width"
	tblSettings[1].defvalue	=0.600

  if sSettings~=nil and sSettings~="" then
    local res, err
    res,err=pcall(ParseSettings, sSettings)
    if res then
      -- Had saved settings
      tblSettings[1].value=g_width
    else
      ac_environment( "tolog", string.format("AskMat/parse settings failed: %s", tostring(err)) )
    end
  end

	bRes,sErr=ac_optiondlg("LDDS", "Double stud settings", tblSettings)
	if not bRes then
    return
  end
    
  return tblSettings[1].value
end


-- Scans edges table and returns table of edges for given holeIndex (1...N)
-- Returns: nil=no such opening, tbl=1-based table of edges
function GetOpening(holeIndex)
  local i,v
  local tblRes, nres
  
  nres=0
  tblRes={}
  for i,v in ipairs(gtblEdges) do
    -- Process only contour line
    if v.holeindex==holeIndex then
      nres=nres+1
      tblRes[nres]=v
    end
  end
  
  if nres==0 then
    return nil
  end

  return tblRes
end


-- Forget bottom joining for now
function DoJoinTopBotXml(plankNum)
  local s

  s=string.format("<jointo target=\"#%d\" operator=\"top*|2ndtop*|bottom*|2ndbottom*|contourtilted\"><cut jointgap=\"0.000\" endshape=\"angleddelfirst\" extendmaxlen=\"0.100\"></cut></jointo>", plankNum)
  return s
end


function DoDoubleStud( strMatId, nMatThickness, nMatHeight )
  local nOpening, tblOpening, edge, vEdge, tblEdit, dx, tblSides, nSides, i, v, elemdata
  local plank, strXmlOp
  local tblLimitOpenings


  gnPlankCount=0
  gtblCreate = {}
  tblLimitOpenings = nil   -- If non-nil, contains true value for every opening index to be handled, for example opening 1: [1]=true
  
  if gAdjustElems then
    -- From options tool palette, may limit openings with selection. Check if selected planks related to any openig
    local tblSel, guid, tblSelGuids

    tblSel=af_request("getselplanks")
    if tblSel then
    
      tblSelGuids={}
      for i,v in pairs(tblSel) do
        tblSelGuids[v]=true
      end

      nOpening=1
      while true do
        tblOpening=GetOpening(nOpening)
        if tblOpening==nil then
          break
        end
        
        for edge,vEdge in ipairs(tblOpening) do
          ac_objectopen(vEdge.ptr)
          guid=ac_objectget("#guid")
          ac_objectclose()
          if tblSelGuids[guid]~=nil then
            if tblLimitOpenings==nil then
              tblLimitOpenings={}
            end
          
            tblLimitOpenings[nOpening]=true
          end
        end
        
        nOpening=nOpening+1
      end
    end
  end
  
  nOpening=1
  strXmlOp=""
  while true do
    tblOpening=GetOpening(nOpening)
    if tblOpening==nil then
      break
    end
    nOpening=nOpening+1

    if #tblOpening==4 and (tblLimitOpenings==nil or tblLimitOpenings[nOpening-1]) then 
      -- Find vertical pieces (openings are ccw as the main contour)
      local x1, x2
      nSides=0
      tblSides={}
      
      
      x1=1E100
      x2=-1E100
      for edge,vEdge in ipairs(tblOpening) do
        if vEdge.x1<x1 then
          x1=vEdge.x1
        end
        if vEdge.x2<x1 then
          x1=vEdge.x2
        end
        if vEdge.x1>x2 then
          x2=vEdge.x1
        end
        if vEdge.x2>x2 then
          x2=vEdge.x2
        end
      end

      if x2-x1+0.0001>g_width then
        for edge,vEdge in ipairs(tblOpening) do
          if math.abs(vEdge.x2-vEdge.x1)<0.001 then
            -- Vertical, inside element is at the right hand side
            if vEdge.ptr then
              dx=nMatThickness
              if vEdge.y1>vEdge.y2 then
                dx=-dx
              end
            
              nSides=nSides+1
              tblSides[nSides]={}
              tblSides[nSides].edge=vEdge
              tblSides[nSides].dx=dx

              ac_objectopen(vEdge.ptr)
              elemdata=ac_objectget("#af_elemdata")
              ac_objectclose()
          
              strXmlOp=strXmlOp .. DoJoinTopBotXml(gnPlanks+gnPlankCount+1)

              plank={}
              plank.guidsettings=vEdge.ptr
              plank.copyops=1
              plank.group=gOptGroupName
              plank.id=strMatId
              plank.thickness=nMatThickness
              plank.height=nMatHeight

              plank.x1=elemdata.x1+dx
              plank.y1=elemdata.y1
              plank.x2=plank.x1
              plank.y2=elemdata.y2
              plank.extendtoelem=1
              gnPlankCount=gnPlankCount+1
              gtblCreate[gnPlankCount]=plank
  --ac_environment("tolog", string.format("UUS, dx=%f, %s", dx, dump(gtblCreate[gnPlankCount])))
            end
          end
        end   -- for edge,vEdge
      end
    end

  end
  
  if strXmlOp~="" then
    gxmlOperations=string.format("<operations>\n%s</operations>", strXmlOp)
  end
  
end


-------------------------
-- FOR OPTION DLG


-- Gets value from key=value\n string
function GetVal(data, keyName)
  local k,v

	for k, v in string.gmatch(data, "([^ \r\n]+)=([^\r\n]+)") do
    --ac_environment("tolog", string.format("#%s=%s\n", k, v))
		if k == keyName then
			return v
		end
	end
  return nil
end


-- Called with pcall(), sets globals: g_mat, g_thickness, g_height
function ParseSettings(sSettings)
  local s, mat, val
  
  --ac_environment("tolog", string.format("sSettings=%s\n", sSettings) )

  g_width=tonumber(GetVal(sSettings, "width"))

  -- Will cause error if bad syntax
  s = string.format("width=%f", g_width)
end


-- Finds nice material
function GetDefaults()
  g_width=0.600
  return true
end


-- Returns: -1=Not known/no planks, 0=nope, 1=has
function Has()
  local i

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return -1
  end
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    s=ac_objectget("iElemGroup")
    if string.match(s, "^" .. gOptGroupName .. ".*") then
      ac_objectclose()
      return 1
    end
    ac_objectclose()
  end
  return 0
end


-- Return: nil=canceled, ""=clear settings/use defaults, str=settings str
function Settings(sSettings)
  if sSettings==nil or sSettings=="" then
    if GetDefaults() then
      sSettings=string.format("width=%f", g_width)
    end
  end
  -- Ask material
  local width
  width = SettingsDlg(sSettings)
  if width==nil then
    return nil
  end

  s=string.format("width=%f", width)
  return s
end


function Set(sSettings)
  local default, res, errStr, matid, tblMat, thickness, height
  
  gnPlankCount=0
  gtblCreate = {}

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return
  end

  default=true
  if sSettings~=nil then
    res, errStr=pcall(ParseSettings, sSettings)
    if res then
      default=false
    end
  end

  if default then
    -- Default settings
    GetDefaults()
  end

  matid=af_request("elem_getstudmat")
  if matid==nil then
    return
  end

  tblMat=af_request("singlemat", matid)
  if tblMat==nil then
    return
  end

  thickness=tblMat.thickness
  height=tblMat.height

  DoDoubleStud( matid, thickness, height )
  
  af_request("elem_createplanks")
end


function Reset()
  local i, elemDel, infoDel, elemNow, infoNow, nOpening, tblOpening, vEdgeOpening, edgeDir, y, y1, y2, e, v, x, tblEdit

  gnPlankCount=0
  gtblCreate = {}

  res=false
  af_request("elem_getpoly")
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    s=ac_objectget("iElemGroup")
    if string.match(s, "^" .. gOptGroupName .. ".*") then
      elemDel=ac_objectget("#af_elemdata")
      infoDel=af_request("plankinfo")
      af_request("delplank")
      ac_objectclose()
      res=true
    end
    ac_objectclose()
  end
  
  return res
end


function GetName(sSettings, baseName)
  if sSettings~=nil then
    res, errStr=pcall(ParseSettings, sSettings)
    if res then
      baseName=string.format("%s >=%s", baseName, ac_environment("ntos", g_width, "length", "work"))
    end
  end
  return baseName
end

-- FOR OPTION DLG
-------------------------


]]>
        </script>


        <!-- Double studs for opening sides -->
        <script id="cornerdouble">
          <![CDATA[
-- Lua script, see ArchiFrame manual

-- For planks to be created
gnPlankCount=0
gtblCreate = {}


gOptGroupName="vertical_y_cornerdouble"


function dump(o)
  if type(o) == 'table' then
    local s = '{ '
    for k,v in pairs(o) do
      if type(k) ~= 'number' then k = '"'..k..'"' end
      s = s .. '['..k..'] = ' .. dump(v) .. ','
    end
    return s .. '} '
  else
    return tostring(o)
  end
end


-- Forget bottom joining for now
function DoJoinTopBotXml(plankNum)
  local s

  s=     string.format("<jointo target=\"#%d\" operator=\"top*|2ndtop*|contourtilted\"><cut jointgap=\"0.000\" endshape=\"angleddelfirst\" extendmaxlen=\"0.1\" removepart=\"up\"></cut></jointo>", plankNum)
  s=s .. string.format("<jointo target=\"#%d\" operator=\"bottom*|2ndbottom*|contourtilted\"><cut jointgap=\"0.000\" endshape=\"angleddelfirst\" extendmaxlen=\"0.1\" removepart=\"down\"></cut></jointo>", plankNum)
  return s
end


function DoDoubleStud( strMatId, nMatThickness, nMatHeight )
  local vEdge, dx, tblSides, nSides, i, v, elemdata, x1, x2, ptr1, ptr2
  local plank, strXmlOp
  local tblLimitOpenings


  gnPlankCount=0
  gtblCreate = {}
  tblLimitOpenings = nil   -- If non-nil, contains true value for every opening index to be handled, for example opening 1: [1]=true
  
  x1=1E100
  x2=-x1
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    plank=af_request("plankinfo")
    elemdata=ac_objectget("#af_elemdata")
    if math.abs(elemdata.x2-elemdata.x1)<0.001 then
      if elemdata.x1<x1 then
        x1=elemdata.x1
        plank1=plank
        plank1.elemdata=elemdata
      end
      if elemdata.x1>x2 then
        x2=elemdata.x1
        plank2=plank
        plank2.elemdata=elemdata
      end
    end
    ac_objectclose()
  end

  strXmlOp=""
  if plank1 then
    strXmlOp=strXmlOp .. DoJoinTopBotXml(gnPlanks+gnPlankCount+1)

    plank={}
    plank.guidsettings=plank1.ptr
    plank.copyops=1
    plank.group=gOptGroupName
    --plank.id=strMatId
    --plank.thickness=nMatThickness
    --plank.height=nMatHeight

    plank.x1=plank1.elemdata.x1+plank1.width
    plank.y1=plank1.elemdata.y1
    plank.x2=plank.x1
    plank.y2=plank1.elemdata.y2
    plank.extendtoelem=1
    gnPlankCount=gnPlankCount+1
    gtblCreate[gnPlankCount]=plank
  end

  if plank2 then
    strXmlOp=strXmlOp .. DoJoinTopBotXml(gnPlanks+gnPlankCount+1)

    plank={}
    plank.guidsettings=plank2.ptr
    plank.copyops=1
    plank.group=gOptGroupName
    --plank.id=strMatId
    --plank.thickness=nMatThickness
    --plank.height=nMatHeight

    plank.x1=plank2.elemdata.x1-plank2.width
    plank.y1=plank2.elemdata.y1
    plank.x2=plank.x1
    plank.y2=plank2.elemdata.y2
    plank.extendtoelem=1
    gnPlankCount=gnPlankCount+1
    gtblCreate[gnPlankCount]=plank
  end

  if strXmlOp~="" then
    gxmlOperations=string.format("<operations>\n%s</operations>", strXmlOp)
  end
  
end


-------------------------
-- FOR OPTION DLG


-- Gets value from key=value\n string
function GetVal(data, keyName)
  local k,v

	for k, v in string.gmatch(data, "([^ \r\n]+)=([^\r\n]+)") do
    --ac_environment("tolog", string.format("#%s=%s\n", k, v))
		if k == keyName then
			return v
		end
	end
  return nil
end


-- Called with pcall(), sets globals: g_mat, g_thickness, g_height
function ParseSettings(sSettings)
  local s, mat, val
  
  --ac_environment("tolog", string.format("sSettings=%s\n", sSettings) )

  g_width=tonumber(GetVal(sSettings, "width"))

  -- Will cause error if bad syntax
  s = string.format("width=%f", g_width)
end


-- Finds nice material
function GetDefaults()
  g_width=0.600
  return true
end


-- Returns: -1=Not known/no planks, 0=nope, 1=has
function Has()
  local i

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return -1
  end
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    s=ac_objectget("iElemGroup")
    if string.match(s, "^" .. gOptGroupName .. ".*") then
      ac_objectclose()
      return 1
    end
    ac_objectclose()
  end
  return 0
end


function Set(sSettings)
  local default, res, errStr, matid, tblMat, thickness, height
  
  gnPlankCount=0
  gtblCreate = {}

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return
  end

  default=true
  if sSettings~=nil then
    res, errStr=pcall(ParseSettings, sSettings)
    if res then
      default=false
    end
  end

  if default then
    -- Default settings
    GetDefaults()
  end

  matid=af_request("elem_getstudmat")
  if matid==nil then
    return
  end

  tblMat=af_request("singlemat", matid)
  if tblMat==nil then
    return
  end

  thickness=tblMat.thickness
  height=tblMat.height

  DoDoubleStud( matid, thickness, height )
  
  af_request("elem_createplanks")
end


function Reset()
  local i, elemDel, infoDel, elemNow, infoNow, nOpening, tblOpening, vEdgeOpening, edgeDir, y, y1, y2, e, v, x, tblEdit

  gnPlankCount=0
  gtblCreate = {}

  res=false
  af_request("elem_getpoly")
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    s=ac_objectget("iElemGroup")
    if string.match(s, "^" .. gOptGroupName .. ".*") then
      elemDel=ac_objectget("#af_elemdata")
      infoDel=af_request("plankinfo")
      af_request("delplank")
      ac_objectclose()
      res=true
    end
    ac_objectclose()
  end
  
  return res
end


-- FOR OPTION DLG
-------------------------

]]>
        </script>


        <script id="reinforceall">
          <![CDATA[
g_matid=nil           -- Element material as default "23x98"
g_issingle=false      -- Set to true if actually option Bottom balk in/out, will affect processing following also
g_topin=1
g_topout=1
g_botin=1
g_botout=1

g_topinname="reinforce_small_topin"
g_topoutname="reinforce_small_topout"
g_botinname="reinforce_small_bottomin"
g_botoutname="reinforce_small_bottomout"


-- Returns: -1=Not known/no planks, 0=nope, 1=has
function Has()
  local b
  
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    s=ac_objectget("iElemGroup")
    ac_objectclose()
    
    b=false
    if g_issingle then
      if g_botin==1 and s==g_botinname then
        b=true
      end
      if g_botout==1 and s==g_botoutname then
        b=true
      end
    else
      b=string.match(s, "^reinforce_small.*")
    end

    if b then
      return 1
    end
  end
  return 0
end


function Set(sSettings)
  local res, errStr

  gxmlOperations=nil
  gnPlankCount=0
  gtblCreate = {}

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return false
  end

  res=false
  if sSettings~=nil then
    res=pcall(ParseSettings, sSettings)
  end

  if not res then
    GetDefaults()
  end

  if g_topin==1 then
    DoReinforce(true, "top_force", "2ndtop_force", "contourtilted", g_matid, false, g_topinname)
  end
  if g_topout==1 then
    DoReinforce(true, "top_force", "2ndtop_force", "contourtilted", g_matid, true, g_topoutname)
  end
  if g_botin==1 then
    DoReinforce(false, "bottom_force", "2ndbottom_force", nil, g_matid, false, g_botinname)
  end
  if g_botout==1 then
    DoReinforce(false, "bottom_force", "2ndbottom_force", nil, g_matid, true, g_botoutname)
  end
  af_request("elem_createplanks")
end


function Reset()
  local i, s

  gnPlankCount=0
  gtblCreate = {}

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return false
  end
  
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    s=ac_objectget("iElemGroup")
    if g_issingle then
      if g_botin==1 and s==g_botinname then
        af_request("delplank")
      end
      if g_botout==1 and s==g_botoutname then
        af_request("delplank")
      end
    else
      if string.match(s, "^reinforce_small.*") then
        af_request("delplank")
      end
    end
    ac_objectclose()
  end
  return 0
end


-------------------------
-- OPTIONS


-- Asks for the material to use
-- sSettings may be nil, otherwise mat=xxx\nthickness=x\nheight=x\ntopoff=x
function AskMat(sSettings)
  local  tblSettings, bRes, sErr, s, n, strSep, tblSorted
  local tblMat, i, id, v, thickness, height, mat
    
    
  tblMat=af_request("matlist")
  s=""
  strSep=""
    
  -- Skip general materials
  tblSorted={}
  i=1
  for id,v in pairs(tblMat) do
    if v.thickness>0.001 then
  		tblSorted[i]=v
	  	i=i+1
	  end
  end

	table.sort(tblSorted, function (n1, n2)
    return n1.index < n2.index
	end)

  for i,v in ipairs(tblSorted) do
    s=string.format("%s%s\"%s:%s (%s)\"", s, strSep, i, v.name, v.id)
    strSep=","
  end
  
  tblSettings={}
  tblSettings[1]      ={}
  tblSettings[1].cfgonly  =0
  tblSettings[1].type    =1
  tblSettings[1].prompt  ="Material"
  tblSettings[1].key    ="balkmat"
  tblSettings[1].valuelist=s
  tblSettings[1].defvalue  =1

    tblSettings[2]      ={}
    tblSettings[2].cfgonly  =0
  tblSettings[2].type		=3
  tblSettings[2].prompt	="Distance from stud end"
  tblSettings[2].key		="distend"
  tblSettings[2].defvalue	=g_reinforceDist

    tblSettings[3]      ={}
    tblSettings[3].cfgonly  =0
  tblSettings[3].type		=3
  tblSettings[3].prompt	="Oversize towards stud end"
  tblSettings[3].key		="overout"
  tblSettings[3].defvalue	=g_reinforceOverEnd
  
    tblSettings[4]      ={}
    tblSettings[4].cfgonly  =0
  tblSettings[4].type		=3
  tblSettings[4].prompt	="Oversize towards stud in"
  tblSettings[4].key		="overin"
  tblSettings[4].defvalue	=g_reinforceOverIn

    tblSettings[5]      ={}
    tblSettings[5].cfgonly  =0
  tblSettings[5].type		=3
  tblSettings[5].prompt	="Oversize sides"
  tblSettings[5].key		="overside"
  tblSettings[5].defvalue	=g_reinforceOverSide

  if g_issingle==false then
    tblSettings[6]      ={}
    tblSettings[6].cfgonly  =0
    tblSettings[6].type    =2
    tblSettings[6].prompt  ="Top back"
    tblSettings[6].key    ="topin"
    tblSettings[6].defvalue  =1

    tblSettings[7]      ={}
    tblSettings[7].cfgonly  =0
    tblSettings[7].type    =2
    tblSettings[7].prompt  ="Top front"
    tblSettings[7].key    ="topout"
    tblSettings[7].defvalue  =1
  
    tblSettings[8]      ={}
    tblSettings[8].cfgonly  =0
    tblSettings[8].type    =2
    tblSettings[8].prompt  ="Bottom back"
    tblSettings[8].key    ="botin"
    tblSettings[8].defvalue  =1

    tblSettings[9]      ={}
    tblSettings[9].cfgonly  =0
    tblSettings[9].type    =2
    tblSettings[9].prompt  ="Bottom front"
    tblSettings[9].key    ="botout"
    tblSettings[9].defvalue  =1
  end

  if sSettings~=nil and sSettings~="" then
    local res, err
    res,err=pcall(ParseSettings, sSettings)
    if res then
      -- Had saved settings
      for i=1,#tblSorted do
        if tblSorted[i].id==g_matid then
          tblSettings[1].value=i
          break
        end
      end
      
      tblSettings[2].value=g_reinforceDist
      tblSettings[3].value=g_reinforceOverEnd
      tblSettings[4].value=g_reinforceOverIn
      tblSettings[5].value=g_reinforceOverSide
      
      if g_issingle==false then
        tblSettings[6].value=g_topin
        tblSettings[7].value=g_topout
        tblSettings[8].value=g_botin
        tblSettings[9].value=g_botout
      end
    else
      ac_environment( "tolog", string.format("AskMat/parse settings failed: %s", tostring(err)) )
    end
  end

  bRes,sErr=ac_optiondlg("LDRA", "Reinforce ALL", tblSettings)
  if not bRes then
    return
  end
    
  -- New settings as globals
  g_reinforceDist=tblSettings[2].value
  g_reinforceOverEnd=tblSettings[3].value
  g_reinforceOverIn=tblSettings[4].value
  g_reinforceOverSide=tblSettings[5].value

  mat=tblSorted[tblSettings[1].value]
  if g_issingle==false then
    return mat.id, tblSettings[6].value, tblSettings[7].value, tblSettings[8].value, tblSettings[9].value
  end

  return mat.id   -- Just single value if bottom balk in/out
end


-- Gets value from key=value\n string
function GetVal(data, keyName)
  local k,v

  for k, v in string.gmatch(data, "([^ \r\n]+)=([^\r\n]+)") do
    --ac_environment("tolog", string.format("#%s=%s\n", k, v))
    if k == keyName then
      return v
    end
  end
  return nil
end


-- Called with pcall(), sets globals: g_mat, g_thickness, g_height and g_reinforceXxx
function ParseSettings(sSettings)
  local s, mat, val
  
  g_matid=GetVal(sSettings, "mat")
  if g_matid==nil then
    g_matid=""
  end
  if g_issingle==false then
    g_topin=tonumber(GetVal(sSettings, "topin"))
    g_topout=tonumber(GetVal(sSettings, "topout"))
    g_botin=tonumber(GetVal(sSettings, "botin"))
    g_botout=tonumber(GetVal(sSettings, "botout"))
  end

  -- These are new values - allow nil values
  val=GetVal(sSettings, "dist")
  if val then
    g_reinforceDist=tonumber(val)
  end

  val=GetVal(sSettings, "overend")
  if val then
    g_reinforceOverEnd=tonumber(val)
  end

  val=GetVal(sSettings, "overin")
  if val then
    g_reinforceOverIn=tonumber(val)
  end

  val=GetVal(sSettings, "overside")
  if val then
    g_reinforceOverSide=tonumber(val)
  end

  -- Will cause error if bad syntax
  s=string.format("mat=%s\ntopin=%d\ntopout=%d\nbotin=%d\nbotout=%d\ndist=%.6f\noverend=%.6f\noverin=%.6f\noverside=%.6f", g_matid, g_topin, g_topout, g_botin, g_botout, g_reinforceDist, g_reinforceOverEnd, g_reinforceOverIn, g_reinforceOverSide)
end


-- Finds nice material
function GetDefaults()
  g_matid=af_request("elem_getstudmat")
  if g_matid==nil then
    g_matid=""
  end
  if g_issingle==false then
    g_topin=1
    g_topout=1
    g_botin=1
    g_botout=1
  end

  g_reinforceOverEnd=0.010
  g_reinforceOverIn=0.002
  g_reinforceOverSide=0.001
  g_reinforceDist=0

  return true
end



-- Return: nil=canceled, ""=clear settings/use defaults, str=settings str
function Settings(sSettings)
  if sSettings==nil or sSettings=="" then
    if GetDefaults() then
      sSettings=string.format("mat=%s\ntopin=%d\ntopout=%d\nbotin=%d\nbotout=%d\ndist=%.6f\noverend=%.6f\noverin=%.6f\noverside=%.6f", g_matid, g_topin, g_topout, g_botin, g_botout, g_reinforceDist, g_reinforceOverEnd, g_reinforceOverIn, g_reinforceOverSide)
    end
  end
  -- Ask material
  local mat, thickness, height, topOff, numPlanks
  if g_issingle==false then
    g_matid, g_topin, g_topout, g_botin, g_botout= AskMat(sSettings)
  else
    g_matid= AskMat(sSettings)
  end

  if g_matid==nil then
    return nil
  end

  s=string.format("mat=%s\ntopin=%d\ntopout=%d\nbotin=%d\nbotout=%d\ndist=%.6f\noverend=%.6f\noverin=%.6f\noverside=%.6f", g_matid, g_topin, g_topout, g_botin, g_botout, g_reinforceDist, g_reinforceOverEnd, g_reinforceOverIn, g_reinforceOverSide)
  return s
end


function GetName(sSettings, baseName)
  if sSettings~=nil then
    res=pcall(ParseSettings, sSettings)
    if res then
      baseName=string.format("%s %s", baseName, g_matid)
      if g_issingle==false then
        if g_topin==1 then
          baseName=string.format("%s topin", baseName)
        end
        if g_topout==1 then
          baseName=string.format("%s topout", baseName)
        end
        if g_botin==1 then
          baseName=string.format("%s botin", baseName)
        end
        if g_botout==1 then
          baseName=string.format("%s botout", baseName)
        end
      end
    end
  end
  return baseName
end

]]>
        </script>
        

        <!-- Window lengthwise cut -->
        <script id="openingsbotcut">
          <![CDATA[
g_height=0.018
g_depth=0.038
g_win=1
g_door=1
g_topbot=1			-- 1=top, 3=bottom

function dump(o)
  if type(o) == 'table' then
    local s = '{ '
    for k,v in pairs(o) do
      if type(k) ~= 'number' then k = '"'..k..'"' end
      s = s .. '['..k..'] = ' .. dump(v) .. ','
    end
    return s .. '} '
  else
    return tostring(o)
  end
end


-- Asks for the material to use
-- sSettings may be nil
-- Sets globals to given values
function SettingsDlg(sSettings)
	local	tblSettings, bRes, sErr, s, n
  local tblMat, i, id, v, thickness, height, mat
    
  tblSettings={}
	tblSettings[1]			={}
	tblSettings[1].cfgonly	=0
	tblSettings[1].type		=3
	tblSettings[1].prompt	="Height of the cut"
	tblSettings[1].key		="cutheight"
	tblSettings[1].defvalue	=0.025

	tblSettings[2]			={}
	tblSettings[2].cfgonly	=0
	tblSettings[2].type		=3
	tblSettings[2].prompt	="Depth of the cut"
	tblSettings[2].key		="cutdepth"
	tblSettings[2].defvalue	=0.040

  tblSettings[3]			={}
  tblSettings[3].cfgonly	=0
  tblSettings[3].type		=2
  tblSettings[3].prompt	="Cut window bottom"
  tblSettings[3].key		="dowin"
  tblSettings[3].defvalue	=1

  tblSettings[4]			={}
  tblSettings[4].cfgonly	=0
  tblSettings[4].type		=2
  tblSettings[4].prompt	="Cut door bottom"
  tblSettings[4].key		="dodoor"
  tblSettings[4].defvalue	=1
  
	tblSettings[5]			={}
	tblSettings[5].cfgonly	=0
	tblSettings[5].type		=1
	tblSettings[5].prompt	="Target surface"
	tblSettings[5].key		="side"
	tblSettings[5].valuelist="\"1:Top\",\"3:Bottom\""
	tblSettings[5].defvalue	=3
  

  if sSettings~=nil and sSettings~="" then
    local res, err
    res,err=pcall(ParseSettings, sSettings)
    if not res then
      ac_environment( "tolog", string.format("SettingsDlg/parse settings failed: %s", tostring(err)) )
    end
  end

  -- Anyway put defaults if not settings
  tblSettings[1].value=g_height
  tblSettings[2].value=g_depth
  tblSettings[3].value=g_win
  tblSettings[4].value=g_door
  tblSettings[5].value=g_topbot

	bRes,sErr=ac_optiondlg("LDWC", "Angled cuts for doors and windows", tblSettings)
	if not bRes then
    return false
  end

  g_height=tblSettings[1].value
  g_depth=tblSettings[2].value
  g_win=tblSettings[3].value
  g_door=tblSettings[4].value
  g_topbot=tblSettings[5].value
  return true
end


-- Returns 1-based table having all items with fields:
-- ptr
-- openingtype 13 or 23 or for empty openings 113 or 123
function FindDoorWinBottoms()
	local	kPoly, vPoly, tblPoly, tblSettings, tblRes, nRes, nBegContour, v
	local x1, y1, x2, y2
  local isBot, tblVert, nVert, elemGroup
  local vert
	
	
	tblSettings={}
	tblSettings.calcopening=1
	tblPoly=af_request("getpoly", tblSettings, gGuidElem)

	tblRes={}
	nRes=0

  tblVert={}
  nVert=0
  
	nBegContour=1
	for kPoly, vPoly in ipairs(tblPoly.poly) do
		if vPoly.isbeghole then
			nBegContour=kPoly
		end
			
    -- Calc line here
			if vPoly.isendcontour then
				v=tblPoly.poly[nBegContour]
			else
				v=tblPoly.poly[kPoly+1]
			end
			x1=vPoly.x
			y1=vPoly.y
			x2=v.x
			y2=v.y

    isBot=(vPoly.openingtype==13 or vPoly.openingtype==113 or vPoly.openingtype==23 or vPoly.openingtype==123)
		if isBot or math.abs(y2-y1)<0.001 then
			-- Is door & win, find all related planks (also all vertical ones if not linked to any AC openings/copied element)
			-- Scan planks
			local i, elemData, plankInfo, dist, off, dist2, off2, lineLen
			
			for i=1,gnPlanks do
				
				ac_objectopen(string.format("#%d", i))
				elemData=ac_objectget("#af_elemdata")
        elemGroup=ac_objectget("iElemGroup")
				plankInfo=af_request("plankinfo")
				ac_objectclose()
				
				dist,off,lineLen=ac_geo("linedist", x1, y1, x2, y2, elemData.x1, elemData.y1)
				dist2,off2,lineLen=ac_geo("linedist", x1, y1, x2, y2, elemData.x2, elemData.y2)
				
				if math.abs(dist-dist2)<0.001 and off>-0.010 and off<lineLen+0.010 and off2>-0.010 and off2<lineLen+0.010 then
					-- Parallel and is inside the polygon edge, say max 30 mm from window line
					if math.abs(dist)-plankInfo.width*0.5<0.030 then
            if isBot then
						-- Found!
						nRes=nRes+1
						tblRes[nRes]={}
						tblRes[nRes].ptr=plankInfo.ptr
						tblRes[nRes].openingtype=vPoly.openingtype
            elseif string.match(elemGroup, "^vertical_x.*") then
              vert={}
              vert.x1=x1
              vert.x2=x2
              vert.y1=y1
              vert.y2=y2
              vert.ptr=plankInfo.ptr
              nVert=nVert+1
              tblVert[nVert]=vert
					end
				end
			end
		end
	end
	end
  
  if nRes==0 then
    -- Perhaps copied element and no links to original AC-openings. Check collected vertical planks and take only the lowest pieces
    local i1, i2, vert2
    
    for i1=1,nVert do
      vert=tblVert[i1]
      if vert.x2<vert.x1 then
        vert.x2,vert.y2,vert.x1,vert.y1=vert.x1,vert.y1,vert.x2,vert.y2
      end
      i2=i1+1
      while i2<=nVert do
        vert2=tblVert[i2]
        if vert2.x2<vert2.x1 then
          vert2.x2,vert2.y2,vert2.x1,vert2.y1=vert2.x1,vert2.y1,vert2.x2,vert2.y2
        end
        if math.abs(vert2.x1-vert.x1)<0.001 and math.abs(vert2.x2-vert.x2)<0.001 and vert2.y1<vert.y1 then
          break
        end
        i2=i2+1
      end
      if i2>nVert then
        nRes=nRes+1
				tblRes[nRes]={}
				tblRes[nRes].ptr=vert.ptr
				tblRes[nRes].openingtype=13   -- Say window bottom
      end
    end
  end
  
  return tblRes
end


-- Deletes all lengthwise cuts from opened plank
-- Returns: true=found, false=not found
function EditCutSingle(bDel, bAdd, openingtype)
  local i, count, mc, col, res, addIndex
  
  res=false
  count=ac_objectget("iMc",-1)
  addIndex=nil
  for i=1,count do
    mc=ac_objectget("iMc", i, 1)
	  if mc==305 then
		  res=true
		  if not addIndex then
			  addIndex=i
		  end
		  if bDel then
			  for col=1,16 do
				  ac_objectset("iMc", 0, i, col)
			  end
		  end
	  end
  end
  
  if bAdd and ((g_win==1 and (openingtype==13 or openingtype==113)) or (g_door==1 and (openingtype==23 or openingtype==123))) then
	  -- Add new one
	  local plankInfo, a
	
	  plankInfo=af_request("plankinfo")
	  if not addIndex then
		  addIndex=count
	  end

	  for col=1,16 do
		  ac_objectset("iMc", 0, addIndex, col)
	  end
	
	  -- double		dType;
	  -- double		dSideOneBased;	// 2
	  -- double		xStart;			// 3
	  -- double		dWidth;			// 4, 0=from xStart to the end
	  -- double		dDepthTop;		// 5, A from surface, neg=outside the plank
	  -- double		dYoffTop;		// 6, B from middle of the surface
	  -- double		dAngleY2Deg;	// 7, C angle at surface y2
	  -- double		dAngleY1Deg;	// 8, D angle at surface y1
	  -- double		dSideType;		// 9, 0=Just sawing, 1=use cutter for the sides
	
    a=57.295779513*math.atan2(g_height, g_depth)     -- 180/PI
	  ac_objectset("iMc", 305, addIndex, 1)
	  ac_objectset("iMc", 2, addIndex, 2)		-- Front surface
	  if g_topbot==1 then
		  ac_objectset("iMc", plankInfo.height*0.5-g_depth, addIndex, 6)
      ac_objectset("iMc", a, addIndex, 7)
	  else
		  ac_objectset("iMc", -plankInfo.height*0.5+g_depth, addIndex, 6)
      ac_objectset("iMc", a, addIndex, 8)
	  end
  end
  return res
end


-- Deletes all cuts from given planks
function EditCuts(tblRes, bDel, bAdd)
  local k,v,res
  
  res=false
  for k,v in ipairs(tblRes) do
	  ac_objectopen(v.ptr)
	  if EditCutSingle(bDel, bAdd, v.openingtype) then
		  res=true
	  end
	  ac_objectclose()
  end
  return res
end


-- Adds cuts
function DoCuts()
	local	tblRes
	
	-- Find all and remove
	tblRes=FindDoorWinBottoms()
	EditCuts(tblRes, true, true)
end


-------------------------
-- FOR OPTION DLG


-- Gets value from key=value\n string
function GetVal(data, keyName)
  local k,v

	for k, v in string.gmatch(data, "([^ \r\n]+)=([^\r\n]+)") do
    --ac_environment("tolog", string.format("#%s=%s\n", k, v))
		if k == keyName then
			return v
		end
	end
  return nil
end


-- Called with pcall(), sets globals
function ParseSettings(sSettings)
  local s
  
--ac_environment("tolog", string.format("sSettings=%s\n", sSettings) )
  g_height=tonumber(GetVal(sSettings, "height"))
  g_depth=tonumber(GetVal(sSettings, "depth"))
  g_win=tonumber(GetVal(sSettings, "win"))
  g_door=tonumber(GetVal(sSettings, "door"))
  g_topbot=tonumber(GetVal(sSettings, "side"))
  
  -- Will cause error if bad syntax
  s=string.format("height=%f\ndepth=%f\nwin=%d\ndoor=%d\nside=%d\n", g_height, g_depth, g_win, g_door, g_topbot)
end


-- Finds nice material
function GetDefaults()
	g_height=0.018
	g_depth=0.038
	g_win=1
	g_door=1
	g_topbot=1
end


-- Returns: -1=Not known/no planks, 0=nope, 1=has
function Has()
	local tblRes

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return -1
  end
	tblRes=FindDoorWinBottoms()
	if EditCuts(tblRes, false, false) then
		return 1
	else
		return 0
	end
end


-- Return: nil=canceled, ""=clear settings/use defaults, str=settings str
function Settings(sSettings)
  if sSettings==nil or sSettings=="" then
    GetDefaults()
  end
  -- Ask material
  
  if not SettingsDlg(sSettings) then
    return nil
  end

  s=string.format("height=%f\ndepth=%f\nwin=%d\ndoor=%d\nside=%d\n", g_height, g_depth, g_win, g_door, g_topbot)
  return s
end


function Set(sSettings)
  local default, res, errStr, zoff, tblLastAdded, i, v, s, overL, overR, thickness
  
  gnPlankCount=0
  gtblCreate = {}

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return
  end

  default=true
  if sSettings~=nil then
    res, errStr=pcall(ParseSettings, sSettings)
    if res then
      default=false
    end
  end

  if default then
    -- Default settings
    GetDefaults()
  end
  
  
  DoCuts()
end


function Reset()
	local	tblRes

	-- Find all and remove
	tblRes=FindDoorWinBottoms()
	EditCuts(tblRes, true, false)
	return true
end


function GetName(sSettings, baseName)
  if sSettings~=nil then
    res, errStr=pcall(ParseSettings, sSettings)
    if res then
      if g_mat.thickness~=0 then
        baseName=string.format("%s %s", baseName, g_mat.id)
      else
        baseName=string.format("%s %sx%s", baseName, ac_environment("ntos", g_height, "length", "work"), ac_environment("ntos", g_depth, "length", "work"))
      end
    end
  end
  return baseName
end

-- FOR OPTION DLG
-------------------------


]]>
        </script>

        <script id="openingsupport">
          <![CDATA[
-- For planks to be created
gnPlankCount=0
gtblCreate = {}


gOptGroupName="vertical_y_openingsupport"


function dump(o)
  if type(o) == 'table' then
    local s = '{ '
    for k,v in pairs(o) do
      if type(k) ~= 'number' then k = '"'..k..'"' end
      s = s .. '['..k..'] = ' .. dump(v) .. ','
    end
    return s .. '} '
  else
    return tostring(o)
  end
end


-- Finds nice material
function GetDefaults()
  local mat
  
  mat=af_request("elem_getstudmat")
  if mat==nil then
    return false
  end

  g_mat=af_request("singlemat", mat)
  return true
end


-- Scans edges table and returns table of edges for given holeIndex (1...N)
-- Returns: nil=no such opening, tbl=1-based table of edges
function GetOpening(holeIndex)
  local i,v
  local tblRes, nres
  
  nres=0
  tblRes={}
  for i,v in ipairs(gtblEdges) do
    -- Process only contour line
    if v.holeindex==holeIndex then
      nres=nres+1
      tblRes[nres]=v
    end
  end
  
  if nres==0 then
    return nil
  end

  return tblRes
end


function DoOpeningSupport( strMatId, nMatThickness, nMatHeight )
  local nOpening, tblOpening, edge, vEdge, dx, i, v
  local plank, strXmlOp
  local tblLimitOpenings


  gnPlankCount=0
  gtblCreate = {}
  tblLimitOpenings = nil   -- If non-nil, contains true value for every opening index to be handled, for example opening 1: [1]=true
  
  if gAdjustElems then
    -- From options tool palette, may limit openings with selection. Check if selected planks related to any openig
    local tblSel, guid, tblSelGuids

    tblSel=af_request("getselplanks")
    if tblSel then
    
      tblSelGuids={}
      for i,v in pairs(tblSel) do
        tblSelGuids[v]=true
      end

      nOpening=1
      while true do
        tblOpening=GetOpening(nOpening)
        if tblOpening==nil then
          break
        end
        
        for edge,vEdge in ipairs(tblOpening) do
          if vEdge.ptr then
            ac_objectopen(vEdge.ptr)
            guid=ac_objectget("#guid")
            ac_objectclose()
            if tblSelGuids[guid]~=nil then
              if tblLimitOpenings==nil then
                tblLimitOpenings={}
              end

              tblLimitOpenings[nOpening]=true
            end
          end
        end
        
        nOpening=nOpening+1
      end
    end
  end

  nOpening=1
  strXmlOp=""
  while true do
    tblOpening=GetOpening(nOpening)
    if tblOpening==nil then
      break
    end
    nOpening=nOpening+1

    if #tblOpening==4 and (tblLimitOpenings==nil or tblLimitOpenings[nOpening-1]) then 
      -- Find vertical pieces (openings are ccw as the main contour)
      for edge,vEdge in ipairs(tblOpening) do
        if math.abs(vEdge.x2-vEdge.x1)<0.001 and vEdge.ptr~=nil then
          -- Could use strMatId, nMatThickness, nMatHeight
          local elemdata, plankinfo, s, prevEdge, nextEdge, miny, maxy

          miny=vEdge.y1
          maxy=vEdge.y2
          dx=-1
          if vEdge.y1>vEdge.y2 then
            dx=1
            miny,maxy=maxy,miny
          end
          
          if edge>1 then
            prevEdge=tblOpening[edge-1]
          else
            prevEdge=tblOpening[#tblOpening]
          end

          if edge<#tblOpening then
            nextEdge=tblOpening[edge+1]
          else
            nextEdge=tblOpening[1]
          end

          ac_objectopen(vEdge.ptr)
          elemdata=ac_objectget("#af_elemdata")
          plankinfo=af_request("plankinfo")
          ac_objectclose()

          -- Above opening (this condition already should skip lintel cases)
          if elemdata.y2>maxy+0.001 then
            plank={}
            plank.guidsettings=vEdge.ptr
            plank.copyops=1
            plank.group=gOptGroupName
            plank.id=strMatId
            plank.thickness=nMatThickness
            plank.height=nMatHeight

            plank.x1=elemdata.x1+dx*plankinfo.width
            if vEdge.y1<vEdge.y2 then
              plank.y1=nextEdge.y1
            else
              plank.y1=prevEdge.y1
            end

            plank.x2=plank.x1
            plank.y2=elemdata.y2
            
            -- Create only if no intersection with a lintel type piece
            local hasx, scan
            
            hasx=false
            for scan=1,gnPlanks do
              ac_objectopen(string.format("#%d",scan))
              s=ac_objectget("iElemGroup")
              ac_objectclose()
              
              if s=="lintel" then
                local infolintel, x, y
                
                ac_objectopen(string.format("#%d",scan))
                infolintel=ac_objectget("#af_elemdata")
                ac_objectclose()

                x,y=ac_geo("linex", plank.x1, plank.y1, plank.x2, plank.x2, infolintel.x1, infolintel.y1, infolintel.x2, infolintel.y2)
                if x~=nil then
                  -- Check if inside the lines
                  if y>plank.y1 and y<plank.y2 and x>infolintel.x1 and x<infolintel.x2 then
                    hasx=true
                    break
                  end
                end
              end
            end
            
            if not hasx then
              gnPlankCount=gnPlankCount+1
              gtblCreate[gnPlankCount]=plank
          
              s=string.format("<jointo target=\"#%d\" operator=\"vertical_x*|top*|2ndtop*|contourtilted\" operatorskip=\"topbalk*\"><cut jointgap=\"0.000\" endshape=\"angleddelfirst\" extendmaxlen=\"0.100\"></cut></jointo>", gnPlanks+gnPlankCount)
              strXmlOp=strXmlOp .. s
            end
          end

          -- Below opening
          if elemdata.y1<miny-0.001 then
            plank={}
            plank.guidsettings=vEdge.ptr
            plank.copyops=1
            plank.group=gOptGroupName
            plank.id=strMatId
            plank.thickness=nMatThickness
            plank.height=nMatHeight

            plank.x1=elemdata.x1+dx*plankinfo.width
            plank.y1=elemdata.y1
            plank.x2=plank.x1
            if vEdge.y1<vEdge.y2 then
              plank.y1=prevEdge.y2
            else
              plank.y1=nextEdge.y2
            end

            gnPlankCount=gnPlankCount+1
            gtblCreate[gnPlankCount]=plank
          
            s=string.format("<jointo target=\"#%d\" operator=\"vertical_x*|bottom*|2ndbottom*\" operatorskip=\"bottombalk*\" ><cut jointgap=\"0.000\" endshape=\"angleddelfirst\" extendmaxlen=\"0.100\"></cut></jointo>", gnPlanks+gnPlankCount)
            strXmlOp=strXmlOp .. s
          end

        end
      end   -- for edge,vEdge
    end
  end
  
  if strXmlOp~="" then
    gxmlOperations=string.format("<operations>\n%s</operations>", strXmlOp)
  end

end


-- Returns: -1=Not known/no planks, 0=nope, 1=has
function Has()
  local i

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return -1
  end
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    s=ac_objectget("iElemGroup")
    if string.match(s, "^" .. gOptGroupName .. ".*") then
      ac_objectclose()
      return 1
    end
    ac_objectclose()
  end
  return 0
end


function Set(sSettings)
  local default, res, errStr, zoff, tblLastAdded, i, v, s, overL, overR, thickness
  
  gnPlankCount=0
  gtblCreate = {}

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return
  end

  GetDefaults()

  if g_mat.thickness>0 then
    g_thickness=g_mat.thickness
  end

  if g_mat.height>0 then
    g_height=g_mat.height
  end

  DoOpeningSupport( g_mat.id, g_thickness, g_height )
  
  af_request("elem_createplanks")
end


function Reset()
  local i, elemDel, infoDel, elemNow, infoNow, nOpening, tblOpening, vEdgeOpening, edgeDir, y, y1, y2, e, v, x
  local strXmlOp

  gnPlankCount=0
  gtblCreate = {}

  res=false
  strXmlOp=""
  af_request("elem_getpoly")
  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d",i))
    s=ac_objectget("iElemGroup")
    if string.match(s, "^" .. gOptGroupName .. ".*") then
      elemDel=ac_objectget("#af_elemdata")
      infoDel=af_request("plankinfo")
      af_request("delplank")
      res=true
    end
    ac_objectclose()
  end

  return res
end
]]>
        </script>


        <script id="autocuttopbot">
          <![CDATA[
-- For planks to be created
gnPlankCount=0
gtblCreate = {}

gtblTop=nil       -- Topmost pieces "top_force" | "bottom_force"
gtbl2ndTop=nil    -- 2nd topmost pieces "2ndtop_force" | "2ndbottom_force"

gdMaxLen=4.78    -- Without EPS, 0=use plank's set maximum length
gdMinLen=1.200
gdMinOverlap=1.200


function dump(o)
  if type(o) == 'table' then
    local s = '{ '
    for k,v in pairs(o) do
      if type(k) ~= 'number' then k = '"'..k..'"' end
      s = s .. '['..k..'] = ' .. dump(v) .. ','
    end
    return s .. '} '
  else
    return tostring(o)
  end
end


-- Sets also gloval target gtblTop, gtbl2ndTop
function FindStuds(isBot)
  local tblStuds, plank, i, s, tblDest, group1, group1ex, group2, rotAngleLimit

  tblStuds={}
  gtblTop={}
  gtbl2ndTop={}
  
  group1="^top_force%a*"
  group1ex="contourtilted"
  group2="^2ndtop_force%a*"
  if isBot then
    group1="^bottom_force%a*"
    group1ex=nil
    group2="^2ndbottom_force%a*"
  end

  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d", i))
    s=ac_objectget("iElemGroup")

    tblDest=nil
    rotAngleLimit=nil
    if string.match(s, group1) or (group1ex and s==group1ex) then
      tblDest=gtblTop
    elseif string.match(s, group2) then
      tblDest=gtbl2ndTop
    elseif string.match(s, "^vertical_%a*") then
      tblDest=tblStuds
      rotAngleLimit=0
    end

    if tblDest then
      plank={}
      plank.elemgroup=s
      plank.elemdata=ac_objectget("#af_elemdata")
      plank.plankinfo=af_request("plankinfo")
      if not rotAngleLimit or math.abs(plank.elemdata.rotangle, rotAngleLimit)<1 then
        if string.match(s, "^vertical_%a*") and math.abs(plank.elemdata.x2-plank.elemdata.x1)>0.001 then
          plank=nil
        end
        
        if plank and not plank.plankinfo.del then
          tblDest[#tblDest+1]=plank
        end
      end
    end

    ac_objectclose()
  end

  table.sort( tblStuds, function (p1, p2)
    if p1.elemgroup~=p1.elemgroup then
      return p1.elemgroup<p1.elemgroup
    end
    return p1.elemdata.x1 < p2.elemdata.x1
	end)

  table.sort( gtblTop, function (p1, p2)
    if p1.elemgroup~=p1.elemgroup then
      return p1.elemgroup<p1.elemgroup
    end
    return p1.elemdata.x1 < p2.elemdata.x1
	end)

  table.sort( gtbl2ndTop, function (p1, p2)
    if p1.elemgroup~=p1.elemgroup then
      return p1.elemgroup<p1.elemgroup
    end
    return p1.elemdata.x1 < p2.elemdata.x1
	end)

  return tblStuds,#tblStuds
end


-- Splits single plank
-- tx1, ty2, tx2, ty2   Line for the plank to be split (lower edge for top, upper edge for bottom): Plank will be cut on stud and this intersection
-- tblSplit All cut places are saved here (sorted)
-- No return value
function DoRow(currPlank, bStartLong, tblStuds, nStuds, tblPrev, tblSplit, tx1, ty1, tx2, ty2)
  local startPos, len, i1, i2, bFound, x, y, xLen, dx, dy, currPtr, maxLen, minLen, minOverlap, cosAngle
  
  cosAngle=math.abs(currPlank.elemdata.x2-currPlank.elemdata.x1)/currPlank.plankinfo.len
  currPtr=currPlank.plankinfo.ptr
  
  maxLen=gdMaxLen
  if maxLen<0.001 then
    -- Get from plank's iMaxLen parameter
    ac_objectopen(currPtr)
    maxLen=ac_objectget("iMaxLen")
    ac_objectclose()
    
    if maxLen<0.001 then
      maxLen=5
    end
  end
  minLen=gdMinLen
  minOverlap=gdMinOverlap
  
  startPos=0
  len=currPlank.plankinfo.len
  while len-startPos>maxLen+0.0005 do
    -- Need to split, find as long as possible splitting part
    bFound=false
    i1=nStuds
    while i1>=1 do
      x,y=ac_geo("linex", tx1, ty1, tx2, ty2, tblStuds[i1].elemdata.x1, tblStuds[i1].elemdata.y1-1, tblStuds[i1].elemdata.x2, tblStuds[i1].elemdata.y2+1)
      if x then
        dx,dy=ac_geo("linedist", tx1, ty1, tx2, ty2, x, y)
        dy=dy-startPos
        if dy<maxLen+0.001 and len-(dy+startPos)>minLen-0.001 then
          if dy<minLen-0.0009 then
            break
          end

          -- Check if allowed
          bFound=true
          for i2=1,#tblPrev do
            if math.abs(x-tblPrev[i2])<minOverlap/cosAngle-0.001 then
              bFound=false
              break
            end
          end
        end
      
        if bFound then
--ac_environment("tolog", string.format("x=%f y=%f dx=%f dy=%f tx1=%f ty1=%f tx2=%f ty2=%f sx1=%f sy1=%f sx2=%f sy2=%f", x, y, dx, dy, tx1, ty1, tx2, ty2, tblStuds[i1].elemdata.x1, tblStuds[i1].elemdata.y1-1, tblStuds[i1].elemdata.x2, tblStuds[i1].elemdata.y2+1))
          break
        end
      end
      
      i1=i1-1
    end

    if not bFound then
      ac_environment("tolog", "WARNING: Unable to automatically cut plank by rules (minimum length, minimum overpal), please check and cut manually.")
      break
    end
    
    local tblPlane
    
    tblSplit[#tblSplit+1]=x
    ac_objectopen(currPtr)
    tblPlane=af_request("getbegendplane", "beg", 1)
    tblPlane.pd=tblPlane.pd+dy
    currPtr=af_request("cutplank", tblPlane)
    ac_objectclose()

    if not currPtr then
      break
    end

    startPos=startPos+dy
    bStartLong=true
  end
end


function DoAutoCutTop(isBot)
  local tblStuds, nStuds, i1, i2, x1, y1, x2, y2, dx, dy, tblPlank

  gnPlankCount=0
  gtblCreate = {}
  
  tblStuds,nStuds=FindStuds(isBot)     -- Also finds target elements
  
  if gAdjustElems then
    -- From options tool palette, may limit targets with selection. Forget now.
    local tblSel

    tblSel=af_request("getselplanks")
    if tblSel then

    end
  end
  
  -- Discard any stud not close enough to lowest top piece
  local yDir=-1
  
  if isBot then
    yDir=1
  end

  local tblTargetRows, bStartLong, tblPrev
  
  tblTargetRows={}
  i2=0
  if isBot then
    if #gtblTop>0 then
      i2=i2+1
      tblTargetRows[i2]=gtblTop
    end
    if #gtbl2ndTop>0 then
      i2=i2+1
      tblTargetRows[i2]=gtbl2ndTop
    end
  else
    if #gtbl2ndTop>0 then
      i2=i2+1
      tblTargetRows[i2]=gtbl2ndTop
    end
    if #gtblTop>0 then
      i2=i2+1
      tblTargetRows[i2]=gtblTop
    end
  end

  local i3, tblPrevTot

  bStartLong=true
  tblPrev={}
  for i1=1,i2 do
    tblPrevTot={}
    for i3=1,#tblTargetRows[i1] do
      tblPlank=tblTargetRows[i1][i3]

      x1=tblPlank.elemdata.x1
      y1=tblPlank.elemdata.y1
      x2=tblPlank.elemdata.x2
      y2=tblPlank.elemdata.y2
      dx=(x2-x1) / tblPlank.plankinfo.len * tblPlank.plankinfo.width * 0.5
      dy=(y2-y1) / tblPlank.plankinfo.len * tblPlank.plankinfo.width * 0.5
  
      if x1>x2 then
        yDir=-yDir
      end

      dx,dy=-dy*yDir, dx*yDir     -- For bottom piece: Left from line
      x1=x1+dx
      y1=y1+dy
      x2=x2+dx
      y2=y2+dy
  
      DoRow(tblTargetRows[i1][i3], bStartLong, tblStuds, nStuds, tblPrev, tblPrevTot, x1, y1, x2, y2)
    end
    tblPrev=tblPrevTot
    bStartLong=not bStartLong
  end
end


-- Returns: -1=Not known/no planks, 0=nope, 1=has
function Has()
  return ResetInt(true)
end


function Set(sSettings)
  local default, res, errStr

  gnPlankCount=0
  gtblCreate = {}

  af_request("elem_getpoly")
  if gnPlanks==0 then
    return
  end

  default=true
  if sSettings~=nil then
    res, errStr=pcall(ParseSettings, sSettings)
    if res then
      default=false
    end
  end

  if default then
    -- Default settings
    GetDefaults()
  end  

  DoAutoCutTop(false)
  DoAutoCutTop(true)

  af_request("elem_createplanks")
end


-- justCheck  true=do not connect, just check if there are split pieces
-- Returns: true=changes, false=no split ones
function DoJoin(tblPlanks, justCheck)
  local i, firstInd, res, x1, y1, x2, y2, hasX, dist1, len1, dist2, len2, dx, dy

  -- Join all connecting ones to the first piece
  firstInd=1
  res=false
  for i=2,#tblPlanks do
    x1=tblPlanks[firstInd].elemdata.x1
    y1=tblPlanks[firstInd].elemdata.y1
    x2=tblPlanks[firstInd].elemdata.x2
    y2=tblPlanks[firstInd].elemdata.y2

    hasX=ac_geo("linex", x1, y1, x2, y2, tblPlanks[i].elemdata.x1, tblPlanks[i].elemdata.y1, tblPlanks[i].elemdata.x2, tblPlanks[i].elemdata.y2)
    dist1,len1 = ac_geo("linedist", x1, y1, x2, y2, tblPlanks[i].elemdata.x1, tblPlanks[i].elemdata.y1)
    dist2,len2 = ac_geo("linedist", x1, y1, x2, y2, tblPlanks[i].elemdata.x2, tblPlanks[i].elemdata.y2)

    if len2<len1 then
      len1=len2
      dist1=dist2
    end
    
    dx=x2-x1
    dy=y2-y1
    len2=math.sqrt(dx*dx+dy*dy)
--ac_environment("tolog", string.format("x1=%f y1=%f x2=%f y2=%f len1=%f dist1=%f len2=%f", x1, y1, x2, y2, len1, dist1, len2))
    if not hasX and math.abs(dist1)<0.001 and math.abs(dist2)<0.001 and len1>-0.001 and len1<len2+0.001 then
      res=true
      if justCheck then
        break
      end
      af_request("joinplanks", tblPlanks[firstInd].plankinfo.ptr, tblPlanks[i].plankinfo.ptr)
      
      ac_objectopen(tblPlanks[firstInd].plankinfo.ptr)
      tblPlanks[firstInd].elemdata=ac_objectget("#af_elemdata")     -- Refresh
      ac_objectclose()
    else
      firstInd=i
    end
  end
  return res
end


function Reset()
  return ResetInt(false)
end


function ResetInt(justCheck)
  local res, i
  
  gnPlankCount=0
  gtblCreate = {}

  res=0
  af_request("elem_getpoly")
  if gnPlanks==0 then
    return -1
  end
  
  -- Top
  FindStuds(false)
  if #gtblTop>1 then
    if DoJoin(gtblTop, justCheck) then
      res=1
    end
  end
  if #gtbl2ndTop>1 then
    if DoJoin(gtbl2ndTop, justCheck) then
      res=1
    end
  end

  -- Bottom
  FindStuds(true)
  if #gtblTop>1 then
    if DoJoin(gtblTop, justCheck) then
      res=1
    end
  end
  if #gtbl2ndTop>1 then
    if DoJoin(gtbl2ndTop, justCheck) then
      res=1
    end
  end

  return res
end


-------------------------
-- OPTIONS


function SettingsDlg(sSettings)
  local  tblSettings, bRes, sErr


  GetDefaults()
  if sSettings~=nil and sSettings~="" then
    pcall(ParseSettings, sSettings)
  end
  
  tblSettings={}
  tblSettings[1]			={}
  tblSettings[1].cfgonly	=0
  tblSettings[1].type		=3
  tblSettings[1].prompt	="Max length (0=use plank's maximum length):"
  tblSettings[1].key		="maxlen"
  tblSettings[1].value	=gdMaxLen

  tblSettings[2]			={}
  tblSettings[2].cfgonly	=0
  tblSettings[2].type		=3
  tblSettings[2].prompt	="Min length:"
  tblSettings[2].key		="minlen"
  tblSettings[2].value  =gdMinLen

  tblSettings[3]			={}
  tblSettings[3].cfgonly	=0
  tblSettings[3].type		=3
  tblSettings[3].prompt	="Min overlap:"
  tblSettings[3].key		="minoverlap"
  tblSettings[3].value  =gdMinOverlap

  bRes,sErr=ac_optiondlg("LDAC", "Automatic cutting", tblSettings)
  if not bRes then
    return false
  end

  gdMaxLen=tblSettings[1].value
  gdMinLen=tblSettings[2].value
  gdMinOverlap=tblSettings[3].value
  return true
end



-- Gets value from key=value\n string
function GetVal(data, keyName)
  local k,v

  for k, v in string.gmatch(data, "([^ \r\n]+)=([^\r\n]+)") do
    if k == keyName then
      return v
    end
  end
  return nil
end


-- Called with pcall(), sets globals: g_mat, g_thickness, g_height
function ParseSettings(sSettings)
  local s
  
  gdMaxLen=tonumber(GetVal(sSettings, "maxlen"))
  gdMinLen=tonumber(GetVal(sSettings, "minlen"))
  gdMinOverlap=tonumber(GetVal(sSettings, "minoverlap"))

  -- Will cause error if bad syntax
  s = string.format("maxlen=%0.5f\nminlen=%0.5f\nminoverlap=%0.5f", gdMaxLen, gdMinLen, gdMinOverlap )
end


-- Finds nice material
function GetDefaults()
  gdMaxLen=4.78    -- Without EPS, 0=use plank's set maximum length
  gdMinLen=1.200
  gdMinOverlap=1.200
end



-- Return: nil=canceled, ""=clear settings/use defaults, str=settings str
function Settings(sSettings)
  if not SettingsDlg(sSettings) then
    return
  end

  sSettings=string.format("maxlen=%0.5f\nminlen=%0.5f\nminoverlap=%0.5f", gdMaxLen, gdMinLen, gdMinOverlap )
  return sSettings
end
]]>
        </script>

        <!-- DIM SCRIPTS BEG -->
        <script id="dim_wallsect">
          <![CDATA[
-- Returns cos angle of the vectors if normalized
function CalcDot3D( x1, y1, z1, x2, y2, z2 )
	return x1 * x2 + y1 * y2 + z1 * z2;
end

function GetLang()
  local lang
  
  lang=af_request("aflang")
  if lang==nil then
    lang="eng"
  end
  return lang
end

function IsCoreBottom(elemgroup)
  return string.match(elemgroup, "^bottom_force.*") or string.match(elemgroup, "^2ndbottom_force.*")
end

function IsCoreTop(elemgroup)
  return string.match(elemgroup, "^top_force.*") or string.match(elemgroup, "^2ndtop_force.*")
end

function GetNameForTypetag(typetag)
  local lang=GetLang()
  local name=typetag

  if lang=="fin" then
    if string.match(typetag, "^finish_int.*") then
      name="VERH"
    elseif string.match(typetag, "^intstud.*") then
      name="KOOL"
    elseif string.match(typetag, "^boarding_int.*") then
      name="LEVY"
    elseif string.match(typetag, "^core.*") then
      name="RUNKO"
    elseif string.match(typetag, "^boarding_ext.*") then
      name="LEVY"
    elseif string.match(typetag, "^extstud.*") then
      name="KOOL"
    elseif string.match(typetag, "^finish_ext.*") then
      name="VERH"
    end
  else
    if string.match(typetag, "^finish_int.*") then
      name="PANEL"
    elseif string.match(typetag, "^intstud.*") then
      name="STUD"
    elseif string.match(typetag, "^boarding_int.*") then
      name="BOARD"
    elseif string.match(typetag, "^core.*") then
      name="CORE"
    elseif string.match(typetag, "^boarding_ext.*") then
      name="BOARD"
    elseif string.match(typetag, "^extstud.*") then
      name="STUD"
    elseif string.match(typetag, "^finish_ext.*") then
      name="CLADD"
    end
  end

  return name
end


-- Gives plank's y-coord in camera y-axis
function GetCamY1(tblCam,info)
  local x,y,z
  
  x=info.begc.x-tblCam.begc.x
  y=info.begc.y-tblCam.begc.y
  z=info.begc.z-tblCam.begc.z
  return CalcDot3D(x, y, z, tblCam.vecy.x, tblCam.vecy.y, tblCam.vecy.z)
end


-- Picks all horizontal pieces from layer typetag (core/intstud/intstud2 etc)
-- Returns:
-- 1. table of dim points
-- 2. true/false if there was any other planks than core
function FindHorPieces(typetag)
  local i, s, n, z, info, a
  local tblRes, tbl, elemdata, tblVertx, nvertx, hasValidDimPts, isCoreOnly
  local tblCoreOthers, ncoreothers
  local tblCoreBot, tblCoreTop
  local tblCam=af_request("dim_camera")     -- Use camera to judge if piece is horizontal or not


  isCoreOnly=(typetag=="core")
  hasValidDimPts=isCoreOnly
  tblRes={}
  n=0
  tblVertx={}       -- Collect vertical_x to be able to guess which one is lower and which upper
  nvertx=0
  tblCoreOthers={}  -- Add these to nvertx if we have nothing (probably floor structure etc)
  ncoreothers=0
  for i=1,gnPlanks do
    tbl=nil
    ac_objectopen(string.format("#%d",i))
    info=af_request("plankinfo")
    a=CalcDot3D(tblCam.vecz.x, tblCam.vecz.y, tblCam.vecz.z, info.vecx.x, info.vecx.y, info.vecx.z)
    if info.type==1 and math.abs(a)>0.999 then
      elemdata=ac_objectget("#af_elemdata")
      s=ac_objectget("iElemGroup")
      if elemdata and s then
        if elemdata.typetag=="core" then
          if IsCoreBottom(s) then
            tbl={}
            tbl.index=i
            tbl.anchorfirst=1
            tbl.anchormid=0
            tbl.anchorlast=0
            if isCoreOnly then
              tbl.anchorlast=1
            else
              -- Pick just lowest part (in camera y-dir)
              tbl.info=info
              if not tblCoreBot or GetCamY1(tblCam,info)<GetCamY1(tblCam,tblCoreBot.info) then
                tblCoreBot=tbl
              end
              tbl=nil
            end
          elseif IsCoreTop(s) then
            tbl={}
            tbl.index=i
            tbl.anchormid=0
            tbl.anchorlast=1
            if isCoreOnly then
              tbl.anchorfirst=1
            else
              -- Pick just lowest part (in camera y-dir)
              tbl.info=info
              if not tblCoreTop or GetCamY1(tblCam,info)>GetCamY1(tblCam,tblCoreTop.info) then
                tblCoreTop=tbl
              end
              tbl=nil
            end
          elseif string.match(s, "^vertical_x.*") then
            -- Just save horizontal opening pieces
            local t
            
            t={}
            t.index=i
            t.elemdata=elemdata
            nvertx=nvertx+1
            tblVertx[nvertx]=t
          else
            -- It is in camera's watching direction, perhaps a top balk
            local t
            
            t={}
            t.index=i
            t.elemdata=elemdata
            ncoreothers=ncoreothers+1
            tblCoreOthers[ncoreothers]=t
          end
        elseif not isCoreOnly and elemdata.typetag==typetag then
          -- Add all bottoms of vertical pieces
          tbl={}
          tbl.index=i
          tbl.anchorfirst=1
          tbl.anchormid=0
          tbl.anchorlast=0
          hasValidDimPts=true
        end
      end
      if tbl then
        n=n+1
        tblRes[n]=tbl
      end
    end
    ac_objectclose()
  end
  
  if tblCoreBot then
    n=n+1
    tblRes[n]=tblCoreBot
  end

  if tblCoreTop then
    n=n+1
    tblRes[n]=tblCoreTop
  end
  
  if (not tblCoreBot or not tblCoreTop) and nvertx==0 and ncoreothers>0 then
    for i=1,ncoreothers do
      nvertx=nvertx+1
      tblVertx[nvertx]=tblCoreOthers[i]
    end
  end

  if nvertx>0 then
    -- Sort horizontal window/door pieces, highest first
	  table.sort(tblVertx, function (n1, n2)
      return n1.elemdata.y1 > n2.elemdata.y1
	  end)
    
    i=1
    while i<=nvertx do
      if nvertx-i>=1 then
        -- Assume first is win top and second window bottom
        tbl={}
        tbl.index=tblVertx[i].index
        tbl.anchorfirst=1
        tbl.anchormid=0
        tbl.anchorlast=0
        if isCoreOnly then
          tbl.anchorlast=1
        end
        n=n+1
        tblRes[n]=tbl

        tbl={}
        tbl.index=tblVertx[i+1].index
        tbl.anchorfirst=0
        if isCoreOnly then
          tbl.anchorfirst=1
        end
        tbl.anchormid=0
        tbl.anchorlast=1
        n=n+1
        tblRes[n]=tbl
        i=i+2
      else
        -- Assume door top
        tbl={}
        tbl.index=tblVertx[i].index
        tbl.anchorfirst=1
        tbl.anchormid=0
        if isCoreOnly then
          tbl.anchorlast=1
        end
        n=n+1
        tblRes[n]=tbl
        i=i+1
      end
    end
  end
  
  return tblRes, hasValidDimPts
end


function MakeTextXml(content, textid)
  local s
  
  s=   "<text content=\"" .. content .. "\" textid=\"" .. textid .. "\" anchor=\"6\" marg=\"0.2\">\n"
  s=s.."  <elemparam name=\"pen\">1</elemparam>\n"
  s=s.."  <elemparam name=\"fontname\">arial</elemparam>\n"
  s=s.."  <elemparam name=\"fontsize\">1.5</elemparam>\n"
  s=s.."  <elemparam name=\"fontstyle\"></elemparam>\n"
  s=s.."  <layer></layer>\n"
  s=s.."</text>\n"
  return s
end


-- Makes dim line for horizontal pieces
-- dMargin is number: 0.2/0.15
-- Returns new ndims
function AddHorPieces(tblDims, ndims, typetag, dimSide, dMargin, dimdir)
  local t, s, name, hasStud

  name=GetNameForTypetag(typetag)
  s=string.format("<dimline side=\"%s\" margin=\"%0.2f\" %s %s>\n", dimSide, dMargin, dimdir, gDimExtraAttr)
  s=s..MakeTextXml(name, string.format("projid*20+%d", ndims))
  s=s..gDimExtraSettings
  s=s.."</dimline>"
  t={}
  t.xmldim=s
  t.dimpoints,hasStud=FindHorPieces(typetag)
  if hasStud then
    ndims=ndims+1
    tblDims[ndims]=t
  end
  return ndims
end


function AddSectionTblVert(tblSect,tblRes,n)
  local i,v,t
  
  for i,v in ipairs(tblSect) do
    t={}
    t.x=v.bottom_minx
    t.y=v.bottom_miny
    n=n+1
    tblRes[n]=t
    
    t={}
    t.x=v.top_minx
    t.y=v.top_miny
    n=n+1
    tblRes[n]=t
  end
  return n
end


function SortDimSectVert(tbl)
	  table.sort(tbl, function (n1, n2)
      return n1.bottom_miny < n2.bottom_miny
	  end)
end


-- Finds dimension points for layer size and offsets to core
function FindLayerSizeAndOff(tblCore, tblDims, ndims, sCurrLayer, sXmlDimLine, sDimText, dimdir)
  local tblCurr
  local nmain, tblMain, t, s, tblExtra, nextra
  
  tblCurr=af_request("dim_section", sCurrLayer)
  SortDimSectVert(tblCurr)
  if #tblCurr==0 then
    -- No such layer now
    return ndims
  end

  -- Add points from curr layer and create additional offset dim points if needed
  local icore, icurr, vcore, vcurr, vfound
  
  -- This is the main dim line for this layer, only coords
  tblMain={}
  nmain=0
  
  -- Additional dim lines after the main on same x-coord
  tblExtra={}
  nextra=0
  
  -- Find closest core points for each current layer's segments
  for icurr,vcurr in ipairs(tblCurr) do
    -- Find overlapping core segment
    vfound=nil
    for icore,vcore in ipairs(tblCore) do
      if vcore.top_miny>vcurr.bottom_miny and vcore.bottom_miny<vcurr.top_miny then
        -- Found overlap, take it
        vfound=vcore
        break
      end
    end

    -- Always add current layer min&max (ok if not sorted now)
    t={}
    t.x=vcurr.bottom_minx
    t.y=vcurr.bottom_miny
    nmain=nmain+1
    tblMain[nmain]=t

    t={}
    t.x=vcurr.top_minx
    t.y=vcurr.top_miny
    nmain=nmain+1
    tblMain[nmain]=t

    if vfound==nil then
      -- No related core segment, anything below?
      
      -- Anything above?
    else
      if vfound.bottom_miny<vcurr.bottom_miny then
        -- Core min below curr layer min, add to main dim line
        t={}
        t.x=vfound.bottom_minx
        t.y=vfound.bottom_miny
        nmain=nmain+1
        tblMain[nmain]=t
      else
        -- Core bottom above curr bottom, add extra line
        local t2
        
        t2={}
        t={}
        t.x=vcurr.bottom_minx
        t.y=vcurr.bottom_miny
        t2[1]=t
        
        t={}
        t.x=vfound.bottom_minx
        t.y=vfound.bottom_miny
        t2[2]=t
       
        nextra=nextra+1
        tblExtra[nextra]=t2
      end
      
      if vfound.top_miny+0.0004>vcurr.top_miny then
        -- Core max above curr layer max, add to main dim line
        t={}
        t.x=vfound.top_minx
        t.y=vfound.top_miny
        nmain=nmain+1
        tblMain[nmain]=t
      else
        -- Core top below curr top, add extra line
        local t2
        
        t2={}
        t={}
        t.x=vfound.top_minx
        t.y=vfound.top_miny
        t2[1]=t
        
        t={}
        t.x=vcurr.top_minx
        t.y=vcurr.top_miny
        t2[2]=t
       
        nextra=nextra+1
        tblExtra[nextra]=t2
      end
    end
  
  end

  s=sXmlDimLine .. "\n"
  s=s..MakeTextXml(sDimText, string.format("projid*20+%d", ndims))
  s=s..gDimExtraSettings
  s=s.."</dimline>"
  t={}
  t.xmldim=s
  t.dimpoints=tblMain

  ndims=ndims+1
  tblDims[ndims]=t
  
  -- Add all extra dim lines to the same x-coordinate (just first one having margin)
  local smarg, s1, s2, dummy
  
  smarg="0.1"
  for icurr,vcurr in ipairs(tblExtra) do
    -- sXmlDimLine is something like "<dimline side=\"left\" margin=\"0.3\" elemvecy=\"1\">", we want to set first margin to 0.25 and rest to 0
    dummy,dummy,s1,s2=string.find(sXmlDimLine, "(.*) margin=\".-\"(.*)")
    s=string.format("%s margin=\"%s\"%s", s1, smarg, s2)
--ac_environment("tolog", string.format("s1=%s s2=%s s=%s #vcurr=%d", s1, s2, s, #vcurr))
    
    smarg="0"
    s=s .. "</dimline>"
    t={}
    t.xmldim=s
    t.dimpoints=vcurr

    ndims=ndims+1
    tblDims[ndims]=t
  end
  return ndims
end


-- Returns two values: x1, x2
function FindX(tblSection)
  local i, v, x1, x2
  
  v=tblSection[1]
  x1=v.left_minx
  x2=v.right_minx
  i=2
  while true do
    v=tblSection[i]
    if v==nil then
      break
    end
    if x1>v.left_minx then
      x1=v.left_minx
    end
    if x2<v.right_minx then
      x2=v.right_minx
    end
    i=i+1
  end
  return x1,x2
end


-- Scans all planks and makes table of layers
-- Returns multiple values (nil if core not found):
-- 1st: 1-based table of layers sorted by camera x-coordinate. Each item has fields:
--   typetag    core/intstud etc.
--   elem.q     elem_quantities for the layer
-- 2nd: index to core layer
-- 3rd: elemvecy="1" etc (whatever axis matches camera's y)
function FindElemLayers(tblCam)
  local i
  local tbl
  local typetag, info
  local tblLayers                       -- key=element layer typetag, data: elem is the owner element ; parts beg and end each having fields: index, elemdata
  
  tblLayers={}
  for i=1,gnPlanks do
    ac_objectopen(string.format("#!%d",i))    -- Open related master plank
    info=af_request("plankinfo")
    typetag=nil
    tbl=ac_objectget("#af_elemdata")   -- To get typetag also
    if tbl then
      typetag=tbl.typetag
    end
    ac_objectclose()
    
    if typetag then
      tbl=tblLayers[typetag]
      if tbl==nil then
        -- Construct info for this layer
        tbl={}
        tbl.elem={}
        tbl.elem.q=af_request("elem_quantities", info.ownerelemguid, 0)
        tblLayers[typetag]=tbl
      end
    end
  end
  
  tblCore=tblLayers["core"]
  if tblCore==nil then
    return nil
  end

  -- Collect all layers and sort by distance from core layer to put dim lines in order
  local tblLayersSort, k, v, x, y, z
  
  tblLayersSort={}
  i=0
  for k,v in pairs(tblLayers) do
    i=i+1
    tblLayersSort[i]=v
    tblLayersSort[i].typetag=k

    x=v.elem.q.geo.orig.x - tblCore.elem.q.geo.orig.x
    y=v.elem.q.geo.orig.y - tblCore.elem.q.geo.orig.y
    z=v.elem.q.geo.orig.z - tblCore.elem.q.geo.orig.z
    tblLayersSort[i].dist=CalcDot3D(tblCam.vecx.x, tblCam.vecx.y, tblCam.vecx.z, x, y, z)
--ac_environment("tolog", string.format("%s, dist=%f", k, tblLayersSort[i].dist))
  end

  table.sort(tblLayersSort, function (n1, n2)
    return n1.dist<n2.dist
  end)

  -- Find core (always found)
  local coreInd
  
  for i,v in ipairs(tblLayersSort) do
    if v.typetag=="core" then
      coreInd=i
      break
    end
  end
  
  local sdim
  
  sdim="elemvecy=\"1\""
  if math.abs(CalcDot3D(tblCore.elem.q.geo.vecx.x, tblCore.elem.q.geo.vecx.y, tblCore.elem.q.geo.vecx.z, tblCam.vecy.x, tblCam.vecy.y, tblCam.vecy.z))>0.999 then
    sdim="elemvecx=\"1\""
  elseif math.abs(CalcDot3D(tblCore.elem.q.geo.vecz.x, tblCore.elem.q.geo.vecz.y, tblCore.elem.q.geo.vecz.z, tblCam.vecy.x, tblCam.vecy.y, tblCam.vecy.z))>0.999 then
    sdim="elemvecz=\"1\""
  end
  
  return tblLayersSort, coreInd, sdim
end


function DoSectDimLayer(vlayer, side, marg, tblDims, ndims, tblCore, dimdir)
  local name, s

  s=vlayer.elem.q.tblelems[1].templateid
  name=GetNameForTypetag(vlayer.typetag)
  if vlayer.typetag=="core" or string.match(s, "airstrips_hor") or string.match(s, "^framinghor.*") or string.match(s, "^horpanel.*") then
    ndims=AddHorPieces(tblDims, ndims, vlayer.typetag, side, marg, dimdir)
  else
    ndims=FindLayerSizeAndOff(tblCore, tblDims, ndims, vlayer.typetag, string.format("<dimline side=\"%s\" margin=\"%0.2f\" %s %s>", side, marg, dimdir, gDimExtraAttr), name)
  end
    
  return ndims
end


-- Creates all dim lines for section
-- spaceL,R if given, tells how much space is needed to left/right hand side of the dim line, default L=0.2, r=0.1
-- spaceDims How much to leave between dim lines
function SectDimLines(strExtraSettings, strExtraAttr, spaceL, spaceR, spaceDims)
  local tblDims, ndims, name, tblCore
  local tblLayers, coreInd, nLayers, nleft, i, marg, v, dimdir
  local tblCam=af_request("dim_camera")
  
  if not spaceL then
    spaceL=0.2
    spaceR=0.1
    spaceDims=0.15
  end
  
  gDimExtraSettings=""
  if strExtraSettings then
    gDimExtraSettings=strExtraSettings
  end
  gDimExtraAttr=""
  if strExtraAttr then
    gDimExtraAttr=strExtraAttr
  end
  
  -- Get table of all layers in our composite
  tblLayers,coreInd,dimdir=FindElemLayers(tblCam)
  nLayers=#tblLayers

  -- Get core section
  tblCore=af_request("dim_section", "core")
  SortDimSectVert(tblCore)

  -- Add dim lines 
  ndims=0
  tblDims={}

  nleft=coreInd-1
  if nLayers-coreInd>nleft then
    nleft=coreInd     -- Core dim to the left side
  end

  marg=spaceR
  i=nleft
  while i>0 do
    ndims=DoSectDimLayer(tblLayers[i], "left", marg, tblDims, ndims, tblCore, dimdir)
    i=i-1
    marg=spaceDims
  end

  marg=spaceL
  i=nleft+1
  while i<=nLayers do
    ndims=DoSectDimLayer(tblLayers[i], "right", marg, tblDims, ndims, tblCore, dimdir)
    i=i+1
    marg=spaceDims
  end
  
  -- Max height
  local tblSect=af_request("dim_section", "*")
  local botx,boty, topx,topy
  
  for i,v in ipairs(tblSect) do
    if not boty or v.bottom_maxy<boty then
      botx=v.bottom_maxx
      boty=v.bottom_maxy
    end
      
    if not topy or v.top_maxy>topy then
      topx=v.top_maxx
      topy=v.top_maxy
    end
  end

  if botx then
    s=string.format("<dimline side=\"right\" margin=\"%0.2f\" %s %s>\n", marg, dimdir, gDimExtraAttr)
    s=s..gDimExtraSettings
    s=s.."</dimline>"
    t={}
    t.xmldim=s
    t.dimpoints={}
    
    v={}
    v.x=botx
    v.y=boty
    t.dimpoints[1]=v
--ac_environment("tolog", string.format("1: v.x=%s v.y=%s", tostring(v.x), tostring(v.y)))
    v={}
    v.x=topx
    v.y=topy
    t.dimpoints[2]=v
--ac_environment("tolog", string.format("2: v.x=%s v.y=%s", tostring(v.x), tostring(v.y)))

    ndims=ndims+1
    tblDims[ndims]=t
  end

  return tblDims
end


-- Dim lines cumulative (Scandicc uses)
function SectDimLinesCum()
  --return SectDimLines("<dimlinesettings><elemparam name=\"dimensiontype\">cumulative</elemparam><elemparam name=\"markertype\">5</elemparam></dimlinesettings>", " textrot=\"0.001\"", 0.1, 0.4, 0.4)
  return SectDimLines("<dimlinesettings><elemparam name=\"dimensiontype\">cumulative</elemparam><elemparam name=\"markertype\">5</elemparam></dimlinesettings>", nil, 0.35, 0.1, 0.15)
end

]]>
        </script>
        <!-- DIM SCRIPTS END-->
      </scripts>
    </settings>

    <elemtypes>
      <elemtype class="wall" id="WALL 100 C/C 600" idstamp="50x100">
        <!-- Default settings for this element type -->
        <settings>
          <newelem>
            <objparam name="iShowElemType">0</objparam>
          </newelem>

          <newelemplank>
            <objparam name="iShowID3D">0</objparam>
          </newelemplank>

          <newelemprojside>
          </newelemprojside>
        </settings>

        <layers>
          <layer name="Core" visible="1" thickness="0.100" type="core" anchorname1="Core out" anchorname2="Core in">

            <!-- Group name will have suffixes: _y=vertical planks, _x=horizontal planks -->
            <!-- Group names can be used for example to make grooves for balks and groups may be referred using wild cards: vertical* -->

            <!-- bottom wood -->
            <planks group="bottom" axis="x" skipaxis="1">
              <material id="50x100" zoff="0" rotangle="0"></material>
              <force>
                <parallel x2off="-mat_thickness*0.5"></parallel>
              </force>
            </planks>

            <!-- Top -->
            <planks group="top" axis="x" skipaxis="1">
              <material id="50x100" zoff="0" rotangle="0"></material>
              <force>
                <parallel x1off="mat_thickness*0.5"></parallel>
              </force>
            </planks>

            <planks group="vertical" axis="y" opening_parallel="1" opening_normal="1" spacing="0.6" spacingtolerance="0.01">
              <material id="50x100" zoff="0" rotangle="0"></material>
            </planks>
            
            <!-- Every other, axis=unused means every edge not handled in previous rules. Added planks for openings will not cut the studs and will have group suffix _opening -->
            <planks group="contourtilted" axis="unused" contour_unused="1" opening_unused="1">
              <material id="50x100" zoff="0" rotangle="0"></material>
            </planks>

            <script ref="setcolours"></script>

            <operations>
              <jointo target="vertical_y*|vertical_spacing|vertical_force" operator="bottom*|top*|vertical_x|contourtilted">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- Trim to tilted openings -->
              <jointo target="vertical_y*|vertical_spacing|vertical_force" operator="contourtilted_opening">
                <cut conntype="endtoline" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
              <jointo target="vertical_y*|vertical_spacing|vertical_force" operator="contourtilted_opening">
                <cut conntype="linex" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- groove operator is the piece that makes the groove, target is here the the piece that gets the groove -->
              <groove target="vertical_y*|vertical_spacing|vertical_force" operator="balktop*">
                <groove overtop="0.000" overbot="0.001" overside="0.000"></groove>
              </groove>
              <!--markingto target="vertical*" operator="bottom*" type="lines_sides" text=""></markingto>-->
            </operations>

          </layer>
        </layers>

        <!-- Projections for the element inside one frame from top to bottom -->
        <projections>
          <group layout="horizontal">
            <group layout="vertical">
              <!-- Only planks belonging to the element are included in cutlist -->
              <!-- layoutalign: -1=left/bottom, 0=center, 1=right/top -->
              <!-- cutlist attribute elemid="0"/"1", includes element id in the cut list (1) or not (0) -->
              <cutlist layoutalign="-1" layoutmargins="0.1,0.1,0.1,0.1" layoutminwidth="2.0" layoutminheight="7.0" settingsref="cutlist" elemid="0"></cutlist>
            </group>
            <group layout="vertical">
              <projection type="front" layoutmargins="2,0.5,1,1">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
                <elemmarkings>
                  <opening ref="mark_opening"></opening>
                </elemmarkings>
              </projection>
              <projection type="top" layoutmargins="2,0.5,0,1">
                <dimlines>
                  <dimline ref="wall_top"></dimline>
                </dimlines>
              </projection>
              <elemstamp layoutalign="-1" layoutmargins="-2.2,0,0,0" layoutminwidth="10.0" layoutminheight="1.0" libname="{9FD03D30-6A12-4B0F-AB3A-01410A529E38}-{D420792D-C066-42CF-988C-9596DD164EB7}" settingsref="elemstamp">
                <script ref="elemstamp"></script>
              </elemstamp>
            </group>
          </group>
        </projections>

        <!--markings ref="mark_default">
        </markings-->
      </elemtype>


      <elemtype class="wall" id="WALL 173 K600" idstamp="42x173">
        <!-- Default settings for this element type -->
        <settings>
          <newelem>
            <elemparam name="pen">1</elemparam>
          </newelem>

          <newelemplank>
          </newelemplank>

          <newelemprojside>
          </newelemprojside>
        </settings>

        <!-- Could set some options on here as default, settings may be given in side <option>settings</option> and format depends on the option -->
        <!--options>
          <option id="openingsides">
            <![CDATA[
mat=block
thickness=0.050
height=0.173
]]>
          </option>
        </options-->

        <layers>
          <layer name="Core" visible="1" thickness="0.173" type="core" anchorname1="Core out" anchorname2="Core in">

            <!-- Group name will have suffixes: _y=vertical planks, _x=horizontal planks -->
            <!-- Group names can be used for example to make grooves for balks and groups may be referred using wild cards: vertical* -->

            <!-- bottom wood -->
            <planks group="bottom" axis="x" skipaxis="1">
              <material id="42x173" zoff="0" rotangle="0"></material>
              <force>
                <parallel x2off="-mat_thickness*0.5"></parallel>
              </force>
            </planks>

            <!-- Top -->
            <planks group="top" axis="x" skipaxis="1">
              <material id="42x173" zoff="0" rotangle="0"></material>
              <force>
                <parallel x1off="mat_thickness*0.5"></parallel>
              </force>
            </planks>

            <planks group="vertical" axis="y" opening_parallel="1" opening_normal="1" spacing="0.6" spacingtolerance="0.01">
              <material id="42x173" zoff="0" rotangle="0"></material>
              <force_nope>
                <!-- parallel|normal, x1off refers to left side of axis, x2off to right side of the axis. Only the line that does not have anything in element polygon to offset direction is handled. -->
                <!-- extend extends the forced planks to outline polygon (to be cut later with top&bottom wood) -->
                <parallel x1off="0.141" extend="1"></parallel>
                <parallel x2off="-0.141" extend="1"></parallel>
              </force_nope>
            </planks>

            <!-- Every other, axis=unused means every edge not handled in previous rules. Added planks for openings will not cut the studs and will have group suffix _opening -->
            <planks group="contourtilted" axis="unused" contour_unused="1" opening_unused="1">
              <material id="42x173" zoff="0" rotangle="0"></material>
            </planks>

            <script ref="setcolours"></script>

            <operations>
              <jointo target="vertical_y*|vertical_spacing|vertical_force" operator="bottom*|top*|vertical_x|contourtilted">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- Trim to tilted openings -->
              <jointo target="vertical_y*|vertical_spacing|vertical_force" operator="contourtilted_opening">
                <cut conntype="endtoline" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
              <jointo target="vertical_y*|vertical_spacing|vertical_force" operator="contourtilted_opening">
                <cut conntype="linex" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- groove operator is the piece that makes the groove, target is here the the piece that gets the groove -->
              <groove target="vertical_y*|vertical_spacing|vertical_force" operator="balktop*">
                <groove overtop="0.000" overbot="0.001" overside="0.000"></groove>
              </groove>
              <!--markingto target="vertical*" operator="bottom*" type="lines_sides" text=""></markingto>-->
            </operations>

          </layer>
        </layers>

        <!-- Projections for the element inside one frame from top to bottom -->
        <projections>
          <group layout="horizontal">
            <group layout="vertical">
              <!-- Only planks belonging to the element are included in cutlist -->
              <!-- layoutalign: -1=left/bottom, 0=center, 1=right/top -->
              <!-- cutlist attribute elemid="0"/"1", includes element id in the cut list (1) or not (0) -->
              <cutlist layoutalign="-1" layoutmargins="0.1,0.1,0.1,0.1" layoutminwidth="2.0" layoutminheight="7.0" settingsref="cutlist" elemid="0"></cutlist>
            </group>
            <group layout="vertical">
              <projection type="front" layoutmargins="2,0.5,1,1">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
                <elemmarkings>
                  <opening ref="mark_opening"></opening>
                </elemmarkings>
              </projection>
              <projection type="top" layoutmargins="2,0.5,0,1">
                <dimlines>
                  <dimline ref="wall_top"></dimline>
                </dimlines>
              </projection>
              <!--projection type="back" layoutmargins="2,2,0,2">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
              </projection-->
              <elemstamp layoutalign="-1" layoutmargins="-2.2,0,0,0" layoutminwidth="10.0" layoutminheight="1.0" libname="{9FD03D30-6A12-4B0F-AB3A-01410A529E38}-{D420792D-C066-42CF-988C-9596DD164EB7}" settingsref="elemstamp">
                <script ref="elemstamp"></script>
              </elemstamp>
            </group>
          </group>
        </projections>

        <!--markings ref="mark_default">
        </markings-->
      </elemtype>


      <elemtype class="wall" id="WALL 42x42 HOR" idstamp="42x42">
        <!-- Default settings for this element type -->
        <settings>
          <newelem>
          </newelem>

          <newelemplank>
          </newelemplank>

          <newelemprojside>
          </newelemprojside>
        </settings>

        <layers>
          <layer name="Core" visible="1" thickness="0.042" type="core" anchorname1="Out" anchorname2="In">

            <!-- Top/bottom -->
            <planks group="bottom" axis="y" skipaxis="1">
              <material id="42x42" zoff="0" rotangle="0"></material>
              <force>
                <parallel x2off="-mat_thickness*0.5"></parallel>
              </force>
            </planks>

            <!-- Top -->
            <planks group="top" axis="y" skipaxis="1">
              <material id="42x42" zoff="0" rotangle="0"></material>
              <force>
                <parallel x1off="mat_thickness*0.5"></parallel>
              </force>
            </planks>

            <!-- Group name will have suffixes: _y=vertical planks, _x=horizontal planks -->
            <!-- Group names can be used for example to make grooves for balks and groups may be referred using wild cards: vertical* -->
            <planks group="vertical" axis="x" opening_parallel="1" opening_normal="1" spacing="0.6" spacingtolerance="0.01">
              <material id="42x42" zoff="0" rotangle="0"></material>
              <force_unused>
                <!-- parallel|normal, x1off refers to left side of axis, x2off to right side of the axis. Only the line that does not have anything in element polygon to offset direction is handled. -->
                <!-- extend extends the forced planks to outline polygon (to be cut later with top&bottom wood) -->
                <parallel x1off="0.141" extend="1"></parallel>
                <parallel x2off="-0.141" extend="1"></parallel>
              </force_unused>
            </planks>

            <!-- Every other, axis=unused means every edge not handled in previous rules. Added planks for openings will not cut the studs and will have group suffix _opening -->
            <planks group="contourtilted" axis="unused" contour_unused="1" opening_unused="0">
              <material id="42x42" zoff="0" rotangle="0"></material>
            </planks>

            <script ref="setcolours"></script>

            <operations>
              <jointo target="vertical_x|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="bottom*|top*|vertical_y|contourtilted">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- Trim to tilted openings -->
              <jointo target="vertical_x|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="endtoline" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
              <jointo target="vertical_x|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="linex" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- groove operator is the piece that makes the groove, target is here the the piece that gets the groove -->
              <groove target="vertical_x|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="balktop*">
                <groove overtop="0.000" overbot="0.001" overside="0.000"></groove>
              </groove>
              <!--markingto target="vertical*" operator="bottom*" type="lines_sides" text=""></markingto>-->
            </operations>

          </layer>
        </layers>

        <!-- Projections for the element inside one frame from top to bottom -->
        <projections>
          <group layout="horizontal">
            <group layout="vertical">
              <!-- Only planks belonging to the element are included in cutlist -->
              <!-- layoutalign: -1=left/bottom, 0=center, 1=right/top -->
              <!-- cutlist attribute elemid="0"/"1", includes element id in the cut list (1) or not (0) -->
              <cutlist layoutalign="-1" layoutmargins="0.1,0.1,0.1,0.1" layoutminwidth="2.0" layoutminheight="7.0" settingsref="cutlist" elemid="0"></cutlist>
            </group>
            <group layout="vertical">
              <projection type="front" layoutmargins="2,0.5,1,1">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
                <elemmarkings>
                  <opening ref="mark_opening"></opening>
                </elemmarkings>
              </projection>
              <projection type="top" layoutmargins="2,0.5,0,1">
                <dimlines>
                  <dimline ref="wall_top"></dimline>
                </dimlines>
              </projection>
              <!--projection type="back" layoutmargins="2,2,0,2">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
              </projection-->
              <elemstamp layoutalign="-1" layoutmargins="-2.2,0,0,0" layoutminwidth="10.0" layoutminheight="1.0" libname="{9FD03D30-6A12-4B0F-AB3A-01410A529E38}-{D420792D-C066-42CF-988C-9596DD164EB7}" settingsref="elemstamp">
                <script ref="elemstamp"></script>
              </elemstamp>
            </group>
          </group>
        </projections>

        <!--markings ref="mark_default">
        </markings-->
      </elemtype>


      <elemtype class="wall" id="WALL 42x42 VERT" idstamp="42x42">
        <!-- Default settings for this element type -->
        <settings>
          <newelem>
            <objparam name="iShowElemType">0</objparam>
          </newelem>

          <newelemplank>
            <objparam name="iShowID3D">0</objparam>
          </newelemplank>

          <newelemprojside>
          </newelemprojside>
        </settings>

        <layers>
          <layer name="Core" visible="1" thickness="0.042" type="core" anchorname1="Core out" anchorname2="Core in">

            <!-- Group name will have suffixes: _y=vertical planks, _x=horizontal planks -->
            <!-- Group names can be used for example to make grooves for balks and groups may be referred using wild cards: vertical* -->

            <!-- bottom wood -->
            <planks group="bottom" axis="x" skipaxis="1">
              <material id="42x42" zoff="0" rotangle="0"></material>
              <force>
                <parallel x2off="-mat_thickness*0.5"></parallel>
              </force>
            </planks>

            <!-- Top -->
            <planks group="top" axis="x" skipaxis="1">
              <material id="42x42" zoff="0" rotangle="0"></material>
              <force>
                <parallel x1off="mat_thickness*0.5"></parallel>
              </force>
            </planks>

            <planks group="vertical" axis="y" opening_parallel="1" opening_normal="1" spacing="0.6" spacingtolerance="0.01">
              <material id="42x42" zoff="0" rotangle="0"></material>
            </planks>

            <!-- Every other, axis=unused means every edge not handled in previous rules. Added planks for openings will not cut the studs and will have group suffix _opening -->
            <planks group="contourtilted" axis="unused" contour_unused="1" opening_unused="1">
              <material id="42x42" zoff="0" rotangle="0"></material>
            </planks>

            <script ref="setcolours"></script>

            <operations>
              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="bottom*|top*|vertical_x|contourtilted">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- Trim to tilted openings -->
              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="endtoline" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="linex" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- groove operator is the piece that makes the groove, target is here the the piece that gets the groove -->
              <groove target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="balktop*">
                <groove overtop="0.000" overbot="0.001" overside="0.000"></groove>
              </groove>
              <!--markingto target="vertical*" operator="bottom*" type="lines_sides" text=""></markingto>-->
            </operations>

          </layer>
        </layers>

        <!-- Projections for the element inside one frame from top to bottom -->
        <projections>
          <group layout="horizontal">
            <group layout="vertical">
              <!-- Only planks belonging to the element are included in cutlist -->
              <!-- layoutalign: -1=left/bottom, 0=center, 1=right/top -->
              <!-- cutlist attribute elemid="0"/"1", includes element id in the cut list (1) or not (0) -->
              <cutlist layoutalign="-1" layoutmargins="0.1,0.1,0.1,0.1" layoutminwidth="2.0" layoutminheight="7.0" settingsref="cutlist" elemid="0"></cutlist>
            </group>
            <group layout="vertical">
              <projection type="front" layoutmargins="2,0.5,1,1">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
                <elemmarkings>
                  <opening ref="mark_opening"></opening>
                </elemmarkings>
              </projection>
              <projection type="top" layoutmargins="2,0.5,0,1">
                <dimlines>
                  <dimline ref="wall_top"></dimline>
                </dimlines>
              </projection>
              <!--projection type="back" layoutmargins="2,2,0,2">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
              </projection-->
              <elemstamp layoutalign="-1" layoutmargins="-2.2,0,0,0" layoutminwidth="10.0" layoutminheight="1.0" libname="{9FD03D30-6A12-4B0F-AB3A-01410A529E38}-{D420792D-C066-42CF-988C-9596DD164EB7}" settingsref="elemstamp">
                <script ref="elemstamp"></script>
              </elemstamp>
            </group>
          </group>
        </projections>

        <!--markings ref="mark_default">
        </markings-->
      </elemtype>

      
      <!-- MULTILAYER BEG -->

      <!-- Used only as part of other elements -->
      <elemtype class="wall" id="GYPSUM 9" idstamp="BOARD 9" tolist="0" density="1.1">
        <!-- Default settings for this element type -->
        <layers>
          <boarding thickness="0.009" type="core" anchorname1="Out" anchorname2="In">
            <board id="GYP 1200x2600x9" name="GYP 1200x2600x9" name_fin="Kipsi 1200x2600x9" width="1.2" height="2.6"></board>
            <!-- cost is slightly higher than area 0.6*2.6=1.56 -->
            <board id="GYP 600x2600x9" name="GYP 600x2600x9" name_fin="Kipsi 600x2600x9" width="0.6" height="2.6" cost="1.8"></board>
          </boarding>
        </layers>
      </elemtype>

      <!-- Used only as part of other elements -->
      <elemtype class="wall" id="GYPSUM 13" idstamp="BOARD 13" tolist="0" density="1.1">
        <!-- Default settings for this element type -->
        <layers>
          <boarding thickness="0.013" type="core" anchorname1="Out" anchorname2="In">
            <board id="GYP 1200x2600x13" name="GYP 1200x2600x13" name_fin="Kipsi 1200x2600x13" width="1.2" height="2.6"></board>
            <!-- cost is slightly higher than area 0.6*2.6=1.56 -->
            <board id="GYP 600x2600x13" name="GYP 600x2600x13" name_fin="Kipsi 600x2600x13" width="0.6" height="2.6" cost="1.8"></board>
          </boarding>
        </layers>
      </elemtype>

      <!-- Multilayer element -->
      <elemtype class="wall" id="WALL 173+42 VERT" idstamp="173+42">
        <settings>
          <masterelem>
            <objparam name="iShowElemType">1</objparam>
            <objparam name="iShowID2D">1</objparam>
            <objparam name="iShowID3D">1</objparam>
          </masterelem>
          <slaveelem>
            <objparam name="iShowElemType">0</objparam>
            <objparam name="iShowID2D">0</objparam>
            <objparam name="iShowID3D">0</objparam>
          </slaveelem>
        </settings>

        <layers>
          <!-- spacepre=empty space before the layer (for unmodeled parts of the structure) -->
          <boarding ref="GYPSUM 9" anchorname1="Windshield ext" anchorname1_fin="Tuulensuoja ulko" type="boarding_ext" studs="core" spacepre="0">
          </boarding>
          <layer ref="WALL 173 K600" anchorname1="Core ext" anchorname2="Core int" anchorname1_fin="Runko ulko" anchorname2_fin="Runko sisä" type="core">
          </layer>
          <layer ref="WALL 42x42 VERT" anchorname2="Inner studding int" anchorname2_fin="Sisäkoolaus sisä" studs="core" type="intstud">
          </layer>
          <boarding ref="GYPSUM 13" anchorname2="Boarding int" anchorname2_fin="Levytys sisä" type="boarding_int" studs="intstud" spacepre="0">
          </boarding>
        </layers>

        <!-- Projections for the element inside one frame from top to bottom -->
        <projections>
          <group layout="horizontal">
            <group layout="vertical">
              <!-- Only planks belonging to the element are included in cutlist -->
              <!-- layoutalign: -1=left/bottom, 0=center, 1=right/top -->
              <!-- cutlist attribute elemid="0"/"1", includes element id in the cut list (1) or not (0) -->
              <cutlist layoutalign="-1" layoutmargins="0.1,0.1,0.1,0.1" layoutminwidth="2.0" layoutminheight="7.0" settingsref="cutlist" elemid="0"></cutlist>
            </group>
            <group layout="vertical">
              <projection type="front" layoutmargins="2,0.5,1,1" boardpanels="boarding_ext" exclude="intstud,extstud">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
                <elemmarkings>
                  <opening ref="mark_opening"></opening>
                </elemmarkings>
              </projection>
              <projection type="top" layoutmargins="2,0.5,0,1" boardpanels="boarding_int,boarding_ext">
                <dimlines>
                  <dimline ref="wall_top"></dimline>
                </dimlines>
              </projection>
              <projection type="back" layoutmargins="2,0.5,0,1" boardpanels="boarding_int" exclude="core,extstud">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
                <elemmarkings>
                  <opening ref="mark_opening"></opening>
                </elemmarkings>
              </projection>
              <elemstamp layoutalign="-1" layoutmargins="-2.2,0,0,0" layoutminwidth="10.0" layoutminheight="1.0" libname="{9FD03D30-6A12-4B0F-AB3A-01410A529E38}-{D420792D-C066-42CF-988C-9596DD164EB7}" settingsref="elemstamp">
                <script ref="elemstamp"></script>
              </elemstamp>
            </group>
          </group>
        </projections>

      </elemtype>



      <!-- Full panel wall -->
      <elemtype class="wall" id="PANEL_HOR_OUTIN" idstamp="PANEL_HOR_OUTIN" tolist="0" density="0.5">
        <!-- Default settings for this element type -->
        <settings>
          <newelemboard>
            <layer>AF Panel</layer>
          </newelemboard>
          <newelemboardprojside>
            <objparam name="iFill">0</objparam>
          </newelemboardprojside>
        </settings>
        <layers>
          <boarding thickness="0.023" type="core" anchorname2="Paneling ext">
            <board panelingref="PANEL_HOR_OUTIN" width="9999" height="9999" >
            </board>
          </boarding>
        </layers>
      </elemtype>

      <!-- External studding -->
      <elemtype class="wall" id="STUDDING20" tolist="0" density="0">
        <layers>
          <layer name="Core" visible="1" thickness="0.020" type="core" anchorname1="Core out" anchorname2="Core in">
            <planks group="vertical" axis="y" opening_parallel="1" opening_normal="0" spacing="0.6" spacingtolerance="0.01">
              <material id="20x70" zoff="mat_thickness*0.5" rotangle="90"></material>
            </planks>
          </layer>
        </layers>
      </elemtype>


      <elemtype class="wall" id="WALL 173+42 PANEL OUTIN" idstamp="173+42">
        <settings>
          <masterelem>
            <objparam name="iShowElemType">1</objparam>
            <objparam name="iShowID2D">1</objparam>
            <objparam name="iShowID3D">1</objparam>
          </masterelem>
          <slaveelem>
            <objparam name="iShowElemType">0</objparam>
            <objparam name="iShowID2D">0</objparam>
            <objparam name="iShowID3D">0</objparam>
          </slaveelem>
        </settings>

        <!-- Default element weights for this type -->
        <elemweight>
          <bools calc="0" door="1" win="1"></bools>
          <floats framingkg="400" boardingkg="1150" insulationkg="35" doorm2kg="10" doorframekg="4" winm2kg="15" winframekg="4"></floats>
        </elemweight>

        <layers>
          <boarding ref="PANEL_HOR_OUTIN" anchorname1="Exterior finishing ext" anchorname1_fin="Panelointi ulko" type="finish_ext" studs="extstud" spacepre="0">
          </boarding>
          <layer ref="STUDDING20" anchorname1="Exterior studding ext" anchorname1_fin="Ulkokoolaus ulko" studs="core" type="extstud">
          </layer>
          <boarding ref="GYPSUM 9" anchorname1="Windshield ext" anchorname1_fin="Tuulensuoja ulko" type="boarding_ext" studs="core" spacepre="0">
          </boarding>
          <layer ref="WALL 173 K600" anchorname1="Core ext" anchorname2="Core int" anchorname1_fin="Runko ulko" anchorname2_fin="Runko sisä" type="core">
          </layer>
          <layer ref="WALL 42x42 VERT" anchorname2="Inner studding int" anchorname2_fin="Sisäkoolaus sisä" studs="core" type="intstud">
          </layer>
          <!--layer ref="WALL 42x42 HOR" anchorname2="Inner studding int" anchorname2_fin="Sisäkoolaus sisä" studs="core" type="intstud">
          </layer-->
          <boarding ref="GYPSUM 13" anchorname2="Boarding int" anchorname2_fin="Levytys sisä" type="boarding_int" studs="intstud" spacepre="0">
          </boarding>
        </layers>

        <!-- Projections for the element inside one frame from top to bottom -->
        <projections>
          <group layout="horizontal">
            <group layout="vertical">
              <!-- Only planks belonging to the element are included in cutlist -->
              <!-- layoutalign: -1=left/bottom, 0=center, 1=right/top -->
              <!-- cutlist attribute elemid="0"/"1", includes element id in the cut list (1) or not (0) -->
              <cutlist layoutalign="-1" layoutmargins="0.1,0.1,0.1,0.1" layoutminwidth="2.0" layoutminheight="7.0" settingsref="cutlist" elemid="0"></cutlist>
            </group>
            <group layout="vertical">
              <projection type="front" layoutmargins="2,0.5,1,1" boardpanels="finish_ext,boarding_ext" exclude="intstud,extstud">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
                <elemmarkings>
                  <opening ref="mark_opening"></opening>
                  <weight libname="{FD6C137D-C647-42FD-A904-181281909443}-{9060078A-0F41-48C8-8400-8E414A838053}" create="1" text="(weight) KG" units="kg">
                    <settings>
                      <layer>[layer_weight;type=layer]</layer>
                      <objparam name="iFill">*25*</objparam>
                      <objparam name="A">0.250</objparam>
                      <objparam name="B">0.325</objparam>
                    </settings>
                  </weight>
                </elemmarkings>
              </projection>
              <projection type="top" layoutmargins="2,0.5,0,1" boardpanels="boarding_int,boarding_ext,finish_ext">
                <dimlines>
                  <dimline ref="wall_top"></dimline>
                </dimlines>
              </projection>
              <projection type="back" layoutmargins="2,0.5,0,1" boardpanels="boarding_int" exclude="core,extstud">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
                <elemmarkings>
                  <opening ref="mark_opening"></opening>
                </elemmarkings>
              </projection>
              <elemstamp layoutalign="-1" layoutmargins="-2.2,0,0,0" layoutminwidth="10.0" layoutminheight="1.0" libname="{9FD03D30-6A12-4B0F-AB3A-01410A529E38}-{D420792D-C066-42CF-988C-9596DD164EB7}" settingsref="elemstamp">
                <script ref="elemstamp"></script>
              </elemstamp>
            </group>
          </group>
        </projections>
      </elemtype>

      <!-- MULTILAYER END -->
      

      <elemtype class="floor" id="FLOOR 300 C/C 300 BORDER" idstamp="300">

        <layers>
          <layer name="Core" visible="1" thickness="0.300" type="core" anchorname1="Top" anchorname2="Bottom">

            <planks group="contour" axis="y" extend="0">
              <material id="block" zoff="0" rotangle="0" thickness="0.025" height="0.300"></material>
            </planks>

            <planks group="contour" axis="x" extend="0">
              <material id="block" zoff="0" rotangle="0" thickness="0.025" height="0.300"></material>
            </planks>

            <!-- Group name will have suffixes: _y=vertical planks, _x=horizontal planks -->
            <!-- Group names can be used for example to make grooves for balks and groups may be referred using wild cards: vertical* -->
            <planks group="vertical" axis="y" skipaxis="1" opening_parallel="1" opening_normal="1" spacing="0.3" spacingtolerance="0.05">
              <material id="I 300" zoff="0" rotangle="0"></material>
              <force>
                <!-- parallel|normal, x1off refers to left side of axis, x2off to right side of the axis. Only the line that does not have anything in element polygon to offset direction is handled. -->
                <!-- extend extends the forced planks to outline polygon (to be cut later with top&bottom wood) -->
                <parallel x1off="0.500" extend="1" handleto1="-0.500">
                  <planks1 group="sideleft" axis="x" spacing="0.3" spacingtolerance="0.05">
                    <material id="I 300" zoff="0" rotangle="0"></material>
                  </planks1>
                </parallel>

                <parallel x2off="-0.500" extend="1" handleto1="0.500">
                  <planks1 group="sideright" axis="x" spacing="0.3" spacingtolerance="0.05">
                    <material id="I 300" zoff="0" rotangle="0"></material>
                  </planks1>
                </parallel>
              </force>
            </planks>

            <planks group="contourtilted" axis="unused" contour_unused="1" opening_unused="1">
              <material id="block" zoff="0" rotangle="0" thickness="0.025" height="0.300"></material>
            </planks>

            <script ref="setcolours"></script>

            <operations>
              <!-- Extend y at inner corners -->
              <jointo target="contour_y" operator="contour_x">
                <cut maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.001" expandopfind="0.001" toend="1"></cut>
              </jointo>

              <!-- Contour y longer -->
              <jointo target="contour_x" operator="contour_y">
                <cut conntype="hasx" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="vertical_x|contour*">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- Trim to holes -->
              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="hasx" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- Trim sides -->
              <jointo target="sideleft*|sideright*" operator="vertical*|contour*">
                <cut conntype="hasx" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
            </operations>

          </layer>
          <!--layer name="Insulation" visible="0" thickness="0.050"></layer-->
          <!--layer name="Vertical studding in" visible="0" thickness="0.022" anchorname1="Vertical studding in"></layer-->
          <!--layer name="Plasterboard" visible="0" thickness="0.013" anchorname2="Plasterboard in"></layer-->
        </layers>

        <!-- No projections at all (no dim lines etc), change tag name projections_nope to projections to have projections. ALSO THE END TAG -->
        <projections_nope>
          <group layout="horizontal">
            <group layout="vertical">
              <!-- Only planks belonging to the element are included in cutlist -->
              <!-- layoutalign: -1=left/bottom, 0=center, 1=right/top -->
              <cutlist layoutalign="-1" layoutmargins="0.1,0.1,0.1,0.1" layoutminwidth="2.0" layoutminheight="7.0" settingsref="cutlist" elemid="0"></cutlist>
            </group>
            <group layout="vertical">
              <projection type="front" layoutmargins="2,2,2,2">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
                <elemmarkings>
                  <opening ref="mark_opening"></opening>
                </elemmarkings>
              </projection>
              <projection type="top" layoutmargins="2,2,0,2">
                <dimlines>
                  <dimline ref="wall_top"></dimline>
                </dimlines>
              </projection>
              <projection type="back" layoutmargins="2,2,0,2">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
              </projection>
            </group>
          </group>
        </projections_nope>

        <!--markings ref="mark_default">
        </markings-->
      </elemtype>


      <elemtype class="floor" id="FLOOR 300 C/C 300" idstamp="300">
        <layers>
          <layer name="Core" visible="1" thickness="0.300" type="core" anchorname1="Top" anchorname2="Bottom">

            <!-- Group name will have suffixes: _y=vertical planks, _x=horizontal planks -->
            <!-- Group names can be used for example to make grooves for balks and groups may be referred using wild cards: vertical* -->
            <planks group="vertical" axis="y" skipaxis="0" opening_parallel="1" opening_normal="1" spacing="0.3" spacingtolerance="0.05">
              <material id="I 300" zoff="0" rotangle="0"></material>
              <force_nope>
                <!-- parallel|normal, x1off refers to left side of axis, x2off to right side of the axis. Only the line that does not have anything in element polygon to offset direction is handled. -->
                <!-- extend extends the forced planks to outline polygon (to be cut later with top&bottom wood) -->
                <parallel x1off="0.500" extend="1" handleto1="-0.500">
                  <planks1 group="sideleft" axis="x" spacing="0.3" spacingtolerance="0.05">
                    <material id="I 300" zoff="0" rotangle="0"></material>
                  </planks1>
                </parallel>

                <parallel x2off="-0.500" extend="1" handleto1="0.500">
                  <planks1 group="sideright" axis="x" spacing="0.3" spacingtolerance="0.05">
                    <material id="I 300" zoff="0" rotangle="0"></material>
                  </planks1>
                </parallel>
              </force_nope>
            </planks>

            <planks group="contourtilted" axis="unused" contour_unused="0" opening_unused="1">
              <material id="block" zoff="0" rotangle="0" thickness="0.025" height="0.300"></material>
            </planks>

            <script ref="setcolours"></script>

            <operations>
              <!-- Extend y at inner corners -->
              <jointo target="contour_y" operator="contour_x">
                <cut maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.001" expandopfind="0.001" toend="1"></cut>
              </jointo>

              <!-- Contour y longer -->
              <jointo target="contour_x" operator="contour_y">
                <cut conntype="hasx" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="vertical_x|contour*">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- Trim to holes -->
              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="hasx" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- Trim sides -->
              <jointo target="sideleft*|sideright*" operator="vertical*|contour*">
                <cut conntype="hasx" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
            </operations>

          </layer>
          <!--layer name="Insulation" visible="0" thickness="0.050"></layer-->
          <!--layer name="Vertical studding in" visible="0" thickness="0.022" anchorname1="Vertical studding in"></layer-->
          <!--layer name="Plasterboard" visible="0" thickness="0.013" anchorname2="Plasterboard in"></layer-->
        </layers>

        <!-- No projections at all (no dim lines etc), change tag name projections_nope to projections to have projections. ALSO THE END TAG -->
        <projections>
          <group layout="horizontal">
            <group layout="vertical">
              <!-- Only planks belonging to the element are included in cutlist -->
              <!-- layoutalign: -1=left/bottom, 0=center, 1=right/top -->
              <!-- cutlist attribute elemid="0"/"1", includes element id in the cut list (1) or not (0) -->
              <cutlist layoutalign="-1" layoutmargins="0.1,0.1,0.1,0.1" layoutminwidth="2.0" layoutminheight="7.0" settingsref="cutlist" elemid="0"></cutlist>
            </group>
            <group layout="vertical">
              <projection type="front" layoutmargins="2,0.5,1,1">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
                <elemmarkings>
                  <opening ref="mark_opening"></opening>
                </elemmarkings>
              </projection>
              <projection type="bottom" layoutmargins="2,0.5,0,1">
                <dimlines>
                  <dimline ref="wall_top"></dimline>
                </dimlines>
              </projection>
              <!--projection type="back" layoutmargins="2,2,0,2">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
              </projection-->
              <elemstamp layoutalign="-1" layoutmargins="-2.2,0,0,0" layoutminwidth="10.0" layoutminheight="1.0" libname="{9FD03D30-6A12-4B0F-AB3A-01410A529E38}-{D420792D-C066-42CF-988C-9596DD164EB7}" settingsref="elemstamp">
                <script ref="elemstamp"></script>
              </elemstamp>
            </group>
          </group>
        </projections>

        <!--markings ref="mark_default">
        </markings-->
      </elemtype>

      <elemtype class="floor" id="FLOOR 300 C/C 600 FRAME" idstamp="300">
        <layers>
          <layer name="Core" visible="1" thickness="0.300" type="core" anchorname1="Top" anchorname2="Bottom">

            <!-- Group name will have suffixes: _y=vertical planks, _x=horizontal planks -->
            <!-- Group names can be used for example to make grooves for balks and groups may be referred using wild cards: vertical* -->

            <!-- bottom wood -->
            <planks group="bottom" axis="x" skipaxis="1">
              <material id="I 300" zoff="0" rotangle="0"></material>
              <force>
                <parallel x2off="-mat_thickness*0.5"></parallel>
              </force>
            </planks>

            <!-- Top -->
            <planks group="top" axis="x" skipaxis="1">
              <material id="I 300" zoff="0" rotangle="0"></material>
              <force>
                <parallel x1off="mat_thickness*0.5"></parallel>
              </force>
            </planks>

            <planks group="vertical" axis="y" skipaxis="0" opening_parallel="1" opening_normal="1" spacing="0.6" spacingtolerance="0.05">
              <material id="I 300" zoff="0" rotangle="0"></material>
              <force_nope>
                <!-- parallel|normal, x1off refers to left side of axis, x2off to right side of the axis. Only the line that does not have anything in element polygon to offset direction is handled. -->
                <!-- extend extends the forced planks to outline polygon (to be cut later with top&bottom wood) -->
                <parallel x1off="0.500" extend="1" handleto1="-0.500">
                  <planks1 group="sideleft" axis="x" spacing="0.3" spacingtolerance="0.05">
                    <material id="I 300" zoff="0" rotangle="0"></material>
                  </planks1>
                </parallel>

                <parallel x2off="-0.500" extend="1" handleto1="0.500">
                  <planks1 group="sideright" axis="x" spacing="0.3" spacingtolerance="0.05">
                    <material id="I 300" zoff="0" rotangle="0"></material>
                  </planks1>
                </parallel>
              </force_nope>
            </planks>

            <planks group="contourtilted" axis="unused" contour_unused="0" opening_unused="1">
              <material id="block" zoff="0" rotangle="0" thickness="0.025" height="0.300"></material>
            </planks>

            <script ref="setcolours"></script>

            <operations>
              <!-- Extend y at inner corners -->
              <jointo target="contour_y" operator="contour_x">
                <cut maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.001" expandopfind="0.001" toend="1"></cut>
              </jointo>

              <!-- Contour y longer -->
              <jointo target="contour_x" operator="contour_y">
                <cut conntype="hasx" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="bottom*|top*|vertical_x|contour*">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- Trim to holes -->
              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="hasx" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- Trim sides -->
              <jointo target="sideleft*|sideright*" operator="vertical*|contour*">
                <cut conntype="hasx" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
            </operations>

          </layer>
          <!--layer name="Insulation" visible="0" thickness="0.050"></layer-->
          <!--layer name="Vertical studding in" visible="0" thickness="0.022" anchorname1="Vertical studding in"></layer-->
          <!--layer name="Plasterboard" visible="0" thickness="0.013" anchorname2="Plasterboard in"></layer-->
        </layers>

        <!-- No projections at all (no dim lines etc), change tag name projections_nope to projections to have projections. ALSO THE END TAG -->
        <projections>
          <group layout="horizontal">
            <group layout="vertical">
              <!-- Only planks belonging to the element are included in cutlist -->
              <!-- layoutalign: -1=left/bottom, 0=center, 1=right/top -->
              <!-- cutlist attribute elemid="0"/"1", includes element id in the cut list (1) or not (0) -->
              <cutlist layoutalign="-1" layoutmargins="0.1,0.1,0.1,0.1" layoutminwidth="2.0" layoutminheight="7.0" settingsref="cutlist" elemid="0"></cutlist>
            </group>
            <group layout="vertical">
              <projection type="front" layoutmargins="2,0.5,1,1">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
                <elemmarkings>
                  <opening ref="mark_opening"></opening>
                </elemmarkings>
              </projection>
              <projection type="bottom" layoutmargins="2,0.5,0,1">
                <dimlines>
                  <dimline ref="wall_top"></dimline>
                </dimlines>
              </projection>
              <!--projection type="back" layoutmargins="2,2,0,2">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
              </projection-->
              <elemstamp layoutalign="-1" layoutmargins="-2.2,0,0,0" layoutminwidth="10.0" layoutminheight="1.0" libname="{9FD03D30-6A12-4B0F-AB3A-01410A529E38}-{D420792D-C066-42CF-988C-9596DD164EB7}" settingsref="elemstamp">
                <script ref="elemstamp"></script>
              </elemstamp>
            </group>
          </group>
        </projections>

        <!--markings ref="mark_default">
        </markings-->
      </elemtype>


      <elemtype class="roof" id="GABLE EAVES 173 K600 LEFT" idstamp="42x173">
        <!-- Default settings for this element type -->
        <settings>
          <newelem>
            <elemparam name="pen">1</elemparam>
          </newelem>

          <newelemplank>
            <elemparam name="pen">1</elemparam>
          </newelemplank>
        </settings>

        <layers>

          <layer name="Core" visible="1" thickness="0.173" type="core" anchorname1="Core top" anchorname2="Core bottom">

            <planks group="purlins" axis="x" opening_parallel="1" opening_normal="1" spacing="0.9" spacingtolerance="0.01">
              <material id="block" thickness="0.042" height="0.173" zoff="0" rotangle="0"></material>
            </planks>

            <!-- Eaves side wood -->
            <planks group="eaves" axis="y" skipaxis="1">
              <material id="block" thickness="0.042" height="0.173" zoff="0" rotangle="0"></material>
              <force>
                <parallel x1off="mat_thickness*0.5"></parallel>
              </force>
            </planks>


            <!-- Transportation support -->
            <planks group="xxx" axis="y" skipaxis="1">
              <material id="block" thickness="0.020" height="0.070" zoff="-mat_thickness*0.5" rotangle="90"></material>
              <force>
                <parallel x2off="-0.070"></parallel>
              </force>
            </planks>

            <operations>
              <jointo target="purlins*" operator="eaves*">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
            </operations>
          </layer>
        </layers>

        <projections>
          <group layout="horizontal">
            <group layout="vertical">
              <!-- Only planks belonging to the element are included in cutlist -->
              <!-- layoutalign: -1=left/bottom, 0=center, 1=right/top -->
              <cutlist layoutalign="-1" layoutmargins="0.1,0.1,0.1,0.1" layoutminwidth="2.0" layoutminheight="7.0" settingsref="cutlist" elemid="0"></cutlist>
            </group>
            <group layout="vertical">
              <projection type="front" layoutmargins="2,2,2,2">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
              </projection>

              <!-- No top projection -->
              <!--projection type="top" layoutmargins="2,2,2,2">
                <dimlines>
                  <dimline ref="wall_top"></dimline>
                </dimlines>
              </projection-->
              <elemstamp layoutalign="-1" layoutmargins="-2.2,0,0,0" layoutminwidth="10.0" layoutminheight="1.0" libname="{9FD03D30-6A12-4B0F-AB3A-01410A529E38}-{D420792D-C066-42CF-988C-9596DD164EB7}" settingsref="elemstamp">
                <script ref="elemstamp"></script>
              </elemstamp>
            </group>
          </group>
        </projections>

        <!--markings ref="mark_default">
        </markings-->
      </elemtype>

      <elemtype class="roof" id="GABLE EAVES 173 K600 RIGHT" idstamp="42x173">
        <!-- Default settings for this element type -->
        <settings>
          <newelem>
            <elemparam name="pen">1</elemparam>
          </newelem>

          <newelemplank>
            <elemparam name="pen">1</elemparam>
          </newelemplank>
        </settings>

        <layers>

          <layer name="Core" visible="1" thickness="0.173" type="core" anchorname1="Core top" anchorname2="Core bottom">

            <planks group="purlins" axis="x" opening_parallel="1" opening_normal="1" spacing="0.9" spacingtolerance="0.01">
              <material id="block" thickness="0.042" height="0.173" zoff="0" rotangle="0"></material>
            </planks>

            <!-- Eaves side wood -->
            <planks group="eaves" axis="y" skipaxis="1">
              <material id="block" thickness="0.042" height="0.173"  zoff="0" rotangle="0"></material>
              <force>
                <parallel x2off="-mat_thickness*0.5"></parallel>
              </force>
            </planks>


            <!-- Transportation support -->
            <planks group="xxx" axis="y" skipaxis="1">
              <material id="block" thickness="0.020" height="0.070" zoff="-mat_thickness*0.5" rotangle="90"></material>
              <force>
                <parallel x1off="0.000"></parallel>
              </force>
            </planks>

            <operations>
              <jointo target="purlins*" operator="eaves*">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
            </operations>
          </layer>
        </layers>

        <projections>
          <group layout="horizontal">
            <group layout="vertical">
              <!-- Only planks belonging to the element are included in cutlist -->
              <!-- layoutalign: -1=left/bottom, 0=center, 1=right/top -->
              <cutlist layoutalign="-1" layoutmargins="0.1,0.1,0.1,0.1" layoutminwidth="2.0" layoutminheight="7.0" settingsref="cutlist" elemid="0"></cutlist>
            </group>
            <group layout="vertical">
              <projection type="front" layoutmargins="2,2,2,2">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
              </projection>

              <!-- No top projection -->
              <!-- projection type="top" layoutmargins="2,2,2,2">
                <dimlines>
                  <dimline ref="wall_top"></dimline>
                </dimlines>
              </projection -->
              <elemstamp layoutalign="-1" layoutmargins="-2.2,0,0,0" layoutminwidth="10.0" layoutminheight="1.0" libname="{9FD03D30-6A12-4B0F-AB3A-01410A529E38}-{D420792D-C066-42CF-988C-9596DD164EB7}" settingsref="elemstamp">
                <script ref="elemstamp"></script>
              </elemstamp>
            </group>
          </group>
        </projections>
      </elemtype>
    </elemtypes>


    <!-- ELEMENT TEMPLATES -->
    <elemtemplates>
      <elemtemplate class="boarding" templateid="boarding" templatename="Boarding" templatename_fin="Levytys" id="[id]">
        <settings>
          <newelemboard>
            <layer>[layer;type=layer;default=AF Board]</layer>
            <elemparam name="material">[material3d;default=]</elemparam>
            <elemparam name="cutfillpen">[cutfillpen;default=]</elemparam>
            <elemparam name="cutlinepen">[cutlinepen;default=]</elemparam>
            <elemparam name="cutfill">[cutfill;default=]</elemparam>
            <objparam name="iShowDiaLine">[boarddialine;default=1]</objparam>
            <objparam name="iPenId">[idpen]</objparam>
          </newelemboard>
        </settings>
        <layers>
          <boarding thickness="[thickness;type=length]" overlap="[boardoverlap;default=1]" boardingtype="[boardingtype;default=1]">
            <board id="[boardid]" width="[boardwidth;type=length]" height="[boardheight;type=length]"></board>
          </boarding>
        </layers>
        <cncinfo cnc_outputline="[cnc_outputline]" cnc_nailgun="[cnc_nailgun]" cnc_matindex="[cnc_matindex]" cnc_matname="[cnc_matname]" cnc_isframing="[cnc_isframing]"></cncinfo>
      </elemtemplate>

      <elemtemplate class="boarding" templateid="paneling" templatename="Paneling" templatename_fin="Verhoilu" id="[id]">
        <settings>
          <newelemboard>
            <layer>[layer;type=layer;default=AF Panel]</layer>
            <elemparam name="material">[material3d;default=]</elemparam>
            <elemparam name="cutfillpen">[cutfillpen;default=]</elemparam>
            <elemparam name="cutlinepen">[cutlinepen;default=]</elemparam>
            <elemparam name="cutfill">[cutfill;default=]</elemparam>
            <objparam name="iFill">0</objparam>
            <objparam name="iPanelRot">[panelrot;type=angle;default=0]</objparam>
            <objparam name="iPanelAnchor">[panelanchor;type=real;default=1]</objparam>
            <objparam name="iPanelX">[panel_offset_X;type=length;default=0]</objparam>
            <objparam name="iPanelY">[panel_offset_Y;type=length;default=0]</objparam>
          </newelemboard>
        </settings>
        <layers>
          <boarding thickness="[thickness;type=length]" type="core">
            <board panelingref="[panelref;type=panelid;default=PANEL_HOR_INOUT]" width="9999" height="9999" >
            </board>
          </boarding>
        </layers>
        <cncinfo cnc_outputline="[cnc_outputline]" cnc_nailgun="[cnc_nailgun]" cnc_matindex="[cnc_matindex]" cnc_matname="[cnc_matname]" cnc_isframing="[cnc_isframing]"></cncinfo>
      </elemtemplate>

      <elemtemplate class="layer" templateid="airstrips_vert" templatename="Air space strips vertical" templatename_fin="Tuuletusrako pysty" id="[id]">
        <settings>
          <newelemplank>
            <layer>[layer;type=layer]</layer>
            <elemparam name="material">[material3d;default=]</elemparam>
            <elemparam name="cutfillpen">[cutfillpen;default=]</elemparam>
            <elemparam name="cutlinepen">[cutlinepen;default=]</elemparam>
            <elemparam name="cutfill">[cutfill;default=]</elemparam>
          </newelemplank>
        </settings>
        <layers>
          <layer thickness="[thickness;type=length]" type="core">
            <planks group="vertical" axis="y" opening_parallel="[opening_parallel;default=1]" opening_normal="[opening_normal;default=0]" spacing="[spacing;type=length;default=0.6]" spacingtolerance="[spacingtolerance;type=length;default=0.005]" framingrule="[framingrule;type=real;default=0]">
              <material id="[matid;type=matid]" zoff="[zoff;default=mat_thickness*0.5]" rotangle="[rotangle;type=real;default=90]"></material>
            </planks>
          </layer>
        </layers>
        <cncinfo cnc_outputline="[cnc_outputline]" cnc_nailgun="[cnc_nailgun]" cnc_matindex="[cnc_matindex]" cnc_matname="[cnc_matname]" cnc_isframing="[cnc_isframing]"></cncinfo>
      </elemtemplate>

      <elemtemplate class="layer" templateid="airstrips_hor" templatename="Air space strips horizontal" templatename_fin="Tuuletusrako vaaka" id="[id]">
        <settings>
          <newelemplank>
            <layer>[layer;type=layer]</layer>
            <elemparam name="material">[material3d;default=]</elemparam>
            <elemparam name="cutfillpen">[cutfillpen;default=]</elemparam>
            <elemparam name="cutlinepen">[cutlinepen;default=]</elemparam>
            <elemparam name="cutfill">[cutfill;default=]</elemparam>
          </newelemplank>
        </settings>
        <layers>
          <layer thickness="[thickness;type=length]" type="core">
            <!-- bottom wood -->
            <planks group="bottom" axis="y" skipaxis="1">
              <material id="[matid;type=matid]" zoff="[zoff;default=mat_thickness*0.5]" rotangle="[rotangle;type=real;default=90]"></material>
              <force>
                <parallel x2off="-mat_thickness*0.5"></parallel>
              </force>
            </planks>

            <!-- Top -->
            <planks group="top" axis="y" skipaxis="1">
              <material id="[matid;type=matid]" zoff="[zoff;default=mat_thickness*0.5]" rotangle="[rotangle;type=real;default=90]"></material>
              <force>
                <parallel x1off="mat_thickness*0.5"></parallel>
              </force>
            </planks>

            <planks group="vertical" axis="x" opening_parallel="[opening_parallel;default=1]" opening_normal="[opening_normal;default=1]" spacing="[spacing;type=length;default=0.6]" spacingtolerance="[spacingtolerance;type=length;default=0.005]" framingrule="[framingrule;type=real;default=0]">
              <material id="[matid;type=matid]" zoff="[zoff;default=mat_thickness*0.5]" rotangle="[rotangle;type=real;default=90]"></material>
            </planks>

            <operations>
              <jointo target="vertical_x|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="bottom*|top*|vertical_y|contourtilted">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
              <jointo target="vertical_x|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="endtoline" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
              <jointo target="vertical_x|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="linex" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
            </operations>
          </layer>
        </layers>
        <cncinfo cnc_outputline="[cnc_outputline]" cnc_nailgun="[cnc_nailgun]" cnc_matindex="[cnc_matindex]" cnc_matname="[cnc_matname]" cnc_isframing="[cnc_isframing]"></cncinfo>
      </elemtemplate>


      <elemtemplate class="layer" templateid="framing1" templatename="Framing" templatename_fin="Runko" id="[id]">
        <settings>
          <newelemplank>
            <layer>[layer;type=layer]</layer>
            <elemparam name="material">[material3d;default=]</elemparam>
            <elemparam name="cutfillpen">[cutfillpen;default=]</elemparam>
            <elemparam name="cutlinepen">[cutlinepen;default=]</elemparam>
            <elemparam name="cutfill">[cutfill;default=]</elemparam>
          </newelemplank>
        </settings>
        <layers>
          <layer name="Core" visible="1" thickness="[thickness;type=length]" type="core" studmindist="[studmindist;type=length]">
            <!-- Left side vertical -->
            <planks group="vertical" axis="y" skipaxis="1">
              <material id="[matid_left;default=@matid;type=matid]" zoff="[zoff_left;default=0]" rotangle="[rotangle_left;type=real;default=0]"></material>
              <force>
                <parallel x1off="[off_center;default=mat_thickness*0.5]"></parallel>
              </force>
            </planks>

            <!-- Right side vertical -->
            <planks group="vertical" axis="y" skipaxis="1">
              <material id="[matid_right;default=@matid;type=matid]" zoff="[zoff_right;default=0]" rotangle="[rotangle_right;type=real;default=0]"></material>
              <force>
                <parallel x2off="-[off_center;default=mat_thickness*0.5]"></parallel>
              </force>
            </planks>

            <!-- bottom wood, assume rotangles 0/90 -->
            <planks group="bottom" axis="x" skipaxis="1">
              <material id="[matid_bot;default=@matid;type=matid]" zoff="[zoff_bot;default=@zoff]" rotangle="[rotangle_bot;type=real;default=@rotangle]">
                <objparam name="iCnc">[cnc_bottom;default=1;type=real]</objparam>
                <layer>[layer_bottom_plate;]</layer>
              </material>
              <force>
                <parallel x2off="-mat_thickness*0.5*abs(cos([rotangle_bot]*pi/180))-mat_height*0.5*abs(sin([rotangle_bot]*pi/180))"></parallel>
              </force>
            </planks>

            <!-- Top -->
            <planks group="top" axis="x" skipaxis="1">
              <material id="[matid_top;default=@matid;type=matid]" zoff="[zoff_top;default=@zoff]" rotangle="[rotangle_top;type=real;default=@rotangle]">
                <objparam name="iCnc">[cnc_top;default=1;type=real]</objparam>
                <layer>[layer_top_plate;]</layer>
              </material>
              <force>
                <parallel x1off="mat_thickness*0.5*abs(cos([rotangle_top]*pi/180))+mat_height*0.5*abs(sin([rotangle_top]*pi/180))"></parallel>
              </force>
            </planks>

            <!-- Spacing must be latest possible to get custom corners work the best -->
            <planks group="vertical" axis="y" opening_parallel="1" opening_normal="1" spacing="[spacing;type=length;default=0.6]" spacingtolerance="[spacingtolerance;type=length;default=0.005]" framingrule="[framingrule;type=real;default=0]">
              <material id="[matid;type=matid]" zoff="[zoff;default=0]" rotangle="[rotangle;type=real;default=0]"></material>
            </planks>

            <!-- Every other, axis=unused means every edge not handled in previous rules. Added planks for openings will not cut the studs and will have group suffix _opening -->
            <planks group="contourtilted" axis="unused" contour_unused="1" opening_unused="1">
              <material id="[matid_tilted;default=@matid;type=matid]" zoff="[zoff;default=0]" rotangle="[rotangle;type=real;default=0]"></material>
            </planks>

            <script ref="setcolours" currpre="1">
gFillPen="[studs_fillpen;prompt=Studs fill pen, empty=default, -=none;default=]"
            </script>

            <operations>
              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="bottom*|top*|vertical_x|contourtilted">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="endtoline" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="linex" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <groove target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="balktop*">
                <groove overtop="0.000" overbot="0.001" overside="0.000"></groove>
              </groove>
            </operations>

          </layer>
        </layers>
        <cncinfo cnc_outputline="[cnc_outputline]" cnc_nailgun="[cnc_nailgun]" cnc_matindex="[cnc_matindex]" cnc_matname="[cnc_matname]" cnc_isframing="[cnc_isframing]"></cncinfo>
      </elemtemplate>

      
      <elemtemplate class="layer" templateid="framingmetal" templatename="Framing metal" templatename_fin="Runko metalli" id="[id]">
        <settings>
          <newelemplank>
            <layer>[layer;type=layer]</layer>
            <elemparam name="material">[material3d;default=]</elemparam>
            <elemparam name="cutfillpen">[cutfillpen;default=]</elemparam>
            <elemparam name="cutlinepen">[cutlinepen;default=]</elemparam>
            <elemparam name="cutfill">[cutfill;default=]</elemparam>
          </newelemplank>
        </settings>
        <layers>
          <layer name="Core" visible="1" thickness="[thickness;type=length]" type="core" studmindist="[studmindist;type=length]">
            <!-- bottom wood -->
            <planks group="bottom" axis="x" skipaxis="1">
              <material id="[matid_bot;default=@matid;type=matid]" zoff="[zoff_bot;default=@zoff]" rotangle="[rotangle_bot;type=real;default=@rotangle]"></material>
              <force>
                <parallel x2off="-mat_thickness*0.5*abs(cos([rotangle_bot]*pi/180))-mat_height*0.5*abs(sin([rotangle_bot]*pi/180))"></parallel>
              </force>
            </planks>

            <!-- Top -->
            <planks group="top" axis="x" skipaxis="1">
              <material id="[matid_top;default=@matid;type=matid]" zoff="[zoff_top;default=@zoff]" rotangle="[rotangle_top;type=real;default=@rotangle]"></material>
              <force>
                <parallel x1off="mat_thickness*0.5*abs(cos([rotangle_top]*pi/180))+mat_height*0.5*abs(sin([rotangle_top]*pi/180))"></parallel>
              </force>
            </planks>

            <planks group="vertical" axis="y" opening_parallel="1" opening_normal="1" spacing="[spacing;type=length;default=0.6]" spacingtolerance="[spacingtolerance;type=length;default=0.005]" framingrule="[framingrule;type=real;default=0]">
              <material id="[matid;type=matid]" zoff="[zoff;default=0]" rotangle="[rotangle;type=real;default=0]"></material>
              <opening_bot>
                <material id="[matid_top;default=@matid;type=matid]" zoff="[zoff_top;default=@zoff]" rotangle="[rotangle_top;type=real;default=@rotangle]"></material>
              </opening_bot>
              <opening_top>
                <material id="[matid_opening_top;default=@matid_bot;type=matid]" zoff="[zoff_bot;default=@zoff]" rotangle="[rotangle_bot;type=real;default=@rotangle]"></material>
              </opening_top>
            </planks>

            <!-- Every other, axis=unused means every edge not handled in previous rules. Added planks for openings will not cut the studs and will have group suffix _opening -->
            <planks group="contourtilted" axis="unused" contour_unused="1" opening_unused="1">
              <material id="[matid;type=matid]" zoff="[zoff;default=0]" rotangle="[rotangle;type=real;default=0]"></material>
            </planks>

            <script ref="setcolours" currpre="1">
              gFillPen="[studs_fillpen;prompt=Studs fill pen, empty=default, -=none;default=]"
            </script>

            <operations>
              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="bottom*|top*|vertical_x|contourtilted">
                <cut jointgap="-[extend_inside;type=length;default=0]" extendmaxlen="0.0"></cut>
              </jointo>

              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="endtoline" jointgap="-[extend_inside;type=length;default=0]" extendmaxlen="0.0"></cut>
              </jointo>

              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="linex" maxdisttoend="0.050" jointgap="-[extend_inside;type=length;default=0]" extendmaxlen="0.0"></cut>
              </jointo>
            </operations>
          </layer>
        </layers>
        <cncinfo cnc_outputline="[cnc_outputline]" cnc_nailgun="[cnc_nailgun]" cnc_matindex="[cnc_matindex]" cnc_matname="[cnc_matname]" cnc_isframing="[cnc_isframing]"></cncinfo>
      </elemtemplate>
      
      
      <elemtemplate class="layer" templateid="framinghor1" templatename="Framing horizontal" templatename_fin="Runko vaaka" id="[id]">
        <settings>
          <newelemplank>
            <layer>[layer;type=layer]</layer>
            <elemparam name="material">[material3d;default=]</elemparam>
            <elemparam name="cutfillpen">[cutfillpen;default=]</elemparam>
            <elemparam name="cutlinepen">[cutlinepen;default=]</elemparam>
            <elemparam name="cutfill">[cutfill;default=]</elemparam>
          </newelemplank>
        </settings>
        <layers>
          <layer thickness="[thickness;type=length]" type="core" studmindist="[studmindist;type=length]">
            <!-- Left side vertical -->
            <planks group="top" axis="y" skipaxis="1" create="[create_left;default=1]">
              <material id="[matid_left;default=@matid;type=matid]" zoff="[zoff_left;default=mat_thickness*0.5]" rotangle="[rotangle_left;type=real;default=90]"></material>
              <force>
                <parallel x1off="[off_center;default=mat_height*0.5;prompt=Offset to center:]"></parallel>
              </force>
            </planks>

            <!-- Right side vertical -->
            <planks group="bottom" axis="y" skipaxis="1" create="[create_right;default=1]">
              <material id="[matid_right;default=@matid;type=matid]" zoff="[zoff_right;default=mat_thickness*0.5]" rotangle="[rotangle_right;type=real;default=90]"></material>
              <force>
                <parallel x2off="-[off_center;default=mat_height*0.5;prompt=Offset to center:]"></parallel>
              </force>
            </planks>


            <!-- Bottom -->
            <planks group="vertical" axis="x" skipaxis="1">
              <material id="[matid_bot;default=@matid;type=matid]" zoff="[zoff;default=mat_thickness*0.5]" rotangle="[rotangle;type=real;default=90]"></material>
              <force>
                <parallel x2off="-[off_center;default=mat_height*0.5;prompt=Offset to center:]"></parallel>
              </force>
            </planks>

            <!-- Top -->
            <planks group="vertical" axis="x" skipaxis="1">
              <material id="[matid_top;default=@matid;type=matid]" zoff="[zoff;default=mat_thickness*0.5]" rotangle="[rotangle;type=real;default=90]"></material>
              <force>
                <parallel x1off="[off_center;default=mat_height*0.5;prompt=Offset to center:]"></parallel>
              </force>
            </planks>

            <planks group="vertical" axis="x" opening_parallel="[opening_parallel;default=1]" opening_normal="[opening_normal;default=1]" spacing="[spacing;type=length;default=0.6]" spacingtolerance="[spacingtolerance;type=length;default=0.005]" framingrule="[framingrule;type=real;default=0]">
              <material id="[matid;type=matid]" zoff="[zoff;default=mat_thickness*0.5]" rotangle="[rotangle;type=real;default=90]"></material>
            </planks>

            <!-- Every other, axis=unused means every edge not handled in previous rules. Added planks for openings will not cut the studs and will have group suffix _opening -->
            <planks group="contourtilted" axis="unused" contour_unused="1" opening_unused="1" create="[create_other;default=0]">
              <material id="[matid;type=matid]" zoff="[zoff;default=0]" rotangle="[rotangle;type=real;default=0]"></material>
            </planks>

            <operations>
              <jointo target="vertical_x|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="bottom*|top*|vertical_y|contourtilted">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
              <jointo target="vertical_x|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="endtoline" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
              <jointo target="vertical_x|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="linex" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
            </operations>
          </layer>
        </layers>
        <cncinfo cnc_outputline="[cnc_outputline]" cnc_nailgun="[cnc_nailgun]" cnc_matindex="[cnc_matindex]" cnc_matname="[cnc_matname]" cnc_isframing="[cnc_isframing]"></cncinfo>
      </elemtemplate>


      <elemtemplate class="layer" templateid="framing_horlong" templatename="Framing horizontal long" templatename_fin="Runko vaaka pitkä" id="[id]">
        <settings>
          <newelemplank>
            <layer>[layer;type=layer]</layer>
            <elemparam name="material">[material3d;default=]</elemparam>
            <elemparam name="cutfillpen">[cutfillpen;default=]</elemparam>
            <elemparam name="cutlinepen">[cutlinepen;default=]</elemparam>
            <elemparam name="cutfill">[cutfill;default=]</elemparam>
          </newelemplank>
        </settings>
        <layers>
          <layer thickness="[thickness;type=length]" type="core" studmindist="[studmindist;type=length]">
            <!-- Left side vertical -->
            <planks group="top" axis="y" skipaxis="1" create="[create_left;default=1]">
              <material id="[matid_left;default=@matid;type=matid]" zoff="[zoff;default=mat_thickness*0.5]" rotangle="[rotangle;type=real;default=90]"></material>
              <force>
                <parallel x1off="mat_height*0.5"></parallel>
              </force>
            </planks>

            <!-- Right side vertical -->
            <planks group="bottom" axis="y" skipaxis="1" create="[create_right;default=1]">
              <material id="[matid_right;default=@matid;type=matid]" zoff="[zoff;default=mat_thickness*0.5]" rotangle="[rotangle;type=real;default=90]"></material>
              <force>
                <parallel x2off="-mat_height*0.5"></parallel>
              </force>
            </planks>

            <!-- Bottom -->
            <planks group="vertical" axis="x" skipaxis="1">
              <material id="[matid_bot;default=@matid;type=matid]" zoff="[zoff;default=mat_thickness*0.5]" rotangle="[rotangle;type=real;default=90]"></material>
              <force>
                <parallel x2off="-mat_height*0.5"></parallel>
              </force>
            </planks>

            <!-- Top -->
            <planks group="vertical" axis="x" skipaxis="1">
              <material id="[matid_top;default=@matid;type=matid]" zoff="[zoff;default=mat_thickness*0.5]" rotangle="[rotangle;type=real;default=90]"></material>
              <force>
                <parallel x1off="mat_height*0.5"></parallel>
              </force>
            </planks>

            <planks group="vertical" axis="x" opening_parallel="[opening_parallel;default=1]" opening_normal="[opening_normal;default=1]" spacing="[spacing;type=length;default=0.6]" spacingtolerance="[spacingtolerance;type=length;default=0.005]" framingrule="[framingrule;type=real;default=0]">
              <material id="[matid;type=matid]" zoff="[zoff;default=mat_thickness*0.5]" rotangle="[rotangle;type=real;default=90]"></material>
            </planks>

            <operations>
              <jointo target="bottom*|top*|contourtilted" operator="vertical_x|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
              <jointo target="vertical_x|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="vertical_y">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
              <jointo target="vertical_x|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="endtoline" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
              <jointo target="vertical_x|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="linex" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
            </operations>
          </layer>
        </layers>
        <cncinfo cnc_outputline="[cnc_outputline]" cnc_nailgun="[cnc_nailgun]" cnc_matindex="[cnc_matindex]" cnc_matname="[cnc_matname]" cnc_isframing="[cnc_isframing]"></cncinfo>
      </elemtemplate>


      <elemtemplate class="layer" templateid="framing_horlong2" templatename="Framing horizontal long opening sides cut" templatename_fin="Runko vaaka pitkä aukkojen sivut pätkinä" id="[id]">
        <settings>
          <newelemplank>
            <layer>[layer;type=layer]</layer>
            <elemparam name="material">[material3d;default=]</elemparam>
            <elemparam name="cutfillpen">[cutfillpen;default=]</elemparam>
            <elemparam name="cutlinepen">[cutlinepen;default=]</elemparam>
            <elemparam name="cutfill">[cutfill;default=]</elemparam>
          </newelemplank>
        </settings>
        <layers>
          <layer thickness="[thickness;type=length]" type="core" studmindist="[studmindist;type=length]">
            <!-- Left side vertical -->
            <planks group="top" axis="y" skipaxis="1" create="[create_left;default=1]">
              <material id="[matid_left;default=@matid;type=matid]" zoff="[zoff;default=mat_thickness*0.5]" rotangle="[rotangle;type=real;default=90]"></material>
              <force>
                <parallel x1off="mat_height*0.5"></parallel>
              </force>
            </planks>

            <!-- Right side vertical -->
            <planks group="bottom" axis="y" skipaxis="1" create="[create_right;default=1]">
              <material id="[matid_right;default=@matid;type=matid]" zoff="[zoff;default=mat_thickness*0.5]" rotangle="[rotangle;type=real;default=90]"></material>
              <force>
                <parallel x2off="-mat_height*0.5"></parallel>
              </force>
            </planks>

            <!-- Bottom -->
            <planks group="vertical" axis="x" skipaxis="1">
              <material id="[matid_bot;default=@matid;type=matid]" zoff="[zoff;default=mat_thickness*0.5]" rotangle="[rotangle;type=real;default=90]"></material>
              <force>
                <parallel x2off="-mat_height*0.5"></parallel>
              </force>
            </planks>

            <!-- Top -->
            <planks group="vertical" axis="x" skipaxis="1">
              <material id="[matid_top;default=@matid;type=matid]" zoff="[zoff;default=mat_thickness*0.5]" rotangle="[rotangle;type=real;default=90]"></material>
              <force>
                <parallel x1off="mat_height*0.5"></parallel>
              </force>
            </planks>

            <planks group="vertical" axis="x" opening_parallel="[opening_parallel;default=1]" opening_normal="[opening_normal;default=1]" spacing="[spacing;type=length;default=0.6]" spacingtolerance="[spacingtolerance;type=length;default=0.005]" framingrule="[framingrule;type=real;default=0]">
              <material id="[matid;type=matid]" zoff="[zoff;default=mat_thickness*0.5]" rotangle="[rotangle;type=real;default=90]"></material>
            </planks>

            <operations>
              <jointo target="bottom*|top*|contourtilted|vertical_y" operator="vertical_x|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
              <jointo target="vertical_x|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="vertical_y">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
              <jointo target="vertical_x|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="endtoline" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
              <jointo target="vertical_x|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="linex" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
            </operations>
          </layer>
        </layers>
        <cncinfo cnc_outputline="[cnc_outputline]" cnc_nailgun="[cnc_nailgun]" cnc_matindex="[cnc_matindex]" cnc_matname="[cnc_matname]" cnc_isframing="[cnc_isframing]"></cncinfo>
      </elemtemplate>


      <elemtemplate class="layer" templateid="framing_ibeam1" templatename="Framing I-beam" templatename_fin="Runko I-palkki" id="[id]">
        <settings>
          <newelemplank>
            <layer>[layer;type=layer]</layer>
            <elemparam name="material">[material3d;default=]</elemparam>
            <elemparam name="cutfillpen">[cutfillpen;default=]</elemparam>
            <elemparam name="cutlinepen">[cutlinepen;default=]</elemparam>
            <elemparam name="cutfill">[cutfill;default=]</elemparam>
          </newelemplank>
        </settings>
        <layers>
          <layer name="Core" visible="1" thickness="[thickness;type=length]" type="core" studmindist="[studmindist;type=length]">
            <!-- Left side vertical -->
            <planks group="vertical" axis="y" skipaxis="1">
              <material id="[matid_left;default=@matid;type=matid]" zoff="[zoff_left;default=0]" rotangle="[rotangle_left;type=real;default=0]"></material>
              <force>
                <parallel x1off="[off_center;default=mat_thickness*0.5]"></parallel>
              </force>
            </planks>

            <!-- Right side vertical -->
            <planks group="vertical" axis="y" skipaxis="1">
              <material id="[matid_right;default=@matid;type=matid]" zoff="[zoff_right;default=0]" rotangle="[rotangle_right;type=real;default=0]"></material>
              <force>
                <parallel x2off="-[off_center;default=mat_thickness*0.5]"></parallel>
              </force>
            </planks>

            <!-- bottom wood, assume rotangles 0/90 -->
            <planks group="bottom" axis="x" skipaxis="1">
              <material id="[matid_bot;default=@matid;type=matid]" zoff="[zoff_bot;default=@zoff]" rotangle="[rotangle_bot;type=real;default=@rotangle]">
                <objparam name="iCnc">[cnc_bottom;default=1;type=real]</objparam>
              </material>
              <force>
                <parallel x2off="-mat_thickness*0.5*abs(cos([rotangle_bot]*pi/180))-mat_height*0.5*abs(sin([rotangle_bot]*pi/180))"></parallel>
              </force>
            </planks>

            <!-- Top -->
            <planks group="top" axis="x" skipaxis="1">
              <material id="[matid_top;default=@matid;type=matid]" zoff="[zoff_top;default=@zoff]" rotangle="[rotangle_top;type=real;default=@rotangle]">
                <objparam name="iCnc">[cnc_top;default=1;type=real]</objparam>
              </material>
              <force>
                <parallel x1off="mat_thickness*0.5*abs(cos([rotangle_top]*pi/180))+mat_height*0.5*abs(sin([rotangle_top]*pi/180))"></parallel>
              </force>
            </planks>

            <planks group="vertical" axis="y" opening_parallel="1" opening_normal="1" spacing="[spacing;type=length;default=0.6]" spacingtolerance="[spacingtolerance;type=length;default=0.005]" framingrule="[framingrule;type=real;default=0]">
              <material id="[matid;type=matid]" zoff="[zoff;default=0]" rotangle="[rotangle;type=real;default=0]"></material>
            </planks>

            <!-- Every other, axis=unused means every edge not handled in previous rules. Added planks for openings will not cut the studs and will have group suffix _opening -->
            <planks group="contourtilted" axis="unused" contour_unused="1" opening_unused="1">
              <material id="[matid;type=matid]" zoff="[zoff;default=0]" rotangle="[rotangle;type=real;default=0]"></material>
            </planks>

            <script ref="setcolours" currpre="1">
              gFillPen="[studs_fillpen;prompt=Studs fill pen, empty=default, -=none;default=]"
            </script>
            <script ref="ibeamframe"></script>

            <operations>
              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="bottom*|top*|vertical_x|contourtilted">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="endtoline" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="linex" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <groove target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="balktop*">
                <groove overtop="0.000" overbot="0.001" overside="0.000"></groove>
              </groove>
            </operations>

          </layer>
        </layers>
        <cncinfo cnc_outputline="[cnc_outputline]" cnc_nailgun="[cnc_nailgun]" cnc_matindex="[cnc_matindex]" cnc_matname="[cnc_matname]" cnc_isframing="[cnc_isframing]"></cncinfo>
      </elemtemplate>


      <elemtemplate class="layer" templateid="floor1" templatename="Floor/roof with sides" templatename_fin="Lattia/katto reunuksilla" id="[id]">
        <settings>
          <newelemplank>
            <layer>[layer;type=layer]</layer>
            <elemparam name="material">[material3d;default=]</elemparam>
            <elemparam name="cutfillpen">[cutfillpen;default=]</elemparam>
            <elemparam name="cutlinepen">[cutlinepen;default=]</elemparam>
            <elemparam name="cutfill">[cutfill;default=]</elemparam>
          </newelemplank>
        </settings>
        <layers>
          <layer name="Core" visible="1" thickness="[thickness;type=length]" type="core" studmindist="[studmindist;type=length]">

            <planks group="contour" axis="y" extend="0" create="[createborder;default=1]">
              <material id="[bordermatid;default=block]" zoff="0" rotangle="0" thickness="[borderthickness;default=0.025;type=length]" height="[borderheight;default=0.100;type=length]"></material>
            </planks>

            <planks group="contour" axis="x" extend="0" create="[createborder]">
              <material id="[bordermatid]" zoff="0" rotangle="0" thickness="[borderthickness]" height="[borderheight]"></material>
            </planks>

            <planks group="vertical" axis="y" skipaxis="1" opening_parallel="1" opening_normal="1" spacing="[spacing;type=length;default=0.6]" spacingtolerance="[spacingtolerance;type=length;default=0.005]" framingrule="[framingrule;type=real;default=0]">
              <material id="[matid;type=matid]" zoff="0" rotangle="0"></material>
              <force>
                <!-- parallel|normal, x1off refers to left side of axis, x2off to right side of the axis. Only the line that does not have anything in element polygon to offset direction is handled. -->
                <!-- extend extends the forced planks to outline polygon (to be cut later with top&bottom wood) -->
                <parallel x1off="[sideoff;type=length;default=0.5]" extend="1" handleto1="-[sideoff]">
                  <planks1 group="sideleft" axis="x" spacing="[spacing_side;type=length;default=0.6]" spacingtolerance="[spacingtolerance_side;type=length;default=0.02]">
                    <material id="[matid_side;default=@matid;type=matid]" zoff="0" rotangle="0"></material>
                  </planks1>
                </parallel>

                <parallel x2off="-[sideoff]" extend="1" handleto1="[sideoff]">
                  <planks1 group="sideright" axis="x" spacing="[spacing_side;type=length;default=0.6]" spacingtolerance="[spacingtolerance_side;type=length;default=0.02]">
                    <material id="[matid_side;type=matid]" zoff="0" rotangle="0"></material>
                  </planks1>
                </parallel>
              </force>
            </planks>

            <planks group="contourtilted" axis="unused" contour_unused="1" opening_unused="1" create="[createborder]">
              <material id="[bordermatid]" zoff="0" rotangle="0" thickness="[borderthickness]" height="[borderheight]"></material>
            </planks>

            <operations>
              <!-- Extend y at inner corners -->
              <jointo target="contour_y" operator="contour_x">
                <cut maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.001" expandopfind="0.001" toend="1"></cut>
              </jointo>

              <!-- Contour y longer -->
              <jointo target="contour_x" operator="contour_y">
                <cut conntype="hasx" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="vertical_x|contour*">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- Trim to holes -->
              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="hasx" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- Trim sides -->
              <jointo target="sideleft*|sideright*" operator="vertical*|contour*">
                <cut conntype="hasx" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
            </operations>

          </layer>
        </layers>
        <cncinfo cnc_outputline="[cnc_outputline]" cnc_nailgun="[cnc_nailgun]" cnc_matindex="[cnc_matindex]" cnc_matname="[cnc_matname]" cnc_isframing="[cnc_isframing]"></cncinfo>
      </elemtemplate>


      <elemtemplate class="layer" templateid="floor_studshort1" templatename="Floor/roof with sides stud short" id="[id]">
        <settings>
          <newelemplank>
            <layer>[layer;type=layer]</layer>
            <elemparam name="material">[material3d;default=]</elemparam>
            <elemparam name="cutfillpen">[cutfillpen;default=]</elemparam>
            <elemparam name="cutlinepen">[cutlinepen;default=]</elemparam>
            <elemparam name="cutfill">[cutfill;default=]</elemparam>
          </newelemplank>
        </settings>
        <layers>
          <layer name="Core" visible="1" thickness="[thickness;type=length]" type="core" studmindist="[studmindist;type=length]">

            <planks group="contour" axis="y" extend="0" create="[createborder;default=1]">
              <material id="[bordermatid;default=block]" zoff="0" rotangle="0" thickness="[borderthickness;default=0.025;type=length]" height="[borderheight;default=0.100;type=length]"></material>
            </planks>

            <planks group="contour" axis="x" extend="0" create="[createborder]">
              <material id="[bordermatid]" zoff="0" rotangle="0" thickness="[borderthickness]" height="[borderheight]"></material>
            </planks>

            <planks group="vertical" axis="y" skipaxis="1" opening_parallel="1" opening_normal="1" spacing="[spacing;type=length;default=0.6]" spacingtolerance="[spacingtolerance;type=length;default=0.005]" framingrule="[framingrule;type=real;default=0]">
              <material id="[matid;type=matid]" zoff="0" rotangle="0"></material>
              <force>
                <!-- parallel|normal, x1off refers to left side of axis, x2off to right side of the axis. Only the line that does not have anything in element polygon to offset direction is handled. -->
                <!-- extend extends the forced planks to outline polygon (to be cut later with top&bottom wood) -->
                <parallel x1off="[sideoff;type=length;default=0.5]" extend="1" handleto1="-[sideoff]">
                  <planks1 group="sideleft" axis="x" spacing="[spacing_side;type=length;default=0.6]" spacingtolerance="[spacingtolerance_side;type=length;default=0.02]">
                    <material id="[matid_side;default=@matid;type=matid]" zoff="0" rotangle="0"></material>
                  </planks1>
                </parallel>

                <parallel x2off="-[sideoff]" extend="1" handleto1="[sideoff]">
                  <planks1 group="sideright" axis="x" spacing="[spacing_side;type=length;default=0.6]" spacingtolerance="[spacingtolerance_side;type=length;default=0.02]">
                    <material id="[matid_side;type=matid]" zoff="0" rotangle="0"></material>
                  </planks1>
                </parallel>
              </force>
            </planks>

            <planks group="contourtilted" axis="unused" contour_unused="1" opening_unused="1" create="[createborder]">
              <material id="[bordermatid]" zoff="0" rotangle="0" thickness="[borderthickness]" height="[borderheight]"></material>
            </planks>

            <operations>
              <!-- Extend x at inner corners -->
              <jointo target="contour_x" operator="contour_y">
                <cut maxdisttoend="0.100" jointgap="0.000" extendmaxlen="0.001" expandopfind="0.001" toend="1"></cut>
              </jointo>

              <!-- Contour x longer -->
              <jointo target="contour_y" operator="contour_x">
                <cut conntype="hasx" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="vertical_x|contour*">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- Trim to holes -->
              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="hasx" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- Trim sides -->
              <jointo target="sideleft*|sideright*" operator="vertical*|contour*">
                <cut conntype="hasx" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
            </operations>

          </layer>
        </layers>
        <cncinfo cnc_outputline="[cnc_outputline]" cnc_nailgun="[cnc_nailgun]" cnc_matindex="[cnc_matindex]" cnc_matname="[cnc_matname]" cnc_isframing="[cnc_isframing]"></cncinfo>
      </elemtemplate>

      <elemtemplate class="layer" templateid="floor2" templatename="Floor/roof no sides" templatename_fin="Lattia/katto ilman reunuksia" id="[id]">
        <settings>
          <newelemplank>
            <layer>[layer;type=layer]</layer>
            <elemparam name="material">[material3d;default=]</elemparam>
            <elemparam name="cutfillpen">[cutfillpen;default=]</elemparam>
            <elemparam name="cutlinepen">[cutlinepen;default=]</elemparam>
            <elemparam name="cutfill">[cutfill;default=]</elemparam>
          </newelemplank>
        </settings>
        <layers>
          <layer name="Core" visible="1" thickness="[thickness;type=length]" type="core" studmindist="[studmindist;type=length]">

            <planks group="contour" axis="y" extend="0" create="[createborder;default=1;prompt=Create border 0/1]">
              <material id="[bordermatid;default=block;prompt=Border mat id]" zoff="0" rotangle="0" thickness="[borderthickness;default=0.025;prompt=Border mat thickness;type=length]" height="[borderheight;default=0.100;prompt=Border mat height;type=length]"></material>
            </planks>

            <planks group="contour" axis="x" extend="0" create="[createborder]">
              <material id="[bordermatid]" zoff="0" rotangle="0" thickness="[borderthickness]" height="[borderheight]"></material>
            </planks>

            <planks group="vertical" axis="y" skipaxis="0" opening_parallel="1" opening_normal="1" spacing="[spacing;type=length;default=0.6]" spacingtolerance="[spacingtolerance;type=length;default=0.005]" framingrule="[framingrule;type=real;default=0]">
              <material id="[matid;type=matid]" zoff="0" rotangle="0"></material>
            </planks>

            <planks group="contourtilted" axis="unused" contour_unused="1" opening_unused="1" create="[createborder]">
              <material id="[bordermatid]" zoff="0" rotangle="0" thickness="[borderthickness]" height="[borderheight]"></material>
            </planks>

            <operations>
              <!-- Extend y at inner corners -->
              <jointo target="contour_y" operator="contour_x">
                <cut maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.001" expandopfind="0.001" toend="1"></cut>
              </jointo>

              <!-- Contour y longer -->
              <jointo target="contour_x" operator="contour_y">
                <cut conntype="hasx" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="vertical_x|contour*">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- Trim to holes -->
              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="hasx" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- Trim sides -->
              <jointo target="sideleft*|sideright*" operator="vertical*|contour*">
                <cut conntype="hasx" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
            </operations>

          </layer>
        </layers>
        <cncinfo cnc_outputline="[cnc_outputline]" cnc_nailgun="[cnc_nailgun]" cnc_matindex="[cnc_matindex]" cnc_matname="[cnc_matname]" cnc_isframing="[cnc_isframing]"></cncinfo>
      </elemtemplate>

      
      <elemtemplate class="layer" templateid="floorlong1" templatename="Floor/roof no sides joists long" templatename_fin="Lattia/katto ilman reunuksia palkit pitkänä" id="[id]">
        <settings>
          <newelemplank>
            <layer>[layer;type=layer]</layer>
            <elemparam name="material">[material3d;default=]</elemparam>
            <elemparam name="cutfillpen">[cutfillpen;default=]</elemparam>
            <elemparam name="cutlinepen">[cutlinepen;default=]</elemparam>
            <elemparam name="cutfill">[cutfill;default=]</elemparam>
          </newelemplank>
        </settings>
        <layers>
          <layer name="Core" visible="1" thickness="[thickness;type=length]" type="core">

            <planks group="contour" axis="y" extend="0" create="[createborder;default=1;prompt=Create border 0/1]">
              <material id="[bordermatid;default=block;prompt=Border mat id]" zoff="0" rotangle="0" thickness="[borderthickness;default=0.025;prompt=Border mat thickness;type=length]" height="[borderheight;default=0.100;prompt=Border mat height;type=length]"></material>
            </planks>

            <planks group="contour" axis="x" extend="0" create="[createborder]">
              <material id="[bordermatid]" zoff="0" rotangle="0" thickness="[borderthickness]" height="[borderheight]"></material>
            </planks>

            <planks group="vertical" axis="y" skipaxis="0" opening_parallel="1" opening_normal="1" spacing="[spacing;type=length;default=0.6]" spacingtolerance="[spacingtolerance;type=length;default=0.005]" framingrule="[framingrule;type=real;default=0]">
              <material id="[matid;type=matid]" zoff="0" rotangle="0"></material>
            </planks>

            <planks group="contourtilted" axis="unused" contour_unused="1" opening_unused="1" create="[createborder]">
              <material id="[bordermatid]" zoff="0" rotangle="0" thickness="[borderthickness]" height="[borderheight]"></material>
            </planks>

            <operations>
              <!-- Extend y at inner corners -->
              <jointo target="contour_y" operator="contour_x">
                <cut maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.001" expandopfind="0.001" toend="1"></cut>
              </jointo>

              <!-- Contour y longer -->
              <jointo target="contour_x" operator="contour_y">
                <cut conntype="hasx" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <jointo target="vertical_x|contour*" operator="vertical_y*|vertical_spacing|vertical_force">
                <cut jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- Trim to holes -->
              <jointo target="vertical_y|vertical_spacing|vertical_force|vertical_y_openingsupport|vertical_y_*double" operator="contourtilted_opening">
                <cut conntype="hasx" maxdisttoend="0.050" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>

              <!-- Trim sides -->
              <jointo target="sideleft*|sideright*" operator="vertical*|contour*">
                <cut conntype="hasx" jointgap="0.000" extendmaxlen="0.0"></cut>
              </jointo>
            </operations>

          </layer>
        </layers>
      </elemtemplate>


      <elemtemplate class="layer" templateid="vertpanel1" id="[id]" templatename="Vertical planks fixed spacing" templatename_fin="Pystyverhoilu vakiovälistyksellä" >
        <settings>
          <newelemplank>
            <layer>[layer;type=layer]</layer>
            <elemparam name="material">[material3d;default=]</elemparam>
            <elemparam name="cutfillpen">[cutfillpen;default=]</elemparam>
            <elemparam name="cutlinepen">[cutlinepen;default=]</elemparam>
            <elemparam name="cutfill">[cutfill;default=]</elemparam>
            <objparam name="iColLines">3</objparam>
          </newelemplank>
        </settings>
        <layers>
          <layer thickness="[thickness;type=length]" type="core">
            <planks group="vertical" axis="y" opening_parallel="0" opening_normal="0" spacing="[spacing;type=length;default=0.100]" stackingoffset="[stackingoffset;type=length;default=mat_height*0.5]" skipaxis="1">
              <material id="[matid;type=matid]" zoff="[zoff;default=mat_thickness*0.5]" rotangle="[rotangle;type=real;default=90]"></material>
            </planks>
          </layer>
        </layers>
        <cncinfo cnc_outputline="[cnc_outputline]" cnc_nailgun="[cnc_nailgun]" cnc_matindex="[cnc_matindex]" cnc_matname="[cnc_matname]" cnc_isframing="[cnc_isframing]"></cncinfo>
      </elemtemplate>


      <elemtemplate class="layer" templateid="horpanel1" id="[id]" templatename="Horizontal planks fixed spacing" templatename_fin="Vaakaverhoilu vakiovälistyksellä" >
        <settings>
          <newelemplank>
            <layer>[layer;type=layer]</layer>
            <elemparam name="material">[material3d;default=]</elemparam>
            <elemparam name="cutfillpen">[cutfillpen;default=]</elemparam>
            <elemparam name="cutlinepen">[cutlinepen;default=]</elemparam>
            <elemparam name="cutfill">[cutfill;default=]</elemparam>
            <objparam name="iColLines">3</objparam>
          </newelemplank>
        </settings>
        <layers>
          <layer thickness="[thickness;type=length]" type="core">
            <planks group="vertical" axis="x" opening_parallel="0" opening_normal="0" spacing="[spacing;type=length;default=0.100]" stackingoffset="[stackingoffset;type=length;default=mat_height*0.5]" skipaxis="1">
              <material id="[matid;type=matid]" zoff="[zoff;default=mat_thickness*0.5]" rotangle="[rotangle;type=real;default=90]"></material>
            </planks>
          </layer>
        </layers>
        <cncinfo cnc_outputline="[cnc_outputline]" cnc_nailgun="[cnc_nailgun]" cnc_matindex="[cnc_matindex]" cnc_matname="[cnc_matname]" cnc_isframing="[cnc_isframing]"></cncinfo>
      </elemtemplate>


      <!-- 2018_03 BEGIN -->
      <elemtemplate class="composite" templateid="frame_singleproj10" templatename="Just framing with cutlist having machinings v 1.0" templatename_fin="Vain runko ja katkaisulista kolouksin v 1.0" id="[id]" idstamp="[idstamp]" cnc_elemtype="[cnc_elemtype]">
        <settings>
          <masterelem>
            <layer>[layer;type=layer]</layer>
            <objparam name="iShowElemType">[showelemtype;default=0]</objparam>
            <objparam name="iShowID2D">1</objparam>
            <objparam name="iShowID3D">1</objparam>
          </masterelem>
          <slaveelem>
            <layer>[layer;type=layer]</layer>
            <objparam name="iShowElemType">0</objparam>
            <objparam name="iShowID2D">0</objparam>
            <objparam name="iShowID3D">0</objparam>
          </slaveelem>
        </settings>

        <!-- Content of <layers> will be added by custom element tool -->

        <!-- Projections for the element inside one frame from top to bottom -->
        <projections>
          <group layout="vertical">
            <group layout="horizontal">
              <group layout="vertical">
                <text content="#id#" anchor="7" x="0" y="0.1" update="1">
                  <elemparam name="pen">1</elemparam>
                  <elemparam name="fontname">arial</elemparam>
                  <elemparam name="fontsize">30</elemparam>
                  <elemparam name="fontstyle"></elemparam>
                </text>
                <projection type="front" layoutmargins="1.5,0.5,1.1,0.5" exclude="[excludeint;default=intstud*,extstud*]" boardpanels="[boardpanelsint;default=]">
                  <dimlines>
                    <dimline ref="an_framing"></dimline>
                  </dimlines>
                  <elemmarkings>
                    <opening text="#id#\n#width#\nx\n#height#">
                      <elemparam name="pen">1</elemparam>
                      <elemparam name="fontname">Arial</elemparam>
                      <elemparam name="fontsize">1.5</elemparam>
                      <elemparam name="fontstyle"></elemparam>
                      <elemparam name="just">center</elemparam>
                      <framelines create="[create_openig_frame_lines;default=0]">
                        <elemparam name="pen">1</elemparam>
                        <elemparam name="linetype">1</elemparam>
                      </framelines>
                    </opening>
                    <weight libname="{FD6C137D-C647-42FD-A904-181281909443}-{9060078A-0F41-48C8-8400-8E414A838053}" create="[show_weight_front;default=3]" text="[weight_text;default=(weight) KG]" units="[weight_unit;default=kg]">
                      <settings>
                        <layer>[layer_weight;type=layer]</layer>
                        <objparam name="iFill">*25*</objparam>
                        <objparam name="A">0.250</objparam>
                        <objparam name="B">0.325</objparam>
                      </settings>
                    </weight>
                  </elemmarkings>
                </projection>

                <projection type="top" layoutmargins="1.5,0.5,0,0.5" boardpanels="[boardpanelstop;default=*]">
                  <dimlines>
                    <dimline ref="wall_top"></dimline>
                  </dimlines>
                  <elemmarkings>
                    <weight libname="{FD6C137D-C647-42FD-A904-181281909443}-{9060078A-0F41-48C8-8400-8E414A838053}" create="[show_weight_top;default=0]" text="[weight_text;default=(weight) KG]" units="[weight_unit;default=kg]">
                      <settings>
                        <layer>[layer_weight;type=layer]</layer>
                        <objparam name="iFill">*25*</objparam>
                        <objparam name="A">0.250</objparam>
                        <objparam name="B">0.325</objparam>
                      </settings>
                    </weight>
                  </elemmarkings>
                </projection>
              </group>

              <group layout="horizontal" >
                <cutlist layoutmargins="1,0.1,0.1,0.1" settingsref="cutlist_table_an_single" elemid="0" layoutminheight="3"></cutlist>
              </group>
            </group>
            <elemstamp layoutalign="-1" layoutmargins="0,0,0,0" layoutminwidth="10.0" layoutminheight="1.0" libname="{9FD03D30-6A12-4B0F-AB3A-01410A529E38}-{D420792D-C066-42CF-988C-9596DD164EB7}" settingsref="elemstamp">
              <script ref="elemstamp"></script>
            </elemstamp>
          </group>
        </projections>
      </elemtemplate>


      <elemtemplate class="composite" templateid="ew_out_frameclad_10" templatename="Wall frame+cladding out to in with cutlist having machinings v 1.0" templatename_fin="Seinä runko+verhoilu ulkoa sisälle ja katkaisulista kolouksin v 1.0" id="[id]" idstamp="[idstamp]" cnc_elemtype="[cnc_elemtype]">
        <settings>
          <masterelem>
            <layer>[layer;type=layer]</layer>
            <objparam name="iShowElemType">[showelemtype;default=0]</objparam>
            <objparam name="iShowID2D">1</objparam>
            <objparam name="iShowID3D">1</objparam>
          </masterelem>
          <slaveelem>
            <layer>[layer;type=layer]</layer>
            <objparam name="iShowElemType">0</objparam>
            <objparam name="iShowID2D">0</objparam>
            <objparam name="iShowID3D">0</objparam>
          </slaveelem>
        </settings>

        <!-- Content of <layers> will be added by custom element tool -->

        <!-- Projections for the element inside one frame from top to bottom -->
        <projections>
          <group layout="horizontal">
            <group layout="vertical">
              <text content="#id#" anchor="7" x="0" y="0.1" update="1">
                <elemparam name="pen">1</elemparam>
                <elemparam name="fontname">arial</elemparam>
                <elemparam name="fontsize">30</elemparam>
                <elemparam name="fontstyle"></elemparam>
              </text>
              <text content="CORE FROM OUTSIDE" content_fin="RUNKO ULKOA" anchor="1" x="1.5" y="-0.1">
                <elemparam name="pen">1</elemparam>
                <elemparam name="fontname">arial</elemparam>
                <elemparam name="fontsize">2.5</elemparam>
                <elemparam name="fontstyle"></elemparam>
              </text>
              <projection type="front" layoutmargins="1.5,0.5,1.1,0.5" exclude="[excludeext;default=intstud*,extstud*]" boardpanels="[boardpanelsext;default=finish_ext]">
                <dimlines>
                  <dimline ref="an_frame_cladding"></dimline>
                </dimlines>
                <elemmarkings>
                  <opening text="#id#\n#width#\nx\n#height#">
                    <elemparam name="pen">1</elemparam>
                    <elemparam name="fontname">Arial</elemparam>
                    <elemparam name="fontsize">1.5</elemparam>
                    <elemparam name="fontstyle"></elemparam>
                    <elemparam name="just">center</elemparam>
                    <framelines create="[create_openig_frame_lines;default=0]">
                      <elemparam name="pen">1</elemparam>
                      <elemparam name="linetype">1</elemparam>
                    </framelines>
                  </opening>
                  <weight libname="{FD6C137D-C647-42FD-A904-181281909443}-{9060078A-0F41-48C8-8400-8E414A838053}" create="[show_weight_front;default=3]" text="[weight_text;default=(weight) KG]" units="[weight_unit;default=kg]">
                    <settings>
                      <layer>[layer_weight;type=layer]</layer>
                      <objparam name="iFill">*25*</objparam>
                      <objparam name="A">0.250</objparam>
                      <objparam name="B">0.325</objparam>
                    </settings>
                  </weight>
                </elemmarkings>
                <projplanksettings type="extstud*">
                  <elemparam name="linetype">*dash*</elemparam>
                  <objparam name="iFill">0</objparam>
                  <objparam name="iShowID">0</objparam>
                  <objparam name="iShowLen">0</objparam>
                  <elemparam name="pen">2</elemparam>
                </projplanksettings>
              </projection>

              <projection type="top" layoutmargins="1.5,0.5,0,0.5" boardpanels="[boardpanelstop;default=*]">
                <dimlines>
                  <dimline ref="wall_top"></dimline>
                </dimlines>
                <elemmarkings>
                  <weight libname="{FD6C137D-C647-42FD-A904-181281909443}-{9060078A-0F41-48C8-8400-8E414A838053}" create="[show_weight_top;default=0]" text="[weight_text;default=(weight) KG]" units="[weight_unit;default=kg]">
                    <settings>
                      <layer>[layer_weight;type=layer]</layer>
                      <objparam name="iFill">*25*</objparam>
                      <objparam name="A">0.250</objparam>
                      <objparam name="B">0.325</objparam>
                    </settings>
                  </weight>
                </elemmarkings>
              </projection>
              <elemstamp layoutalign="-1" layoutmargins="0,0,0,0" layoutminwidth="10.0" layoutminheight="1.0" libname="{9FD03D30-6A12-4B0F-AB3A-01410A529E38}-{D420792D-C066-42CF-988C-9596DD164EB7}" settingsref="elemstamp">
                <script ref="elemstamp"></script>
              </elemstamp>
            </group>

            <group layout="horizontal" >
              <cutlist layoutmargins="1,0.1,0.1,0.1" settingsref="cutlist_table_an_single" elemid="0" layoutminheight="3"></cutlist>
            </group>
          </group>
        </projections>
      </elemtemplate>


      <elemtemplate class="composite" templateid="frame_singleproj_floor10" templatename="Just framing floor+roof with cutlist having machinings v 1.0" templatename_fin="Vain runko vp ja yp ja katkaisulista kolouksin v 1.0" id="[id]" idstamp="[idstamp]" cnc_elemtype="[cnc_elemtype]">
        <settings>
          <masterelem>
            <layer>[layer;type=layer]</layer>
            <objparam name="iShowElemType">[showelemtype;default=0]</objparam>
            <objparam name="iShowID2D">1</objparam>
            <objparam name="iShowID3D">1</objparam>
          </masterelem>
          <slaveelem>
            <layer>[layer;type=layer]</layer>
            <objparam name="iShowElemType">0</objparam>
            <objparam name="iShowID2D">0</objparam>
            <objparam name="iShowID3D">0</objparam>
          </slaveelem>
        </settings>

        <!-- Content of <layers> will be added by custom element tool -->

        <!-- Projections for the element inside one frame from top to bottom -->
        <projections>
          <group layout="vertical">
            <group layout="horizontal">
              <group layout="vertical">
                <text content="#id#" anchor="7" x="0" y="0.1" update="1">
                  <elemparam name="pen">1</elemparam>
                  <elemparam name="fontname">arial</elemparam>
                  <elemparam name="fontsize">30</elemparam>
                  <elemparam name="fontstyle"></elemparam>
                </text>
                <projection type="front" layoutmargins="1.5,0.5,1.1,0.5" exclude="[excludeint;default=intstud*,extstud*]" boardpanels="[boardpanelsint;default=]">
                  <dimlines>
                    <dimline ref="an_framing"></dimline>
                  </dimlines>
                  <elemmarkings>
                    <opening text="#id#\n#width#\nx\n#height#">
                      <elemparam name="pen">1</elemparam>
                      <elemparam name="fontname">Arial</elemparam>
                      <elemparam name="fontsize">1.5</elemparam>
                      <elemparam name="fontstyle"></elemparam>
                      <elemparam name="just">center</elemparam>
                      <framelines create="[create_openig_frame_lines;default=0]">
                        <elemparam name="pen">1</elemparam>
                        <elemparam name="linetype">1</elemparam>
                      </framelines>
                    </opening>
                    <weight libname="{FD6C137D-C647-42FD-A904-181281909443}-{9060078A-0F41-48C8-8400-8E414A838053}" create="[show_weight_front;default=3]" text="[weight_text;default=(weight) KG]" units="[weight_unit;default=kg]">
                      <settings>
                        <layer>[layer_weight;type=layer]</layer>
                        <objparam name="iFill">*25*</objparam>
                        <objparam name="A">0.250</objparam>
                        <objparam name="B">0.325</objparam>
                      </settings>
                    </weight>
                  </elemmarkings>
                </projection>

                <projection type="bottom" layoutmargins="1.5,0.5,0,0.5" boardpanels="[boardpanelstop;default=*]">
                  <dimlines>
                    <dimline ref="wall_top"></dimline>
                  </dimlines>
                  <elemmarkings>
                    <weight libname="{FD6C137D-C647-42FD-A904-181281909443}-{9060078A-0F41-48C8-8400-8E414A838053}" create="[show_weight_top;default=0]" text="[weight_text;default=(weight) KG]" units="[weight_unit;default=kg]">
                      <settings>
                        <layer>[layer_weight;type=layer]</layer>
                        <objparam name="iFill">*25*</objparam>
                        <objparam name="A">0.250</objparam>
                        <objparam name="B">0.325</objparam>
                      </settings>
                    </weight>
                  </elemmarkings>
                </projection>
              </group>

              <group layout="horizontal" >
                <cutlist layoutmargins="1,0.1,0.1,0.1" settingsref="cutlist_table_an_single" elemid="0" layoutminheight="3"></cutlist>
              </group>
            </group>
            <elemstamp layoutalign="-1" layoutmargins="0,0,0,0" layoutminwidth="10.0" layoutminheight="1.0" libname="{9FD03D30-6A12-4B0F-AB3A-01410A529E38}-{D420792D-C066-42CF-988C-9596DD164EB7}" settingsref="elemstamp">
              <script ref="elemstamp"></script>
            </elemstamp>
          </group>
        </projections>
      </elemtemplate>
      
      
      <elemtemplate class="composite" templateid="an_extwall_10" templatename="Multisheet external wall from out to in v 1.0" templatename_fin="Moniarkkituloste ulkoseinät ulkoa sisälle v 1.0" id="[id]" idstamp="[idstamp]" cnc_elemtype="[cnc_elemtype]">
        <settings>
          <masterelem>
            <layer>[layer;type=layer]</layer>
            <objparam name="iShowElemType">[showelemtype;default=0]</objparam>
            <objparam name="iShowID2D">1</objparam>
            <objparam name="iShowID3D">1</objparam>
          </masterelem>
          <slaveelem>
            <layer>[layer;type=layer]</layer>
            <objparam name="iShowElemType">0</objparam>
            <objparam name="iShowID2D">0</objparam>
            <objparam name="iShowID3D">0</objparam>
          </slaveelem>
        </settings>

        <!-- Content of <layers> will be added by custom element tool -->

        <!-- Projections for the element inside one frame from top to bottom -->
        <projections>
          <group layout="vertical">
            <!-- PAGE 1 -->
            <group layout="vertical">
              <frame x1off="0.01" x2off="-0.01" y1off="0.01" y2off="-0.01">
                <objparam name="name">MAIN</objparam>
              </frame>
              <group layout="vertical">
                <text content="#id#" anchor="7" x="0" y="0.1" update="1">
                  <elemparam name="pen">1</elemparam>
                  <elemparam name="fontname">arial</elemparam>
                  <elemparam name="fontsize">30</elemparam>
                  <elemparam name="fontstyle"></elemparam>
                </text>
                <text content="CORE FROM OUTSIDE" content_fin="RUNKO ULKOA" anchor="1" x="6" y="-2">
                  <elemparam name="pen">1</elemparam>
                  <elemparam name="fontname">arial</elemparam>
                  <elemparam name="fontsize">2.5</elemparam>
                  <elemparam name="fontstyle"></elemparam>
                </text>
                <projection type="front" layoutmargins="6,0.5,3,0.5" exclude="[excludeext;default=intstud*,extstud*]" boardpanels="[boardpanelsext;default=]">
                  <dimlines>
                    <dimline ref="an_framing"></dimline>
                  </dimlines>
                  <elemmarkings>
                    <opening text="#id#\n#width#\nx\n#height#">
                      <elemparam name="pen">1</elemparam>
                      <elemparam name="fontname">Arial</elemparam>
                      <elemparam name="fontsize">1.5</elemparam>
                      <elemparam name="fontstyle"></elemparam>
                      <elemparam name="just">center</elemparam>
                      <framelines create="[create_openig_frame_lines;default=0]">
                        <elemparam name="pen">1</elemparam>
                        <elemparam name="linetype">1</elemparam>
                      </framelines>
                    </opening>
                    <weight libname="{FD6C137D-C647-42FD-A904-181281909443}-{9060078A-0F41-48C8-8400-8E414A838053}" create="[show_weight_front;default=3]" text="[weight_text;default=(weight) KG]" units="[weight_unit;default=kg]">
                      <settings>
                        <layer>[layer_weight;type=layer]</layer>
                        <objparam name="iFill">*25*</objparam>
                        <objparam name="A">0.250</objparam>
                        <objparam name="B">0.325</objparam>
                      </settings>
                    </weight>
                  </elemmarkings>
                  <projplanksettings type="extstud*">
                    <elemparam name="linetype">*dash*</elemparam>
                    <objparam name="iFill">0</objparam>
                    <objparam name="iShowID">0</objparam>
                    <objparam name="iShowLen">0</objparam>
                    <elemparam name="pen">2</elemparam>
                  </projplanksettings>
                </projection>

                <projection type="top" layoutmargins="6,0.5,0,0.5" boardpanels="[boardpanelstop;default=*]">
                  <dimlines>
                    <dimline ref="wall_top"></dimline>
                  </dimlines>
                  <elemmarkings>
                    <weight libname="{FD6C137D-C647-42FD-A904-181281909443}-{9060078A-0F41-48C8-8400-8E414A838053}" create="[show_weight_top;default=0]" text="[weight_text;default=(weight) KG]" units="[weight_unit;default=kg]">
                      <settings>
                        <layer>[layer_weight;type=layer]</layer>
                        <objparam name="iFill">*25*</objparam>
                        <objparam name="A">0.250</objparam>
                        <objparam name="B">0.325</objparam>
                      </settings>
                    </weight>
                  </elemmarkings>
                </projection>
              </group>

              <group layout="horizontal" >
                <cutlist layoutmargins="4.5,0.1,0.1,0.1" settingsref="cutlist_table_an11" elemid="0" layoutminheight="3"></cutlist>
                <cutlist layoutmargins="0,0.1,0.1,0.1" settingsref="cutlist_table_an11" elemid="0"></cutlist>
              </group>
            </group>

            <!-- PAGE 2 -->
            <group layout="horizontal">
              <frame x1off="0.01" x2off="-0.01" y1off="0.01" y2off="-0.01">
                <objparam name="name">EXTERIOR</objparam>
              </frame>
              <group layout="vertical">
                <text content="WINDSHIELD BOARDS FROM OUTSIDE" content_fin="TS-LEVYT ULKOA" anchor="7" x="2" y="-0.9">
                  <elemparam name="pen">1</elemparam>
                  <elemparam name="fontname">arial</elemparam>
                  <elemparam name="fontsize">2.5</elemparam>
                  <elemparam name="fontstyle"></elemparam>
                </text>
                <projection type="front" layoutmargins="2,0.5,1,1" boardpanels="[windshieldboards;default=boarding_ext*]" exclude="[excludeext_windshield;default=intstud*,extstud*]">
                  <dimlines>
                    <dimline ref="kw_levy"></dimline>
                  </dimlines>
                  <projplanksettings type="core">
                    <elemparam name="linetype">*dash*</elemparam>
                    <objparam name="iFill">0</objparam>
                    <objparam name="iShowID">0</objparam>
                    <objparam name="iShowLen">0</objparam>
                    <elemparam name="pen">2</elemparam>
                  </projplanksettings>
                </projection>

                <text content="CLADDING FROM OUTSIDE" content_fin="VERHOILU ULKOA" anchor="7" x="2" y="0.1">
                  <elemparam name="pen">1</elemparam>
                  <elemparam name="fontname">arial</elemparam>
                  <elemparam name="fontsize">2.5</elemparam>
                  <elemparam name="fontstyle"></elemparam>
                </text>
                <projection type="front" layoutmargins="2,0,0,1" boardpanels="finish_ext" exclude="[exclude_cladding;default=intstud*,extstud2]">
                  <projplanksettings type="core">
                    <elemparam name="linetype">*dash*|*katkoviiva*</elemparam>
                    <objparam name="iFill">0</objparam>
                    <objparam name="iShowID">0</objparam>
                    <objparam name="iShowLen">0</objparam>
                    <elemparam name="pen">2</elemparam>
                  </projplanksettings>
                </projection>
              </group>
              <group layout="vertical" layoutmargins="1,0,0.1,0">
                <cutlist layoutmargins="0.1,0.1,0,0.1" layoutminwidth="2.50" settingsref="cutlist_table_an11" elemid="0"></cutlist>
                <cutlist layoutmargins="0.1,0.1,0.1,0.1" layoutminwidth="2.50" settingsref="cutlist_table_an11" elemid="0"></cutlist>
              </group>
            </group>

            <!-- PAGE 3 -->
            <group layout="horizontal">
              <frame x1off="0.01" x2off="-0.01" y1off="0.01" y2off="-0.01">
                <objparam name="name">INTERIOR</objparam>
              </frame>
              <group layout="vertical">
                <!-- VILLAKUVA -->
                <text content="INSULATION FROM INSIDE" content_fin="ERISTE SISÄLTÄ" anchor="1" x="2" y="-0.05">
                  <elemparam name="pen">1</elemparam>
                  <elemparam name="fontname">arial</elemparam>
                  <elemparam name="fontsize">2.5</elemparam>
                  <elemparam name="fontstyle"></elemparam>
                </text>
                <projection type="back" layoutmargins="2,0,1,0.5" exclude="*boarding*,*stud*,*finish*">
                  <dimlines>
                    <dimline ref="an_insu"></dimline>
                  </dimlines>
                  <projplanksettings type="core">
                    <objparam name="iFill">0</objparam>
                    <objparam name="iShowID">0</objparam>
                    <objparam name="iShowLen">0</objparam>
                  </projplanksettings>
                </projection>

                <text content="INTERIOR STUDDING INSIDE" content_fin="SISÄKOOLAUS SISÄLTÄ" anchor="7" x="2" y="0.1">
                  <elemparam name="pen">1</elemparam>
                  <elemparam name="fontname">arial</elemparam>
                  <elemparam name="fontsize">2.5</elemparam>
                  <elemparam name="fontstyle"></elemparam>
                </text>
                <projection type="back" layoutmargins="2,0,0,1" exclude="*ext*" boardpanels="boarding_int*">
                  <dimlines>
                    <dimline ref="an_horframing"></dimline>
                  </dimlines>
                  <projplanksettings type="core">
                    <elemparam name="linetype">*dash*|*katkoviiva*</elemparam>
                    <objparam name="iFill">0</objparam>
                    <objparam name="iShowID">0</objparam>
                    <objparam name="iShowLen">0</objparam>
                    <elemparam name="pen">2</elemparam>
                  </projplanksettings>
                </projection>
              </group>
              <group layout="vertical" layoutmargins="1,0.5,0,1" >
                <cutlist layoutmargins="0.1,0.1,0.1,0.1" layoutminwidth="3.50" settingsref="cutlist_table_an11" elemid="0"></cutlist>
                <cutlist layoutmargins="0.1,0.1,0.5,0.1" layoutminwidth="3.50" settingsref="cutlist_table_an11" elemid="0"></cutlist>
              </group>
            </group>
          </group>
        </projections>
      </elemtemplate>
      <!-- 2018_03 END -->
  
	  
      <elemtemplate class="composite" templateid="composite_outin" templatename="Looked from out to in" templatename_fin="Katselusuunta ulkoa sisälle" id="[id]" idstamp="[idstamp]" cnc_elemtype="[cnc_elemtype]">
        <settings>
          <masterelem>
            <layer>[layer;type=layer]</layer>
            <objparam name="iShowElemType">[showelemtype;default=1]</objparam>
            <objparam name="iShowID2D">1</objparam>
            <objparam name="iShowID3D">1</objparam>
          </masterelem>
          <slaveelem>
            <layer>[layer;type=layer]</layer>
            <objparam name="iShowElemType">0</objparam>
            <objparam name="iShowID2D">0</objparam>
            <objparam name="iShowID3D">0</objparam>
          </slaveelem>
        </settings>

        <!-- Content of <layers> will be added by custom element tool -->

        <!-- Projections for the element inside one frame from top to bottom -->
        <projections>
          <group layout="horizontal">
            <group layout="vertical">
              <cutlist layoutalign="-1" layoutmargins="0.1,0.1,0.1,0.1" layoutminwidth="2.0" layoutminheight="7.0" settingsref="[cutlist;default=cutlist;prompt=cutlist or cutlist_table]" elemid="0"></cutlist>
            </group>
            <group layout="vertical">
              <projection type="front" layoutmargins="2,0.5,1,1" boardpanels="[boardpanelsext;default=finish_ext,boarding_ext*]" exclude="[excludeext;default=intstud*,extstud*]">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
                <elemmarkings>
                  <opening text="#id#\n#width#\nx\n#height#">
                    <elemparam name="pen">1</elemparam>
                    <elemparam name="fontname">Arial</elemparam>
                    <elemparam name="fontsize">1.5</elemparam>
                    <elemparam name="fontstyle"></elemparam>
                    <elemparam name="just">center</elemparam>
                    <framelines create="[create_openig_frame_lines;default=0]">
                      <elemparam name="pen">1</elemparam>
                      <elemparam name="linetype">1</elemparam>
                    </framelines>
                  </opening>
                  <weight libname="{FD6C137D-C647-42FD-A904-181281909443}-{9060078A-0F41-48C8-8400-8E414A838053}" create="[show_weight_front;default=0]" text="[weight_text;default=(weight) KG]" units="[weight_unit;default=kg]">
                    <settings>
                      <layer>[layer_weight;type=layer]</layer>
                      <objparam name="iFill">*25*</objparam>
                      <objparam name="A">0.250</objparam>
                      <objparam name="B">0.325</objparam>
                    </settings>
                  </weight>
                </elemmarkings>
              </projection>
              <projection type="top" layoutmargins="2,0.5,0,0.5" boardpanels="[boardpanelstop;default=*]">
                <dimlines>
                  <dimline ref="wall_top"></dimline>
                </dimlines>
                <elemmarkings>
                  <weight libname="{FD6C137D-C647-42FD-A904-181281909443}-{9060078A-0F41-48C8-8400-8E414A838053}" create="[show_weight_top;default=0]" text="[weight_text;default=(weight) KG]" units="[weight_unit;default=kg]">
                    <settings>
                      <layer>[layer_weight;type=layer]</layer>
                      <objparam name="iFill">*25*</objparam>
                      <objparam name="A">0.250</objparam>
                      <objparam name="B">0.325</objparam>
                    </settings>
                  </weight>
                </elemmarkings>
              </projection>
              <projection type="back" layoutmargins="2,0.5,0,1" boardpanels="[boardpanelsint;default=boarding_int*]" exclude="[excludeint;default=intstud*,extstud*]">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
                <elemmarkings>
                  <opening text="#id#\n#width#\nx\n#height#">
                    <elemparam name="pen">1</elemparam>
                    <elemparam name="fontname">Arial</elemparam>
                    <elemparam name="fontsize">1.5</elemparam>
                    <elemparam name="fontstyle"></elemparam>
                    <elemparam name="just">center</elemparam>
                    <framelines create="[create_openig_frame_lines;default=0]">
                      <elemparam name="pen">1</elemparam>
                      <elemparam name="linetype">1</elemparam>
                    </framelines>
                  </opening>
                </elemmarkings>
              </projection>
              <elemstamp layoutalign="-1" layoutmargins="-2.2,0,0,0" layoutminwidth="10.0" layoutminheight="1.0" libname="{9FD03D30-6A12-4B0F-AB3A-01410A529E38}-{D420792D-C066-42CF-988C-9596DD164EB7}" settingsref="elemstamp">
                <script ref="elemstamp"></script>
              </elemstamp>
            </group>
          </group>
        </projections>
      </elemtemplate>

      <elemtemplate class="composite" templateid="composite_inout" templatename="Looked from in to out" templatename_fin="Katselusuunta sisältä ulos" id="[id]" idstamp="[idstamp]" cnc_elemtype="[cnc_elemtype]">
        <settings>
          <masterelem>
            <layer>[layer;type=layer]</layer>
            <objparam name="iShowElemType">[showelemtype;default=1]</objparam>
            <objparam name="iShowID2D">1</objparam>
            <objparam name="iShowID3D">1</objparam>
          </masterelem>
          <slaveelem>
            <layer>[layer;type=layer]</layer>
            <objparam name="iShowElemType">0</objparam>
            <objparam name="iShowID2D">0</objparam>
            <objparam name="iShowID3D">0</objparam>
          </slaveelem>
        </settings>

        <!-- Content of <layers> will be added by custom element tool -->

        <!-- Projections for the element inside one frame from top to bottom -->
        <projections>
          <group layout="horizontal">
            <group layout="vertical">
              <cutlist layoutalign="-1" layoutmargins="0.1,0.1,0.1,0.1" layoutminwidth="2.0" layoutminheight="7.0" settingsref="cutlist" elemid="0"></cutlist>
            </group>
            <group layout="vertical">
              <projection type="front" layoutmargins="2,0.5,1,1" boardpanels="[boardpanelsint;default=boarding_int*]" exclude="[excludeint;default=intstud*,extstud*]">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
                <elemmarkings>
                  <opening text="#id#\n#width#\nx\n#height#">
                    <elemparam name="pen">1</elemparam>
                    <elemparam name="fontname">Arial</elemparam>
                    <elemparam name="fontsize">1.5</elemparam>
                    <elemparam name="fontstyle"></elemparam>
                    <elemparam name="just">center</elemparam>
                    <framelines create="[create_openig_frame_lines;default=0]">
                      <elemparam name="pen">1</elemparam>
                      <elemparam name="linetype">1</elemparam>
                    </framelines>
                  </opening>
                  <weight libname="{FD6C137D-C647-42FD-A904-181281909443}-{9060078A-0F41-48C8-8400-8E414A838053}" create="[show_weight_front;default=0]" text="[weight_text;default=(weight) KG]" units="[weight_unit;default=kg]">
                    <settings>
                      <layer>[layer_weight;type=layer]</layer>
                      <objparam name="iFill">*25*</objparam>
                      <objparam name="A">0.250</objparam>
                      <objparam name="B">0.325</objparam>
                    </settings>
                  </weight>
                </elemmarkings>
              </projection>
              <projection type="top" layoutmargins="2,0.5,0,0.5" boardpanels="[boardpanelstop;default=*]">
                <dimlines>
                  <dimline ref="wall_top"></dimline>
                </dimlines>
                <elemmarkings>
                  <weight libname="{FD6C137D-C647-42FD-A904-181281909443}-{9060078A-0F41-48C8-8400-8E414A838053}" create="[show_weight_top;default=0]" text="[weight_text;default=(weight) KG]" units="[weight_unit;default=kg]">
                    <settings>
                      <layer>[layer_weight;type=layer]</layer>
                      <objparam name="iFill">*25*</objparam>
                      <objparam name="A">0.250</objparam>
                      <objparam name="B">0.325</objparam>
                    </settings>
                  </weight>
                </elemmarkings>
              </projection>
              <projection type="back" layoutmargins="2,0.5,0,1" boardpanels="[boardpanelsext;default=finish_ext,boarding_ext*]" exclude="[excludeext;default=intstud*,extstud*]">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
                <elemmarkings>
                  <opening text="#id#\n#width#\nx\n#height#">
                    <elemparam name="pen">1</elemparam>
                    <elemparam name="fontname">Arial</elemparam>
                    <elemparam name="fontsize">1.5</elemparam>
                    <elemparam name="fontstyle"></elemparam>
                    <elemparam name="just">center</elemparam>
                    <framelines create="[create_openig_frame_lines;default=0]">
                      <elemparam name="pen">1</elemparam>
                      <elemparam name="linetype">1</elemparam>
                    </framelines>
                  </opening>
                </elemmarkings>
              </projection>
              <elemstamp layoutalign="-1" layoutmargins="-2.2,0,0,0" layoutminwidth="10.0" layoutminheight="1.0" libname="{9FD03D30-6A12-4B0F-AB3A-01410A529E38}-{D420792D-C066-42CF-988C-9596DD164EB7}" settingsref="elemstamp">
                <script ref="elemstamp"></script>
              </elemstamp>
            </group>
          </group>
        </projections>
      </elemtemplate>

      <elemtemplate class="composite" templateid="composite_outin_single" templatename="Looked from out to in single projection" id="[id]" templatename_fin="Katselusuunta ulkoa sisälle yksi projektio" idstamp="[idstamp]" cnc_elemtype="[cnc_elemtype]">
        <settings>
          <masterelem>
            <layer>[layer;type=layer]</layer>
            <objparam name="iShowElemType">[showelemtype;default=1]</objparam>
            <objparam name="iShowID2D">1</objparam>
            <objparam name="iShowID3D">1</objparam>
          </masterelem>
          <slaveelem>
            <layer>[layer;type=layer]</layer>
            <objparam name="iShowElemType">0</objparam>
            <objparam name="iShowID2D">0</objparam>
            <objparam name="iShowID3D">0</objparam>
          </slaveelem>
        </settings>

        <!-- Content of <layers> will be added by custom element tool -->

        <!-- Projections for the element inside one frame from top to bottom -->
        <projections>
          <group layout="horizontal">
            <group layout="vertical">
              <cutlist layoutalign="-1" layoutmargins="0.1,0.1,0.1,0.1" layoutminwidth="2.0" layoutminheight="7.0" settingsref="[cutlist;default=cutlist;prompt=cutlist or cutlist_table]" elemid="0"></cutlist>
            </group>
            <group layout="vertical">
              <projection type="front" layoutmargins="2,0.5,1,1" boardpanels="[boardpanelsext;default=finish_ext,boarding_ext*]" exclude="[excludeext;default=intstud*,extstud*]">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
                <elemmarkings>
                  <opening text="#id#\n#width#\nx\n#height#">
                    <elemparam name="pen">1</elemparam>
                    <elemparam name="fontname">Arial</elemparam>
                    <elemparam name="fontsize">1.5</elemparam>
                    <elemparam name="fontstyle"></elemparam>
                    <elemparam name="just">center</elemparam>
                    <framelines create="[create_openig_frame_lines;default=0]">
                      <elemparam name="pen">1</elemparam>
                      <elemparam name="linetype">1</elemparam>
                    </framelines>
                  </opening>
                  <weight libname="{FD6C137D-C647-42FD-A904-181281909443}-{9060078A-0F41-48C8-8400-8E414A838053}" create="[show_weight_front;default=0]" text="[weight_text;default=(weight) KG]" units="[weight_unit;default=kg]">
                    <settings>
                      <layer>[layer_weight;type=layer]</layer>
                      <objparam name="iFill">*25*</objparam>
                      <objparam name="A">0.250</objparam>
                      <objparam name="B">0.325</objparam>
                    </settings>
                  </weight>
                </elemmarkings>
              </projection>
              <projection type="top" layoutmargins="2,0.5,0,0.5" boardpanels="[boardpanelstop;default=*]">
                <dimlines>
                  <dimline ref="wall_top"></dimline>
                </dimlines>
              </projection>
              <elemstamp layoutalign="-1" layoutmargins="-2.2,0,0,0" layoutminwidth="10.0" layoutminheight="1.0" libname="{9FD03D30-6A12-4B0F-AB3A-01410A529E38}-{D420792D-C066-42CF-988C-9596DD164EB7}" settingsref="elemstamp">
                <script ref="elemstamp"></script>
              </elemstamp>
            </group>
          </group>
        </projections>
      </elemtemplate>

      <elemtemplate class="composite" templateid="composite_inout_single" templatename="Looked from in to out single projection" templatename_fin="Katselusuunta sisältä ulos yksi projektio" id="[id]" idstamp="[idstamp]" cnc_elemtype="[cnc_elemtype]">
        <settings>
          <masterelem>
            <layer>[layer;type=layer]</layer>
            <objparam name="iShowElemType">[showelemtype;default=1]</objparam>
            <objparam name="iShowID2D">1</objparam>
            <objparam name="iShowID3D">1</objparam>
          </masterelem>
          <slaveelem>
            <layer>[layer;type=layer]</layer>
            <objparam name="iShowElemType">0</objparam>
            <objparam name="iShowID2D">0</objparam>
            <objparam name="iShowID3D">0</objparam>
          </slaveelem>
        </settings>

        <!-- Content of <layers> will be added by custom element tool -->

        <!-- Projections for the element inside one frame from top to bottom -->
        <projections>
          <group layout="horizontal">
            <group layout="vertical">
              <cutlist layoutalign="-1" layoutmargins="0.1,0.1,0.1,0.1" layoutminwidth="2.0" layoutminheight="7.0" settingsref="[cutlist;default=cutlist;prompt=cutlist or cutlist_table]" elemid="0"></cutlist>
            </group>
            <group layout="vertical">
              <projection type="front" layoutmargins="2,0.5,1,1" boardpanels="[boardpanelsint;default=boarding_int*]" exclude="[excludeint;default=intstud*,extstud*]">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
                <elemmarkings>
                  <opening text="#id#\n#width#\nx\n#height#">
                    <elemparam name="pen">1</elemparam>
                    <elemparam name="fontname">Arial</elemparam>
                    <elemparam name="fontsize">1.5</elemparam>
                    <elemparam name="fontstyle"></elemparam>
                    <elemparam name="just">center</elemparam>
                    <framelines create="[create_openig_frame_lines;default=0]">
                      <elemparam name="pen">1</elemparam>
                      <elemparam name="linetype">1</elemparam>
                    </framelines>
                  </opening>
                  <weight libname="{FD6C137D-C647-42FD-A904-181281909443}-{9060078A-0F41-48C8-8400-8E414A838053}" create="[show_weight_front;default=0]" text="[weight_text;default=(weight) KG]" units="[weight_unit;default=kg]">
                    <settings>
                      <layer>[layer_weight;type=layer]</layer>
                      <objparam name="iFill">*25*</objparam>
                      <objparam name="A">0.250</objparam>
                      <objparam name="B">0.325</objparam>
                    </settings>
                  </weight>
                </elemmarkings>
              </projection>
              <projection type="top" layoutmargins="2,0.5,0,0.5" boardpanels="[boardpanelstop;default=*]">
                <dimlines>
                  <dimline ref="wall_top"></dimline>
                </dimlines>
              </projection>
              <elemstamp layoutalign="-1" layoutmargins="-2.2,0,0,0" layoutminwidth="10.0" layoutminheight="1.0" libname="{9FD03D30-6A12-4B0F-AB3A-01410A529E38}-{D420792D-C066-42CF-988C-9596DD164EB7}" settingsref="elemstamp">
                <script ref="elemstamp"></script>
              </elemstamp>
            </group>
          </group>
        </projections>
      </elemtemplate>

      <elemtemplate class="composite" templateid="composite_fromtop" templatename="Floors/roofs looked from top" templatename_fin="Lattiat ja katot ylhäältä katsottuna" id="[id]" idstamp="[idstamp]" cnc_elemtype="[cnc_elemtype]">
        <settings>
          <masterelem>
            <layer>[layer;type=layer]</layer>
            <objparam name="iShowElemType">[showelemtype;default=1]</objparam>
            <objparam name="iShowID2D">1</objparam>
            <objparam name="iShowID3D">1</objparam>
          </masterelem>
          <slaveelem>
            <layer>[layer;type=layer]</layer>
            <objparam name="iShowElemType">0</objparam>
            <objparam name="iShowID2D">0</objparam>
            <objparam name="iShowID3D">0</objparam>
          </slaveelem>
        </settings>

        <!-- Content of <layers> will be added by custom element tool -->

        <!-- Projections for the element inside one frame from top to bottom -->
        <projections>
          <group layout="horizontal">
            <group layout="vertical">
              <cutlist layoutalign="-1" layoutmargins="0.1,0.1,0.1,0.1" layoutminwidth="2.0" layoutminheight="7.0" settingsref="[cutlist;default=cutlist;prompt=cutlist or cutlist_table]" elemid="0"></cutlist>
            </group>
            <group layout="vertical">
              <projection type="front" layoutmargins="2,0.5,1,1" boardpanels="[boardpanelsext;default=finish_ext,boarding_ext*]" exclude="[excludeext;default=intstud*,extstud*]" rotate="[rotproj;default=0]">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
                <elemmarkings>
                  <opening text="#id#\n#width#\nx\n#height#">
                    <elemparam name="pen">1</elemparam>
                    <elemparam name="fontname">Arial</elemparam>
                    <elemparam name="fontsize">1.5</elemparam>
                    <elemparam name="fontstyle"></elemparam>
                    <elemparam name="just">center</elemparam>
                    <framelines create="[create_openig_frame_lines;default=0]">
                      <elemparam name="pen">1</elemparam>
                      <elemparam name="linetype">1</elemparam>
                    </framelines>
                  </opening>
                  <weight libname="{FD6C137D-C647-42FD-A904-181281909443}-{9060078A-0F41-48C8-8400-8E414A838053}" create="[show_weight_front;default=0]" text="[weight_text;default=(weight) KG]" units="[weight_unit;default=kg]">
                    <settings>
                      <layer>[layer_weight;type=layer]</layer>
                      <objparam name="iFill">*25*</objparam>
                      <objparam name="A">0.250</objparam>
                      <objparam name="B">0.325</objparam>
                    </settings>
                  </weight>
                </elemmarkings>
              </projection>
              <projection type="bottom" layoutmargins="2,0.5,0,1" boardpanels="[boardpanelstop;default=*]">
                <dimlines>
                  <dimline ref="wall_top"></dimline>
                </dimlines>
              </projection>
              <!--projection type="back" layoutmargins="2,0.5,0,1" boardpanels="[boardpanelsint;default=boarding_int*]" exclude="[excludeint;default=intstud*,extstud*]">
                <dimlines>
                  <dimline ref="wall_elevation"></dimline>
                </dimlines>
                <elemmarkings>
                  <opening ref="mark_opening"></opening>
                </elemmarkings>
              </projection-->
              <elemstamp layoutalign="-1" layoutmargins="-2.2,0,0,0" layoutminwidth="10.0" layoutminheight="1.0" libname="{9FD03D30-6A12-4B0F-AB3A-01410A529E38}-{D420792D-C066-42CF-988C-9596DD164EB7}" settingsref="elemstamp">
                <script ref="elemstamp"></script>
              </elemstamp>
            </group>
          </group>
        </projections>
      </elemtemplate>


      <elemtemplate class="composite" templateid="composite_noproj" templatename="No projections" templatename_fin="Ei elementtikuvia" id="[id]" idstamp="[idstamp]" cnc_elemtype="[cnc_elemtype]">
        <settings>
          <masterelem>
            <layer>[layer;type=layer]</layer>
            <objparam name="iShowElemType">[showelemtype;default=1]</objparam>
            <objparam name="iShowID2D">1</objparam>
            <objparam name="iShowID3D">1</objparam>
          </masterelem>
          <slaveelem>
            <layer>[layer;type=layer]</layer>
            <objparam name="iShowElemType">0</objparam>
            <objparam name="iShowID2D">0</objparam>
            <objparam name="iShowID3D">0</objparam>
          </slaveelem>
        </settings>
      </elemtemplate>
    </elemtemplates>

    <options>
      <option id="doubletop" name="Double top" name_fin="Tuplayläjuoksu" name_nor="Dobbel Toppsvill" name_swe="Dubbla hammarband" name_ger="Doppelter oberer Lauf">
        <!-- If there is already grotop for the element, remove existing and set after running this option -->
        <reapply id="grotop"></reapply>
        <reapply id="markingslines"></reapply>
        <reapply id="markingsgro"></reapply>
        <reapply id="balktopint"></reapply>
        <reapply id="balktopext"></reapply>
        <reapply id="reinforceall"></reapply>
        <reapply id="reinforcebotint"></reapply>
        <reapply id="reinforcebotext"></reapply>
        <reapply id="autocuttopbot"></reapply>
        <script ref="doubletopbot">
          <![CDATA[
gbTop=true
gsTopBotGroup="top_force"
gsDoubleGroup="2ndtop_force"
  ]]>
        </script>
      </option>

      <option id="doublebot" name="Double bottom" name_fin="Tupla-alajuoksu" name_nor="Dobbel Bunnsvill" name_swe="Dubbel syll" name_ger="Doppelter unterer Lauf">
        <!-- If there is already grobot for the element, remove existing and set after running this option -->
        <reapply id="grobot"></reapply>
        <reapply id="markingslines"></reapply>
        <reapply id="markingsgro"></reapply>
        <reapply id="reinforceall"></reapply>
        <reapply id="reinforcebotint"></reapply>
        <reapply id="reinforcebotext"></reapply>
        <reapply id="markings"></reapply>
        <reapply id="autocuttopbot"></reapply>
        <script ref="doubletopbot">
          <![CDATA[
gbTop=false
gsTopBotGroup="bottom_force"
gsDoubleGroup="2ndbottom_force"
  ]]>
        </script>
      </option>


      <option id="balktopint" name="Top balk back" name_fin="Yläpalkki taka" name_nor="Topp Bjelke back" name_swe="Översta balk back" name_ger="Oberster Balken back">
        <script ref="balktop">
          <![CDATA[
gOptGroupName="balktopin"
gOptInOut="in"
]]>
        </script>
      </option>

      <option id="balktopext" name="Top balk front" name_fin="Yläpalkki etu" name_nor="Topp Bjelke Front" name_swe="Översta balk front" name_ger="Oberster Balken front">
        <script ref="balktop">
          <![CDATA[
gOptGroupName="balktopout"
gOptInOut="out"
]]>
        </script>
      </option>

      <option id="reinforcebotint" name="Bottom balk back" name_fin="Palkki ala taka" ordernum="999">
        <script ref="doubletopbot" ref1="reinforceall">
          g_issingle=true
          g_topin=0
          g_topout=0
          g_botin=1
          g_botout=0
          g_botinname="balkbottomin"
          g_botoutname="balkbottomout"
        </script>
      </option>

      <option id="reinforcebotext" name="Bottom balk front" name_fin="Palkki ala etu" ordernum="999">
        <script ref="doubletopbot" ref1="reinforceall">
          g_issingle=true
          g_topin=0
          g_topout=0
          g_botin=0
          g_botout=1
          g_botinname="balkbottomin"
          g_botoutname="balkbottomout"
        </script>
      </option>

      <option id="reinforceall" name="Reinforce ALL" name_fin="Palkit kaikkialle" ordernum="999">
        <script ref="doubletopbot" ref1="reinforceall">
        </script>
      </option>

      
      
      <option id="grobot" name="Grooves bottom 2 mm" name_fin="Urat ala 2 mm" name_nor="Spor Bunnsvill 2 mm" name_swe="Skarv nedre ända 2 mm" name_ger="Rillen unten 2mm" ordernum="999">
        <script ref="grotopbot">
          <![CDATA[
gOptGroTop=false
]]>
        </script>
      </option>

      <option id="grotop" name="Grooves top 2 mm" name_fin="Urat ylä 2 mm" name_nor="Spor Toppsvill 2 mm" name_swe="Skarv övre ända 2 mm" name_ger="Rillen oben 2mm" ordernum="999">
        <script ref="grotopbot">
          <![CDATA[
gOptGroTop=true
]]>
        </script>
      </option>

      <option id="markingsgro" name="Marking grooves" name_fin="Merkintäurat">
        <script ref="markingsgro">
        </script>
      </option>


      <option id="markingslines" name="Marking lines" name_fin="Merkitse ylä- ja alajuoksu" reapplyupdate="1" ordernum="1010">
        <script ref="markingslines">
        </script>
      </option>


      <option id="splitbot" name="Split bottom" name_fin="Alajuoksu kahdella kappaleella" name_nor="Splitt Bunnsvill" name_swe="Beskär nedre ända" name_ger="Zweiteliger unterer Lauf" ordernum="998">
        <script ref="splittopbot">
          <![CDATA[
gbTop=false
gsTopBotGroup="bottom_force"
gsSplitGroup="bottom_forcesplit"
]]>
        </script>
      </option>

      <!-- applystate="prespacing" means that option is applied before adding pieces from spacing rules -->
      <option id="openingsides" name="Planks to openings sides" name_fin="Laudat aukkojen sivuille" name_nor="Utfyllingsbord" name_swe="Reglar för öppningens sidor" name_ger="Bretter an Seiten der Öffnung" applystate="prespacing">
        <script ref="openingsides">
          <![CDATA[
]]>
        </script>
      </option>

      <option id="openingdouble" name="Double studs to opening sides" name_fin="Tuplatolppa aukkojen sivuille" applystate="prespacing">
        <reapply id="grotop"></reapply>
        <reapply id="markingslines"></reapply>
        <reapply id="markingsgro"></reapply>
        <script ref="openingdouble">
          <![CDATA[
]]>
        </script>
      </option>

      <option id="cornerdouble" name="Double studs to left and right" name_fin="Tuplatolppa reunoille" applystate="prespacing">
        <reapply id="grotop"></reapply>
        <reapply id="markingslines"></reapply>
        <reapply id="markingsgro"></reapply>
        <script ref="cornerdouble">
          <![CDATA[
]]>
        </script>
      </option>

      <option id="lintenoload" name="Lintels no load (set only)" name_fin="Aukonylityspalkki ei-kantava (vain aseta)" name_nor="Overdekkning Ikke bærende" name_swe="Överliggare utan belastning (fasta inställningar)" name_ger="Überbruckungsbalken unbelastet (nur setzen)">
        <script ref="lintels">
          <![CDATA[
function Set()
  DoLintelNoLoad()
end
]]>
        </script>
      </option>


      <option id="linteload" name="Lintels load bearing (set only)" name_fin="Aukonylityspalkki kantava (vain aseta)" name_nor="Overdekkning  bærende" name_swe="Överliggare med belastning (fasta inställningar)" name_ger="Überbruckungsbalken tragend (nur setzen)">
        <script ref="lintels">
          <![CDATA[
function Set()
  DoLintelLoad()
end
]]>
        </script>
      </option>


      <option id="lintelcustom" name="Lintels custom for selected pieces" name_fin="Aukonylityspalkki säädöillä valittuihin" name_nor="Overdekkning manuell" name_swe="Anpassad överliggare för valda delar" name_ger="Manueller Überbrückungsbalken" type="button">
        <reapply id="grotop"></reapply>
        <reapply id="markingslines"></reapply>
        <reapply id="markingsgro"></reapply>
        <script ref="lintels">
          <![CDATA[
-- Called before setting to individual elements
function OnPreSet()
  gtblSettings=nil
  gbCancel=false
end

function Set()
  if not DoLintelCustom() then
    gbCancel=true
  end
end
]]>
        </script>
      </option>

      <option id="windoorcuts" name="Cut window/door sills" name_fin="Ikkunan/oven alle viiste">
        <script ref="openingsbotcut">
        </script>
      </option>


      <option id="autocuttopbot" name="Automatic cut top and bottom" name_fin="Katko ylä- ja alajuoksu automaattisesti">
        <reapply id="markings"></reapply>
        <reapply id="markingsgro"></reapply>
        <script ref="autocuttopbot">
        </script>
      </option>

      <option id="openingsupport" name="Opening support" name_fin="Tolpat aukon vaakapuun reunoihin">
        <reapply id="grobot"></reapply>
        <reapply id="grotop"></reapply>
        <reapply id="markings"></reapply>
        <reapply id="markingsgro"></reapply>
        <script ref="openingsupport">
        </script>
      </option>
    </options>


    <corners>
      <!-- Script included to every corner type. Contains all corner types -->
      <common_script>
        <![CDATA[
-- ArchiFrame sets globals:
-- gAdjustElems true=type set from corner UI, set elements - no planking, false=called after creating planks - adjust planks
-- gbCornerFindOther, UI value for check box Find connecting corner
-- gbCornerAdjustOther, UI value for check box Adjust connecting corner
-- Type numbers: 1 long, 2 long left, 3 long right, 4=long left2, 5=long right2, 6=long corner to corner style, 7=Long double at the end
-- 8=Long left variation 3, 9=Long right variation 3 (also used for short)
-- 100 hedalm style, 101 anebyhus, 102 omatalo, 108=Nordic Baltic left, 109=Nordic Baltic right
-- 110=Plusshus long ext, 110=Plusshus short ext
-- 120=YIT long/short outer corner
-- 121=YIT long/short inner corner


-- Compatibility with older prog version
function IsFindOther()
  return gbCornerFindOther==nil or gbCornerFindOther==true
end

function IsAdjustOther()
  return gbCornerAdjustOther==nil or gbCornerAdjustOther==true
end


-- Dumps given variable into string
function DumpTblInt(o)
  local s,k,v
  
  if type(o) == 'table' then
    s = '{ '
    for k,v in pairs(o) do
      if type(k) ~= 'number' then k = '"'..k..'"' end
      s = s .. '['..k..'] = ' .. DumpTblInt(v) .. ','
    end
    s=s .. '} '
  else
    s=tostring(o)
  end
  return s
end


function DumpTbl(o)
  ac_environment("tolog", DumpTblInt(o))
end

function FindStuds()
  local tblStuds, plank, i, s, nStuds

  tblStuds={}
  nStuds=0

  tblStuds={}
  nStuds=0

  for i=1,gnPlanks do
    ac_objectopen(string.format("#%d", i))
    s=ac_objectget("iElemGroup")
    if string.match(s, "^vertical_%a*") then
      plank={}
      plank.elemgroup=s
      plank.elemdata=ac_objectget("#af_elemdata")
      if math.abs(plank.elemdata.x1-plank.elemdata.x2)<0.001 then
        plank.plankinfo=af_request("plankinfo")
        nStuds=nStuds+1
        tblStuds[nStuds]=plank
      end
    end
    ac_objectclose()
  end

  return tblStuds,nStuds
end


function FindThickerMat(orgMatId)
  local tblMat, i, v, matInfo

  
  matInfo=af_request("singlemat", orgMatId)
  
  tblMat=af_request("matlist")
  for i,v in pairs(tblMat) do
    if v.thickness>0.001 and v.thickness>matInfo.thickness+0.001 and v.thickness<matInfo.thickness*1.5 and math.abs(v.height-matInfo.height)<0.0009 then
      -- Return first applicable
      return v.id
	  end
  end

  return nil
end


-- Adjusts planks for given corner 1/2
-- nType  See top
-- Called with element planks opened
function DoLongPlanks(layerType, nCorner, nType, guidElem)
  local tblStuds, plank, i, s, nStuds, dir, nCreate

  gtblCreate={}
  nCreate=0
  
  if nCorner>2 then
    return
  end

  dir=1
  if nCorner==2 then
    -- Right
    dir=-1
  end

  ac_objectopen(guidElem)
  s=ac_objectget("iElemTypeId")
  ac_objectclose()
  if string.match(s, "%a*HOR$") then
    -- Horizontal element
    if layerType=="intstud" and nType>=2 and nType<=5 then
      -- Change top piece to bigger
      local i, s, newType, info

      af_request("elem_getpoly")
      

      for i=1,gnPlanks do
        ac_objectopen(string.format("#%d", i))
        s=ac_objectget("iElemGroup")
        if (s=="top_force" and nCorner==1) or (s=="bottom_force" and nCorner==2) then
          info=af_request("plankinfo")
          s=ac_objectget("iMatId")
          tblEdit={}
          tblEdit.elemdata=ac_objectget("#af_elemdata")
          tblEdit.guid=tblEdit.elemdata.ptr
          tblEdit.mat=nil
          
          if s=="45x45" then
            if af_request("singlemat", "45x95")~=nil then
              -- Ökoehituse
              tblEdit.mat="45x95"
            end
          end

          if tblEdit.mat==nil then
            -- Block
            tblEdit.mat="block"
            tblEdit.thickness=info.width
            tblEdit.height=info.height*2
          end

          tblEdit.elemdata.rotangle=-90
          if nCorner==2 then
            tblEdit.elemdata.rotangle=90
          end

          tblEdit.elemdata.x1=tblEdit.elemdata.x1-info.width*dir*0.5
          tblEdit.elemdata.z1=tblEdit.elemdata.z1+info.height*0.5
          tblEdit.elemdata.x2=tblEdit.elemdata.x2-info.width*dir*0.5
          tblEdit.elemdata.z2=tblEdit.elemdata.z1

          af_request("editplank", tblEdit)

        end
        ac_objectclose()
      end
    end
    return
  end

  af_request("elem_getpoly")
  tblStuds,nStuds=FindStuds()
  if #tblStuds<1 then
    return
  end

  -- Sort so that corner piece is the first one in the table
  if nCorner==1 then
    -- Left side
	  table.sort(tblStuds, function (n1, n2)
      return n1.elemdata.x1 < n2.elemdata.x1
	  end)
  else
    -- Right side
	  table.sort(tblStuds, function (n1, n2)
      return n1.elemdata.x1 > n2.elemdata.x1
	  end)
  end

  local nStud, stud, x1, x2, w2

  if layerType=="core" then
    -- core - Duplicate the corner stud
    nStud=1
    while tblStuds[1] and tblStuds[nStud] and math.abs(tblStuds[1].elemdata.x1 - tblStuds[nStud].elemdata.x1)<0.001 do
      stud=tblStuds[nStud]
    
      plank={}
      plank.guidsettings=stud.elemdata.ptr
      
      w2=stud.plankinfo.width*0.5
      if (nType>=2 and nType<=5) or nType==8 or nType==9 or nType==108 or nType==109 then
        -- L
        local orgMatId, addx
        
        ac_objectopen(stud.elemdata.ptr)
        orgMatId=ac_objectget("iMatId")
        ac_objectclose()
        addx=0
        
        if nType==8 or nType==9 or nType==108 or nType==109 then
          -- Duplicate end piece and make the last one slightly thicker - find the thicker material
          local newMat

          newMat=FindThickerMat(orgMatId)
          if newMat then
            local tblEdit, dx
            
            addx=(af_request("singlemat", newMat).thickness-stud.plankinfo.width) * 0.5
            dx=dir*addx

            tblEdit={}
            tblEdit.guid=stud.elemdata.ptr
            tblEdit.elemdata=stud.elemdata
            tblEdit.elemdata.x1=tblEdit.elemdata.x1+dx
            tblEdit.elemdata.x2=tblEdit.elemdata.x2+dx
            tblEdit.mat=newMat

            af_request("editplank", tblEdit)
          end
          
          -- Duplicate corner stud
          plank.group="vertical_force"
          plank.x1=stud.elemdata.x1+dir*(stud.plankinfo.width+addx)
          plank.y1=stud.elemdata.y1
          plank.x2=plank.x1
          plank.y2=stud.elemdata.y2
          plank.extendtoelem=1
          plank.id=orgMatId
          nCreate=nCreate+1
          gtblCreate[nCreate]=plank
          plank={}
          plank.guidsettings=stud.elemdata.ptr
          
          addx=addx+stud.plankinfo.width
        end
        
        if nType==4 or nType==5 or nType==8 or nType==9 or nType==108 or nType==109 then
          plank.group="vertical_force"
          plank.x1=stud.elemdata.x1+dir*(stud.plankinfo.width+stud.plankinfo.height+addx)
          plank.y1=stud.elemdata.y1
          plank.x2=plank.x1
          plank.y2=stud.elemdata.y2
          plank.extendtoelem=1
          plank.id=orgMatId
          nCreate=nCreate+1
          gtblCreate[nCreate]=plank
          plank={}
          plank.guidsettings=stud.elemdata.ptr
        end

        plank.group="vertical_force"
        plank.x1=stud.elemdata.x1+dir*(w2+addx)
        plank.y1=stud.elemdata.y1
        plank.x2=plank.x1
        plank.y2=stud.elemdata.y2
        if nType==3 or nType==5 or nType==9 then
          plank.zoff=w2
        else
          plank.zoff=stud.plankinfo.height-w2
        end
        plank.rotangle=-90*dir
        plank.extendtoelem=1
        plank.id=orgMatId
        x1=stud.elemdata.x1-dir*w2
        x2=plank.x1+dir*(w2+addx+stud.plankinfo.height)
        if nType>=4 then
          x2=x2+dir*stud.plankinfo.width
        end
      elseif nType==100 or nType==102 then
        -- Hedalm Long, Omatalo long duplicate end
        if nType==100 then
          plank.group="vertical_force"
          plank.x1=stud.elemdata.x1+dir*stud.plankinfo.width
          plank.y1=stud.elemdata.y1
          plank.x2=plank.x1
          plank.y2=stud.elemdata.y2
          plank.extendtoelem=1
          nCreate=nCreate+1
          gtblCreate[nCreate]=plank
        end
        
        -- Duplicate another
        plank={}
        plank.guidsettings=stud.elemdata.ptr
        plank.group="vertical_force"
        if nType==100 then
        plank.x1=stud.elemdata.x1+dir*(stud.plankinfo.height+0.063)     -- Gives 229-36/2 mm for 148 mm stud
        else
          plank.x1=stud.elemdata.x1+dir*(stud.plankinfo.height-stud.plankinfo.width)
        end
        plank.y1=stud.elemdata.y1
        plank.x2=plank.x1
        plank.y2=stud.elemdata.y2
        plank.extendtoelem=1

        x1=stud.elemdata.x1-dir*w2
        x2=plank.x1+dir*w2
      elseif nType==101 then
        -- Anybyhus duplicate closer
        plank.group="vertical_force"
        plank.x1=stud.elemdata.x1+dir*(stud.plankinfo.height-w2-w2)
        plank.y1=stud.elemdata.y1
        plank.x2=plank.x1
        plank.y2=stud.elemdata.y2
        plank.extendtoelem=1
        x1=stud.elemdata.x1-dir*w2
        x2=plank.x1+dir*w2
      elseif nType==110 then
        -- Plusshus duplicate further
        plank.group="vertical_force"
        plank.x1=stud.elemdata.x1+dir*(stud.plankinfo.height+0.045)
        plank.y1=stud.elemdata.y1
        plank.x2=plank.x1
        plank.y2=stud.elemdata.y2
        plank.extendtoelem=1
        x1=stud.elemdata.x1-dir*w2
        x2=plank.x1+dir*w2
      elseif nType==120 then
        -- YIT long ext
        -- Duplicate another
        plank={}
        plank.guidsettings=stud.elemdata.ptr
        plank.group="vertical_force"
        plank.x1=stud.elemdata.x1+dir*(stud.plankinfo.height-stud.plankinfo.width+0.009)
        plank.y1=stud.elemdata.y1
        plank.x2=plank.x1
        plank.y2=stud.elemdata.y2
        plank.extendtoelem=1

        x1=stud.elemdata.x1-dir*w2
        x2=plank.x1+dir*w2
      elseif nType==121 then
        -- YIT long ext inner
        -- Duplicate another
        plank={}
        plank.guidsettings=stud.elemdata.ptr
        plank.group="vertical_force"
        plank.x1=stud.elemdata.x1+dir*0.290
        plank.y1=stud.elemdata.y1
        plank.x2=plank.x1
        plank.y2=stud.elemdata.y2
        plank.extendtoelem=1

        x1=stud.elemdata.x1-dir*w2
        x2=plank.x1+dir*w2
      else
        -- Duplicate, types 1,6,7
        plank.group="vertical_force"
        if nType==7 then
          plank.x1=stud.elemdata.x1+dir*stud.plankinfo.width
        else
          plank.x1=stud.elemdata.x1+dir*stud.plankinfo.height
          if nType==1 then
            plank.x1=plank.x1-dir*w2
          end
        end
        plank.y1=stud.elemdata.y1
        plank.x2=plank.x1
        plank.y2=stud.elemdata.y2
        plank.extendtoelem=1
        x1=stud.elemdata.x1-dir*w2
        x2=plank.x1+dir*w2
      end

      nCreate=nCreate+1
      gtblCreate[nCreate]=plank
      af_request("elem_marknoplanks", x1, plank.y1-10, x2, plank.y2+10)
      
      nStud=nStud+1
    end
  elseif layerType=="intstud" and nType==120 then
    nStud=1
    while tblStuds[nStud] and math.abs(tblStuds[1].elemdata.x1 - tblStuds[nStud].elemdata.x1)<0.001 do
      stud=tblStuds[nStud]

      -- Corner piece duplicated
      plank={}
      plank.guidsettings=stud.elemdata.ptr
      plank.group="vertical_force"
      
      plank.x1=stud.elemdata.x1+dir*(0.009+0.198)
      plank.y1=stud.elemdata.y1
      plank.x2=plank.x1
      plank.y2=stud.elemdata.y2
      plank.extendtoelem=1
      plank.force=true
      
      nCreate=nCreate+1
      gtblCreate[nCreate]=plank

      nStud=nStud+1
    end

  elseif layerType=="intstud" and nType==121 then
    local x1, x2

    nStud=1
    while tblStuds[nStud] and math.abs(tblStuds[1].elemdata.x1 - tblStuds[nStud].elemdata.x1)<0.001 do
      stud=tblStuds[nStud]

      -- Corner piece rotated and different material
      tblEdit={}
      tblEdit.elemdata=stud.elemdata
      tblEdit.guid=tblEdit.elemdata.ptr
      tblEdit.mat="48x98"
          
      tblEdit.elemdata.rotangle=-90
      if nCorner==2 then
        tblEdit.elemdata.rotangle=90
      end

      tblEdit.elemdata.x1=tblEdit.elemdata.x1-0.048*dir*0.5
      tblEdit.elemdata.z1=tblEdit.elemdata.z1+0.048*0.5
      tblEdit.elemdata.x2=tblEdit.elemdata.x2-0.048*dir*0.5
      tblEdit.elemdata.z2=tblEdit.elemdata.z1
      af_request("editplank", tblEdit)
      
      x1=stud.elemdata.x1
      x2=stud.elemdata.x1+dir*0.098
      
      nStud=nStud+1
    end

    if x1 then
      af_request("elem_marknoplanks", x1, -10, x2, 10)
    end

  elseif layerType=="extstud" and (nType==8 or nType==9 or nType==108 or nType==109) then
    local finishThick
    
    finishThick=0.023
    nStud=1
    while math.abs(tblStuds[1].elemdata.x1 - tblStuds[nStud].elemdata.x1)<0.001 do
      stud=tblStuds[nStud]

      -- Corner piece, 
      plank={}
      plank.guidsettings=stud.elemdata.ptr
      plank.group="vertical_force"
      plank.id="block"
      plank.thickness=0.022
      plank.height=0.123
      
      plank.x1=stud.elemdata.x1-stud.plankinfo.height-stud.plankinfo.width-finishThick+plank.height
      plank.rotangle=90
      if dir<0 then
        plank.x1=stud.elemdata.x1+stud.plankinfo.height+stud.plankinfo.width+finishThick-plank.height
        plank.rotangle=-90
      end
      plank.y1=stud.elemdata.y1
      plank.x2=plank.x1
      plank.y2=stud.elemdata.y2
      plank.zoff=-finishThick-plank.thickness*0.5   -- change zoff sign if element built from in to out, 0.023 is thickness of finishing layer
      plank.extendtoelem=2
      plank.force=true
      
      nCreate=nCreate+1
      gtblCreate[nCreate]=plank

      nStud=nStud+1
    end

  elseif layerType=="intstud" or (layerType=="extstud" and nType==100) then
    -- intstud, rotate corner stud and move it
    local tblEdit, height, x1, x2, w2, orgMatId

    nStud=1
    while tblStuds[nStud] and math.abs(tblStuds[1].elemdata.x1 - tblStuds[nStud].elemdata.x1)<0.001 do
      stud=tblStuds[nStud]

      ac_objectopen(stud.elemdata.ptr)
      orgMatId=ac_objectget("iMatId")
      ac_objectclose()

      if math.abs(stud.elemdata.rotangle)<1 then
        w2=stud.plankinfo.width*0.5
        tblEdit=nil
        if layerType=="extstud" and nType==100 then
          -- do not rotate, change from 19x48 to 19x73
          if math.abs(stud.plankinfo.width-0.048)<0.001 then
            local newWidth
            
            newWidth=0.073
            stud.elemdata.x1=stud.elemdata.x1+(newWidth - stud.plankinfo.width)*0.5*dir
            stud.elemdata.x2=stud.elemdata.x1

            tblEdit={}
            tblEdit.guid=stud.elemdata.ptr
            tblEdit.elemdata=stud.elemdata
            tblEdit.mat="block"
            tblEdit.thickness=newWidth
            tblEdit.height=stud.plankinfo.height
            
            -- No planks area
            if nCorner==1 then
              x1=tblEdit.elemdata.x1
              x2=tblEdit.elemdata.x1+tblEdit.thickness
            elseif nCorner==2 then
              x1=tblEdit.elemdata.x1-tblEdit.thickness
              x2=tblEdit.elemdata.x1
            end

          end

        else
          -- intstud
          -- Zero rotate, set size and rotate
          stud.elemdata.rotangle=-90
          if nCorner==2 then
            stud.elemdata.rotangle=90
          end

          stud.elemdata.x1=stud.elemdata.x1-w2*dir
          stud.elemdata.z1=stud.elemdata.z1+stud.plankinfo.height*0.5
          stud.elemdata.x2=stud.elemdata.x2-w2*dir
          stud.elemdata.z2=stud.elemdata.z1

          tblEdit={}
          tblEdit.guid=stud.elemdata.ptr
          tblEdit.elemdata=stud.elemdata
          tblEdit.mat="block"
          tblEdit.thickness=stud.plankinfo.height
          tblEdit.height=stud.plankinfo.height*2
        
          if nType==100 then
            -- Hedalm Long, different material
            tblEdit.height=stud.plankinfo.width*2
          end
          
          if nType==110 then
            -- Plusshus, corner is bigger
            tblEdit.mat="45x195"
            tblEdit.thickness=stud.plankinfo.height
            tblEdit.height=0.195
          end
          
          -- No planks area
          if nCorner==1 then
            x1=tblEdit.elemdata.x1
            x2=tblEdit.elemdata.x1+tblEdit.height
          elseif nCorner==2 then
            x1=tblEdit.elemdata.x1-tblEdit.height
            x2=tblEdit.elemdata.x1
          end
        end

        if tblEdit then
          af_request("editplank", tblEdit)
          
          if nType==101 then
            -- Anebyhus corner, duplicate another rotated
            plank={}
            plank.guidsettings=tblEdit.guid           -- is a ptr
            plank.group="vertical_force"
            plank.id=tblEdit.mat
            plank.thickness=tblEdit.thickness
            plank.height=tblEdit.height
            plank.x1=stud.elemdata.x1+dir*(0.195)     -- HARD CODED core STUD
            plank.y1=stud.elemdata.y1
            plank.x2=plank.x1
            plank.y2=stud.elemdata.y2
            plank.zoff=stud.elemdata.z1
            plank.extendtoelem=1
            plank.rotangle=stud.elemdata.rotangle
            plank.force=true
            nCreate=nCreate+1
            gtblCreate[nCreate]=plank
            if nCorner==1 then
              x2=plank.x1+plank.height
            else
              x1=plank.x1-plank.height
            end
          elseif nType==110 then
            -- Plusshus corner, duplicate two 45x45 next to 45x195 at corner
            local plank2

            plank={}
            plank.guidsettings=stud.elemdata.ptr
            plank.id=orgMatId
            plank.group="vertical_force"
            plank.x1=stud.elemdata.x1+dir*tblEdit.height     -- HARD CODED core STUD
            plank.y1=stud.elemdata.y1
            plank.x2=plank.x1
            plank.y2=stud.elemdata.y2
            plank.zoff=stud.elemdata.z1
            plank.extendtoelem=1
            plank.rotangle=stud.elemdata.rotangle
            plank.force=true
            nCreate=nCreate+1
            gtblCreate[nCreate]=plank
            
            -- Another one
            plank2={}
            plank2.guidsettings=stud.elemdata.ptr
            plank2.id=orgMatId
            plank2.thickness=stud.plankinfo.width
            plank2.height=stud.plankinfo.height
            plank2.group="vertical_force"
            plank2.x1=plank.x1+dir*stud.plankinfo.height
            plank2.y1=stud.elemdata.y1
            plank2.x2=plank2.x1
            plank2.y2=stud.elemdata.y2
            plank2.zoff=stud.elemdata.z1
            plank2.extendtoelem=1
            plank2.rotangle=stud.elemdata.rotangle
            plank2.force=true
            nCreate=nCreate+1
            gtblCreate[nCreate]=plank2

            if nCorner==1 then
              x2=plank2.x1+stud.plankinfo.width
            else
              x1=plank2.x1-stud.plankinfo.width
            end
          end

--ac_environment("tolog", string.format("x1=%f x2=%f\n", x1, x2))
          af_request("elem_marknoplanks", x1, tblEdit.elemdata.y1-10, x2, tblEdit.elemdata.y2+10)

          -- Remove any stud in x1, x2 area (double studding)
          local scan, vscan
          for scan,vscan in ipairs(tblStuds) do
            if vscan.elemdata.x1-vscan.plankinfo.width*0.5+0.010>x1 and vscan.elemdata.x1+vscan.plankinfo.width*0.5-0.010<x2 and vscan.elemdata.ptr~=stud.elemdata.ptr then
--ac_environment("tolog", string.format("DEL vscan.elemdata.x1=%f\n", vscan.elemdata.x1))
              ac_objectopen(vscan.elemdata.ptr)
              af_request("delplank")
              ac_objectclose()
            end
          end
        end
      end
      nStud=nStud+1
    end
  end

  if nCreate>0 then
    af_request("elem_createplanks")
  end
  
end



-- Adjusts planks for given corner 1/2
-- nType  See top
-- Called with element planks opened
function DoShortPlanks(layerType, nCorner, nType, guidElem)
  local tblStuds, plank, i, s, nStuds, dir, nCreate

  gtblCreate={}
  nCreate=0
  
  if nCorner>2 then
    return
  end

  ac_objectopen(guidElem)
  s=ac_objectget("iElemTypeId")
  ac_objectclose()
  if string.match(s, "%a*HOR$") then
    return
  end

  af_request("elem_getpoly")
  tblStuds,nStuds=FindStuds()
  if #tblStuds<1 then
    return
  end

  -- Sort so that corner piece is the first one in the table
  if nCorner==1 then
    -- Left side
    dir=1
	  table.sort(tblStuds, function (n1, n2)
      return n1.elemdata.x1 < n2.elemdata.x1
	  end)
  else
    -- Right side
    dir=-1
	  table.sort(tblStuds, function (n1, n2)
      return n1.elemdata.x1 > n2.elemdata.x1
	  end)
  end

  local nStud, stud, x1, x2, w2

  if layerType=="extstud" and (nType==8 or nType==9 or nType==108 or nType==109) then
    local finishThick
    
    finishThick=0.023
    nStud=1
    while math.abs(tblStuds[1].elemdata.x1 - tblStuds[nStud].elemdata.x1)<0.001 do
      stud=tblStuds[nStud]

      -- Corner piece, 
      plank={}
      plank.guidsettings=stud.elemdata.ptr
      plank.group="vertical_force"
      plank.id="block"
      plank.thickness=0.022
      plank.height=0.148
      
      plank.x1=stud.elemdata.x1-stud.plankinfo.height-stud.plankinfo.width-finishThick-plank.thickness+plank.height
      plank.rotangle=90
      if dir<0 then
        plank.x1=stud.elemdata.x1+stud.plankinfo.height+stud.plankinfo.width+finishThick+plank.thickness-plank.height
        plank.rotangle=-90
      end
      plank.y1=stud.elemdata.y1
      plank.x2=plank.x1
      plank.y2=stud.elemdata.y2
      plank.zoff=-finishThick-plank.thickness*0.5   -- change zoff sign if element built from in to out, 0.023 is thickness of finishing layer
      plank.extendtoelem=2
      plank.force=true
      
      nCreate=nCreate+1
      gtblCreate[nCreate]=plank

      nStud=nStud+1
    end
  elseif layerType=="intstud" and nType==121 then
    nStud=1
    while tblStuds[nStud] and math.abs(tblStuds[1].elemdata.x1 - tblStuds[nStud].elemdata.x1)<0.001 do
      stud=tblStuds[nStud]

      -- Corner piece rotated and different material
      tblEdit={}
      tblEdit.elemdata=stud.elemdata
      tblEdit.guid=tblEdit.elemdata.ptr
      tblEdit.mat="48x148"
          
      tblEdit.elemdata.rotangle=-90
      if nCorner==2 then
        tblEdit.elemdata.rotangle=90
      end

      tblEdit.elemdata.x1=tblEdit.elemdata.x1-0.048*dir*0.5
      tblEdit.elemdata.z1=tblEdit.elemdata.z1+0.048*0.5
      tblEdit.elemdata.x2=tblEdit.elemdata.x2-0.048*dir*0.5
      tblEdit.elemdata.z2=tblEdit.elemdata.z1
      af_request("editplank", tblEdit)
      
      x1=stud.elemdata.x1
      x2=stud.elemdata.x1+dir*0.148
      
      nStud=nStud+1
    end

    if x1 then
      af_request("elem_marknoplanks", x1, -10, x2, 10)
    end
 end

  if nCreate>0 then
    af_request("elem_createplanks")
  end
  
end


-- Save connections for this script to be able to make shape for related element(s)
function AddConn(guidthis, cornerthis, relData)
  if not IsAdjustOther() then
    return
  end

  local item

--ac_environment("tolog", string.format("guidthis=%s, cornerthis=%s, guidother=%s, cornerother=%s\n", tostring(guidthis), tostring(cornerthis), tostring(guidother), tostring(cornerother)))
  item={}
  item.guidthis   =guidthis
  item.cornerthis =cornerthis
  item.guidother  =relData.this.guidother
  item.cornerother=relData.other.reltype
  item.reldata    =relData                -- Also full relData
  gtblConn[#gtblConn+1]=item
end


-- Handles every layer not having tblParent[nLayer].handled set to true
function DoDefaultLong(tblParent, nCorner, coreElem, nType)
  if not gAdjustElems then
    return
  end

  local i, v, off

  if nType==nil then
    nType=1
  end
  
  if nType==110 then
    return      -- NOP for Plusshus
  end

  -- Keep core in place, move all others
  for i,v in ipairs(tblParent.tblelems) do
    if not v.handled then
      af_request("elem_openlayer", v.guid)
      off=nil
      if nType==100 or nType==102 then
        -- Hedalm
        if nCorner==1 then
          off=-v.x1off
        elseif nCorner==2 then
          off=-v.x2off
        end

        if off then
          if v.type=="panel_ext" then
            off=off+0.049
          elseif v.type=="boarding_ext" then
            off=off+v.thickness
          end
        end
      elseif nType==120 then
        -- YIT ext 1
        if nCorner==1 then
          off=-v.x1off
        elseif nCorner==2 then
          off=-v.x2off
        end

        if off then
          if v.type=="finish_ext" then
            off=off+0.034
          elseif v.type=="boarding_int" then
            off=off-0.009-0.198
          end
        end
      elseif nType==121 then
        -- YIT ext int 1
        if nCorner==1 then
          off=-v.x1off
        elseif nCorner==2 then
          off=-v.x2off
        end

        if off then
          if v.type=="finish_ext" or string.match(v.type, "^extstud%a*") then
            off=off-0.305
          elseif v.type=="boarding_int" or string.match(v.type, "^intstud%a*") then
            off=off+0.048
          end
        end
      else
        if nType==101 then
          -- This type is made from int to ext
          off=(v.zoff+v.thickness)-(coreElem.zoff+coreElem.thickness)
          if v.type=="intstud" then
            -- Extend this as far as core
            off=off+coreElem.thickness
          end
        else
          -- Default ext to int
          off=coreElem.zoff-v.zoff
        end
        if nCorner==1 then
          off=off-v.x1off
        elseif nCorner==2 then
          off=off-v.x2off
        elseif nCorner==3 then
          off=off-v.y1off
        elseif nCorner==4 then
          off=off-v.y2off
        else
          error(string.format("bad corner %s", tostring(nCorner)))
        end
      end
      if gAdjustElems and off then
        af_request("elem_moveside", nCorner, off)
      end
      af_request("elem_closelayer")
    end
  end
end


-- Looks for core layer relation and returns information for long core layer
-- layerType  nil="core", others=override
-- Returns (anything can be nil): relFound, x1offCore, x2offCore, coreLayer
function FindCoreRel(tblParent, nCorner, layerType)
  if not IsFindOther() then
    return
  end

  local i, v, tblRel, coreLayer
  local iRel, vRel, relFound
  local x1offCore, x2offCore

  if layerType==nil then
    layerType="core"
  end

  for i,v in ipairs(tblParent.tblelems) do
    if v.type==layerType then
      coreLayer=v
      tblRel=af_request("elem_getrelations", v.guid)
      if tblRel then
        if nCorner==1 then
          for iRel,vRel in ipairs(tblRel) do
            if vRel.this.reltype==1 then
              relFound=vRel
              x1offCore=-vRel.this.x1
              break
            end
          end
        elseif nCorner==2 then
          for iRel,vRel in ipairs(tblRel) do
            if vRel.this.reltype==2 then
              relFound=vRel
              x2offCore=vRel.this.x2-v.xsize
              break
            end
          end
        end
      end
    end
  end
  
  return relFound, x1offCore, x2offCore, coreLayer
end


function DoWithRelLong(tblParent, nCorner, coreElem, nType)
  local i, v, off, tblRel
  local iRel, vRel, relFound, reFoundCore
  local x1offCore, x2offCore      -- How much the core must be adjusted

  reFoundCore, x1offCore, x2offCore=FindCoreRel(tblParent, nCorner)
--ac_environment("tolog", string.format("LONG %s x1offCore=%s, x2offCore=%s", tostring(nType), tostring(x1offCore), tostring(x2offCore)))
  
  if nType==100 or nType==102 then
    -- Hedalm long, find core relation
    for i,v in ipairs(tblParent.tblelems) do
      af_request("elem_openlayer", v.guid)
      off=nil
      if nCorner==1 and x1offCore then
        off=-v.x1off+x1offCore
        if v.type=="panel_ext" then
          off=off+0.049
        elseif v.type=="boarding_ext" then
          off=off+v.thickness
        end
      elseif nCorner==2 and x2offCore then
        off=-v.x2off+x2offCore
        if v.type=="panel_ext" then
          off=off+0.049
        elseif v.type=="boarding_ext" then
          off=off+v.thickness
        end
      end
      if off then
        AddConn(v.guid, nCorner, reFoundCore)
        if gAdjustElems then
          af_request("elem_moveside", nCorner, off)
        end
        v.handled=true
      end
      af_request("elem_closelayer")
    end

    return
  end

  if nType==120 then
    -- YIT Long 1
    for i,v in ipairs(tblParent.tblelems) do
      af_request("elem_openlayer", v.guid)
      off=nil
      if nCorner==1 and x1offCore then
        off=-v.x1off+x1offCore+0.009        -- Add crossing wall's windshield board thickness
        if v.type=="finish_ext" then
          off=off+0.034
        elseif v.type=="boarding_int" then
          off=off-0.009-0.198
        end
      elseif nCorner==2 and x2offCore then
        off=-v.x2off+x2offCore+0.009
        if v.type=="finish_ext" then
          off=off+0.034
        elseif v.type=="boarding_int" then
          off=off-0.009-0.198
        end
      end
      if off then
        AddConn(v.guid, nCorner, reFoundCore)
        if gAdjustElems then
          af_request("elem_moveside", nCorner, off)
        end
        v.handled=true
      end
      af_request("elem_closelayer")
    end

    return
  end
  
  if nType==121 then
    -- YIT Long inner 1
    for i,v in ipairs(tblParent.tblelems) do
      af_request("elem_openlayer", v.guid)
      off=nil
      if nCorner==1 and x1offCore then
        off=-v.x1off+x1offCore
        if v.type=="finish_ext" or string.match(v.type, "^extstud%a*") then
          off=off-0.290
        elseif v.type=="boarding_int" or v.type=="intstud" then
          off=off+0.048
        end
      elseif nCorner==2 and x2offCore then
        off=-v.x2off+x2offCore
        if v.type=="finish_ext" or string.match(v.type, "^extstud%a*") then
          off=off-0.290
        elseif v.type=="boarding_int" or v.type=="intstud" then
          off=off+0.048
        end
      end
      if off then
        AddConn(v.guid, nCorner, reFoundCore)
        if gAdjustElems then
          af_request("elem_moveside", nCorner, off)
        end
        v.handled=true
      end
      af_request("elem_closelayer")
    end

    return
  end
  
  -- Check if built from out to in
  local firstExt, s
  
  firstExt=false
  s=tblParent.tblelems[1].type
  if string.match(s, "_ext.*") or string.match(s, "^ext.*") then
    firstExt=true
  end
--ac_environment("tolog", string.format("tblParent.tblelems[1].type=%s firstExt=%s", tblParent.tblelems[1].type, tostring(firstExt)))

  -- Match to related element
  for i,v in ipairs(tblParent.tblelems) do
    tblRel=nil
    if IsFindOther() then
      tblRel=af_request("elem_getrelations", v.guid)
    end
    
    if tblRel and (gGuidElemToPlank==nil or gGuidElemToPlank==v.guid) then
      af_request("elem_openlayer", v.guid)
      off=nil
      if nCorner==1 then
        for iRel,vRel in ipairs(tblRel) do
          if vRel.this.reltype==1 then
            relFound=vRel
            off=-vRel.this.x1
            break
          end
        end
        
      elseif nCorner==2 then
        for iRel,vRel in ipairs(tblRel) do
          if vRel.this.reltype==2 then
            relFound=vRel
            off=vRel.this.x2-v.xsize
--ac_environment("tolog", string.format("vRel.this.x2=%f vRel.this.angledeg=%f vRel.other.angledeg=%f v.xsize=%f", vRel.this.x2, vRel.this.angledeg, vRel.other.angledeg, v.xsize))
            break
          end
        end
      else
        error(string.format("bad corner %s", tostring(nCorner)))
      end

      s=v.type
      if relFound and (nType==8 or nType==9 or nType==108 or nType==109 or nType==110) and (string.match(s, "_ext.*") or string.match(s, "^ext.*")) and (s~="boarding_ext" or nType==110) then
        -- Make extstud, finish_ext shorter (adjust to boarding_ext) if found
        -- For type 110/Plusshus: Adjust to main framing
        local relBoard, x1offBoard, x2offBoard, boardLayer

        if nType==110 then
          relBoard, x1offBoard, x2offBoard, boardLayer=FindCoreRel(tblParent, nCorner, "core")
        else
          relBoard, x1offBoard, x2offBoard, boardLayer=FindCoreRel(tblParent, nCorner, "boarding_ext")
        end
        if relBoard then
          if (relFound.this.angledeg>0 and firstExt==true) or (relFound.this.angledeg<0 and firstExt==false) then
            -- Outer corner
            if nCorner==1 then
              off=boardLayer.x1off-v.x1off
              off=off+x1offBoard
            elseif nCorner==2 then
              off=boardLayer.x2off-v.x2off
              off=off+x2offBoard
            end
          else
            -- Inner corner, reduce thickness of all layers from this to the last exterior layer
            local i2
            
            if firstExt then
              i2=i
              while i2>0 do
                off=off-tblParent.tblelems[i2].thickness
                i2=i2-1
              end
            else
              i2=i
              while tblParent.tblelems[i2]~=nil do
                off=off-tblParent.tblelems[i2].thickness
                i2=i2+1
              end
            end
          end
        end
      end

      if off then
        if (nType==101 or nType==110) and v.type=="intstud" then
          -- Extend this as far as core
          off=off+coreElem.thickness
        end

        AddConn(v.guid, nCorner, relFound)
        if gAdjustElems then
          af_request("elem_moveside", nCorner, off)
        end
        v.handled=true
      end
      af_request("elem_closelayer")
    end
  end
end


-- Handles every layer not having tblParent[nLayer].handled set to true
function DoDefaultShort(tblParent, nCorner, coreElem, nType)
  local i, v, off

  if nType==110 then
    return      -- NOP for Plusshus
  end

  -- Keep core in place, move all others
  for i,v in ipairs(tblParent.tblelems) do
    if not v.handled then
      af_request("elem_openlayer", v.guid)
      off=nil
      if nType==100 then
        -- Hedalm
        if nCorner==1 then
          off=-v.x1off
        elseif nCorner==2 then
          off=-v.x2off
        end

        if off then
          if v.type=="panel_ext" then
            off=off+coreElem.thickness+0.061+0.028
          elseif v.type=="extstud" or v.type=="boarding_ext" then
            off=off+coreElem.thickness+0.061
          end
        end
      elseif nType==120 then
        -- YIT Short ext 1
        if nCorner==1 then
          off=-v.x1off
        elseif nCorner==2 then
          off=-v.x2off
        end

        if off then
          if string.match(v.type, "^extstud%a*") then
            off=off+0.274
          elseif string.match(v.type, "^finish_ext%a*") then
            off=off+0.330
          end
        end
      elseif nType==121 then
        -- YIT Short ext inner 1
        if nCorner==1 then
          off=-v.x1off
        elseif nCorner==2 then
          off=-v.x2off
        end

        if off then
          -- Should stop inner studding&boarding to next stud
        end
      elseif nType==102 then
        -- Omatalo
        if nCorner==1 then
          off=-v.x1off
        elseif nCorner==2 then
          off=-v.x2off
        end

        if off then
          if v.type=="boarding_ext" then
            off=off+coreElem.thickness+0.013
          end
        end
      else
        if nType==101 then
          -- This type is made from int to ext
          off=(v.zoff)-(coreElem.zoff)
          
          if nType==101 and v.type=="core" and tblParent.tblelems[i-1]~=nil and tblParent.tblelems[i-1].type=="intstud" then
            -- Core gives space for long one's intstud
            off=off-tblParent.tblelems[i-1].thickness
          end

        else
          -- Default ext to int
          off=(coreElem.zoff+coreElem.thickness)-(v.zoff+v.thickness)
        end
        if nCorner==1 then
          off=off-v.x1off
        elseif nCorner==2 then
          off=off-v.x2off
        elseif nCorner==3 then
          off=off-v.y1off
        elseif nCorner==4 then
          off=off-v.y2off
        else
          error(string.format("bad corner %s", tostring(nCorner)))
        end
      end
      if gAdjustElems and off then
        af_request("elem_moveside", nCorner, off)
      end
      af_request("elem_closelayer")
    end
  end
end


function DoWithRelShort(tblParent, nCorner, coreElem, nType)
  local i, v, off, tblRel
  local iRel, vRel, relFound


  if nType==100 then
    local x1offCore, x2offCore, coreLayer      -- How much the core must be adjusted
    
    -- Hedalm short, find core relation
    relFound, x1offCore, x2offCore, coreLayer=FindCoreRel(tblParent, nCorner)

    for i,v in ipairs(tblParent.tblelems) do
      af_request("elem_openlayer", v.guid)
      off=nil
      if nCorner==1 and x1offCore then
        off=-v.x1off+x1offCore-coreLayer.thickness-0.061
        if v.type=="panel_ext" then
          off=off+coreLayer.thickness+0.061+0.028
        elseif v.type=="extstud" or v.type=="boarding_ext" then
          off=off+coreLayer.thickness+0.061
        end
      elseif nCorner==2 and x2offCore then
        off=-v.x2off+x2offCore-coreLayer.thickness-0.061
        if v.type=="panel_ext" then
          off=off+coreLayer.thickness+0.061+0.028
        elseif v.type=="extstud" or v.type=="boarding_ext" then
          off=off+coreLayer.thickness+0.061
        end
      end
      if off then
        AddConn(v.guid, nCorner, relFound)
        if gAdjustElems then
          af_request("elem_moveside", nCorner, off)
        end
        v.handled=true
      end
      af_request("elem_closelayer")
    end

    return
  elseif nType==120 then
    local x1offCore, x2offCore, coreLayer      -- How much the core must be adjusted
    
    -- YIT short, find core relation
    relFound, x1offCore, x2offCore, coreLayer=FindCoreRel(tblParent, nCorner)

    for i,v in ipairs(tblParent.tblelems) do
      af_request("elem_openlayer", v.guid)
      off=nil
      if nCorner==1 and x1offCore then
        off=-v.x1off+x1offCore-coreLayer.thickness-0.048-0.028
      elseif nCorner==2 and x2offCore then
        off=-v.x2off+x2offCore-coreLayer.thickness-0.048-0.028
      end
      if off then
        if v.type=="boarding_int" then
          off=off
        elseif string.match(v.type, "^extstud%a*") then
          off=off+coreLayer.thickness+0.048+0.028
        elseif string.match(v.type, "^finish_ext%a*") then
          off=off+coreLayer.thickness+0.048+0.028+0.009+0.045+0.002
        end
        AddConn(v.guid, nCorner, relFound)
        if gAdjustElems then
          af_request("elem_moveside", nCorner, off)
        end
        v.handled=true
      end
      af_request("elem_closelayer")
    end

    return
    
  elseif nType==121 then
    local x1offCore, x2offCore, coreLayer      -- How much the core must be adjusted
    
    -- YIT short inner, find core relation
    relFound, x1offCore, x2offCore, coreLayer=FindCoreRel(tblParent, nCorner)

    for i,v in ipairs(tblParent.tblelems) do
      af_request("elem_openlayer", v.guid)
      off=nil
      if nCorner==1 and x1offCore then
        off=-v.x1off+x1offCore-coreLayer.thickness-0.024
      elseif nCorner==2 and x2offCore then
        off=-v.x2off+x2offCore-coreLayer.thickness-0.024
      end
      if off then
        if v.type=="boarding_int" then
          off=off+0.283
        elseif string.match(v.type, "^intstud%a*") then
          off=off+0.100
        end
        AddConn(v.guid, nCorner, relFound)
        if gAdjustElems then
          af_request("elem_moveside", nCorner, off)
        end
        v.handled=true
      end
      af_request("elem_closelayer")
    end

    return
  elseif nType==102 then
    -- Omatalo
    local x1offCore, x2offCore, coreLayer      -- How much the core must be adjusted
    
    -- Hedalm short, find core relation
    relFound, x1offCore, x2offCore, coreLayer=FindCoreRel(tblParent, nCorner)
    
    for i,v in ipairs(tblParent.tblelems) do
      af_request("elem_openlayer", v.guid)
      off=nil
      if nCorner==1 and x1offCore then
        off=-v.x1off+x1offCore-coreLayer.thickness-0.013
        if v.type=="core" then
          off=off-0.010
        elseif v.type=="boarding_ext" then
          off=off+coreLayer.thickness+0.013
        end
      elseif nCorner==2 and x2offCore then
        off=-v.x1off+x2offCore-coreLayer.thickness-0.013
        if v.type=="core" then
          off=off-0.010
        elseif v.type=="boarding_ext" then
          off=off+coreLayer.thickness+0.013
        end
      end
      if off then
        AddConn(v.guid, nCorner, relFound)
        if gAdjustElems then
          af_request("elem_moveside", nCorner, off)
        end
        v.handled=true
      end
      af_request("elem_closelayer")
    end

    return
  elseif nType==110 then
    -- Plusshus (short)
    local x1offCore, x2offCore, coreLayer      -- How much the core must be adjusted
    
    relFound, x1offCore, x2offCore, coreLayer=FindCoreRel(tblParent, nCorner)
    for i,v in ipairs(tblParent.tblelems) do
      af_request("elem_openlayer", v.guid)
      off=nil
      if nCorner==1 and x1offCore then
        off=-v.x1off+x1offCore-coreLayer.thickness-0.053      -- 0.045+0.008
        if string.match(v.type, "_ext.*") or string.match(v.type, "^ext.*") then
          off=off+coreLayer.thickness+0.053
        end
      elseif nCorner==2 and x2offCore then
        off=-v.x2off+x2offCore-coreLayer.thickness-0.053
        if string.match(v.type, "_ext.*") or string.match(v.type, "^ext.*") then
          off=off+coreLayer.thickness+0.053
        end
      end
      if off then
        AddConn(v.guid, nCorner, relFound)
        if gAdjustElems then
          af_request("elem_moveside", nCorner, off)
        end
        v.handled=true
      end
      af_request("elem_closelayer")
    end

    return
  end

  -- Check if built from out to in
  local firstExt, s
  
  firstExt=false
  s=tblParent.tblelems[1].type
  if string.match(s, "_ext.*") or string.match(s, "^ext.*") then
    firstExt=true
  end

  for i,v in ipairs(tblParent.tblelems) do
    tblRel=nil
    if IsFindOther() then
      tblRel=af_request("elem_getrelations", v.guid)
    end
    if tblRel then
      af_request("elem_openlayer", v.guid)
      off=nil
      if nCorner==1 then
        for iRel,vRel in ipairs(tblRel) do
          if vRel.this.reltype==1 then
            relFound=vRel
            off=-(vRel.this.x2-vRel.this.x2off)
            break
          end
        end
      elseif nCorner==2 then
        for iRel,vRel in ipairs(tblRel) do
          if vRel.this.reltype==2 then
            relFound=vRel
            off=(vRel.this.x1+vRel.this.x1off)-v.xsize
            break
          end
        end
      else
        error(string.format("bad corner %s", tostring(nCorner)))
      end

      s=v.type
      if relFound and (nType==8 or nType==9 or nType==108 or nType==109) and (string.match(s, "_ext.*") or string.match(s, "^ext.*")) and s~="boarding_ext" then
        -- Make extstud, finish_ext shorter if found
        local relBoard, x1offBoard, x2offBoard, boardLayer

        relBoard, x1offBoard, x2offBoard, boardLayer=FindCoreRel(tblParent, nCorner, "boarding_ext")
        if relBoard then
          local i2

          if (relFound.this.angledeg>0 and firstExt==true) or (relFound.this.angledeg<0 and firstExt==false) then
            -- Outer corner
            i2=i
            while true do
              if firstExt then
                i2=i2+1
              else
                i2=i2-1
              end
              if tblParent.tblelems[i2]==nil then
                break
              end
              s=tblParent.tblelems[i2].type
              if s=="boarding_ext" or not (string.match(s, "_ext.*") or string.match(s, "^ext.*")) then
                break
              end
              off=off-tblParent.tblelems[i2].thickness
            end
          else
            -- Inner corner, reduce thickness of all layers from this to the last exterior layer
            i2=i
            while true do
              if firstExt then
                i2=i2-1
              else
                i2=i2+1
              end
              if i2<1 or i2>#tblParent.tblelems then
                break
              end
              off=off-tblParent.tblelems[i2].thickness
            end
          end
        end
      end

      if off then
        if nType==101 and v.type=="core" and tblParent.tblelems[i-1]~=nil and tblParent.tblelems[i-1].type=="intstud" then
          -- Core gives space for long one's intstud
          off=off-tblParent.tblelems[i-1].thickness
        end

        AddConn(v.guid, nCorner, relFound)
        if gAdjustElems then
          af_request("elem_moveside", nCorner, off)
        end
        v.handled=true
      end
      af_request("elem_closelayer")
    end
  end
end


-- nType as for creating planks: nil=no specs
function SetLongElem( sSettings, guidElem, nCorner, nType )
  local tblParent
  local coreElem, nSaveElems

  gtblConn={}
  tblParent=af_request("elem_openparent", guidElem)

  -- Find core layer
  coreElem=nil
  for i,v in ipairs(tblParent.tblelems) do
    if v.type=="core" then
      coreElem=v
      break
    end
  end

  if coreElem==nil then
    af_request("elem_closeparent", 0)
    return
  end
  
  gGuidElemToPlank=guidElem
  nSaveElems=0
  if gAdjustElems then
    nSaveElems=1
    gGuidElemToPlank=nil
  end

  DoWithRelLong(tblParent, nCorner, coreElem, nType)
  DoDefaultLong(tblParent, nCorner, coreElem, nType)
  af_request("elem_closeparent", nSaveElems)
  
  if #gtblConn>0 and gAdjustElems then
    -- To other part
    local v
    
    v=gtblConn[1]
    
    if v.cornerother==1 or v.cornerother==2 then
      v.idother="short"     -- To be saved into other element's settings
      if nType==100 then
        v.idother="short_hedalm"
      elseif nType==101 then
        v.idother="short_anebyhus"
      elseif nType==102 then
        v.idother="short_omatalo"
      elseif nType==8 or nType==9 or nType==108 or nType==109 then
        v.idother="short3"
      elseif nType==110 then
        v.idother="plusshus_short_ext1"
      elseif nType==120 then
        v.idother="yit_short1"
      elseif nType==121 then
        v.idother="yit_shortint1"
      end
      tblParent=af_request("elem_openparent", v.guidother)
      DoWithRelShort(tblParent, v.cornerother, nil, nType)
      af_request("elem_closeparent", 1)
    end
  end
end


function SetShortElem( sSettings, guidElem, nCorner, nType )
  local tblParent
  local coreElem

  gtblConn={}
  tblParent=af_request("elem_openparent", guidElem)

  -- Find core layer
  coreElem=nil
  for i,v in ipairs(tblParent.tblelems) do
    if v.type=="core" then
      coreElem=v
      break
    end
  end

  if coreElem==nil then
    af_request("elem_closeparent", 0)
    return
  end

  gGuidElemToPlank=guidElem
  nSaveElems=0
  if gAdjustElems then
    nSaveElems=1
    gGuidElemToPlank=nil
  end

  DoWithRelShort(tblParent, nCorner, coreElem, nType)
  DoDefaultShort(tblParent, nCorner, coreElem, nType)
  af_request("elem_closeparent", nSaveElems)
  
  if #gtblConn>0 and gAdjustElems then
    -- To other part
    local v
    
    v=gtblConn[1]
    
    if v.cornerother==1 or v.cornerother==2 then
      v.idother="long"     -- To be saved into other element's settings
      if nType==100 then
        v.idother="long_hedalm"
      elseif nType==101 then
        v.idother="long_anebyhus"
      elseif nType==102 then
        v.idother="long_omatalo"
      elseif nType==8 or nType==9 or nType==108 or nType==109 then
        if v.reldata.other.angledeg>0 then
          v.idother="long_l_left3"
        else
          v.idother="long_l_right3"
        end
      elseif nType==110 then
        v.idother="plusshus_long_ext1"
      elseif nType==120 then
        v.idother="yit_long1"
      elseif nType==121 then
        v.idother="yit_longint1"
      end
      tblParent=af_request("elem_openparent", v.guidother)
      DoWithRelLong(tblParent, v.cornerother, coreElem, nType)
      af_request("elem_closeparent", 1)
    end
  end
end



-- Example of offsetting layers with constant values
function DoDefaultTopBottom(tblParent, nCorner, coreElem, nType)
  local i, v, off

  -- Keep core in place, move all others
  for i,v in ipairs(tblParent.tblelems) do
    -- Following condition is always true for bottom & top since no element relation are used
    if not v.handled then
      af_request("elem_openlayer", v.guid)
      off=nil
      -- Keep core unmoved
      if v~=coreElem then
        if nCorner==3 then
          -- Bottom
          off=-v.y1off
        else
          -- Top
          off=-v.y2off
        end
        
        if v.type=="intstud" or v.type=="boarding_int" then
          if nCorner==3 then
            off=off-0.050
          else
            off=2.5 - v.ysize   -- Height=2500
          end
        elseif v.type=="boarding_ext" then
          if nCorner==3 then
            -- Adjust bottom to core
          else
            off=off+0.1         -- Top 100 mm over core
          end
        elseif v.type=="extstud" or v.type=="finish_ext" then
          if nCorner==3 then
            off=off-0.15         -- Bottom 150 mm up from core bottom
          else
            off=off+0.15         -- Top 150 mm over core
          end
        else
          ac_environment("tolog", string.format("Unknown element layer type=%s", v.type))
          off=nil               -- No change
        end
      end

      if gAdjustElems and off then
        af_request("elem_moveside", nCorner, off)
      end
      af_request("elem_closelayer")
    end
  end
end


function SetTopBottomEx( sSettings, guidElem, nCorner, nType )
  local tblParent
  local coreElem

  gtblConn={}
  tblParent=af_request("elem_openparent", guidElem)

  -- Find core layer
  coreElem=nil
  for i,v in ipairs(tblParent.tblelems) do
    if v.type=="core" then
      coreElem=v
      break
    end
  end

  if coreElem==nil then
    af_request("elem_closeparent", 0)
    return
  end

  gGuidElemToPlank=guidElem
  nSaveElems=0
  if gAdjustElems then
    nSaveElems=1
    gGuidElemToPlank=nil
  end

  DoDefaultTopBottom(tblParent, nCorner, coreElem, nType)
  af_request("elem_closeparent", nSaveElems)
end


function SetTopBottom( guidElem, nCorner, offBoardInt, offBoardExt, offStuddingExt1, offStuddingExt2, offFinishExt )
  local tblParent
  local coreElem
  local i, v, off

  tblParent=af_request("elem_openparent", guidElem)

  -- Find core layer
  coreElem=nil
  for i,v in ipairs(tblParent.tblelems) do
    if v.type=="core" then
      coreElem=v
      break
    end
  end

  if coreElem==nil then
    af_request("elem_closeparent", 0)
    return
  end

  gGuidElemToPlank=guidElem
  nSaveElems=0
  if gAdjustElems then
    nSaveElems=1
    gGuidElemToPlank=nil
  end

  -- Keep core in place, move all others
  for i,v in ipairs(tblParent.tblelems) do
    -- Following condition is always true for bottom & top since no element relation are used
    af_request("elem_openlayer", v.guid)
    off=nil
    -- Keep core unmoved
    if v~=coreElem then
      if nCorner==3 then
        -- Bottom
        off=-v.y1off
      else
        -- Top
        off=-v.y2off
      end

      if string.match(v.type, "^intstud%a*") or string.match(v.type, "^boarding_int%a*") then
        off=off+offBoardInt
      elseif string.match(v.type, "^boarding_ext%a*") then
        off=off+offBoardExt
      elseif string.match(v.type, "^extstud%a*") then
        off=off+offStuddingExt1
      elseif string.match(v.type, "^extstud2%a*") then
        off=off+offStuddingExt2
      elseif string.match(v.type, "^finish_ext%a*") then
        off=off+offFinishExt
      else
        ac_environment( "tolog", string.format("WARNING: SET TOP&BOTTOM, UNKONWN LAYER: %s", v.type))
        off=nil               -- No change
      end
    end

    if gAdjustElems and off then
      af_request("elem_moveside", nCorner, off)
    end
    af_request("elem_closelayer")
  end

  af_request("elem_closeparent", nSaveElems)
end



function SetStraight( guidElem, nCorner )
  local tblParent
  local coreElem
  local i, v, off

  tblParent=af_request("elem_openparent", guidElem)

  -- Find core layer
  coreElem=nil
  for i,v in ipairs(tblParent.tblelems) do
    if v.type=="core" then
      coreElem=v
      break
    end
  end

  if coreElem==nil then
    af_request("elem_closeparent", 0)
    return
  end

  gGuidElemToPlank=guidElem
  nSaveElems=0
  if gAdjustElems then
    nSaveElems=1
    gGuidElemToPlank=nil
  end


  -- Keep core in place, move all others
  for i,v in ipairs(tblParent.tblelems) do
    -- Following condition is always true for bottom & top since no element relation are used
    af_request("elem_openlayer", v.guid)
    off=nil
    -- Keep core unmoved
    if v~=coreElem then
      if nCorner==1 then
        off=-v.x1off
      elseif nCorner==2 then
        off=-v.x2off
      elseif nCorner==3 then
        off=-v.y1off
      elseif nCorner==4 then
        off=-v.y2off
      end
    end

    if gAdjustElems and off and math.abs(off)>0.0001 then
      af_request("elem_moveside", nCorner, off)
    end
    af_request("elem_closelayer")
  end

  af_request("elem_closeparent", nSaveElems)
end
]]>
      </common_script>


      <corner id="long" name="Long" name_fin="Pitkä" name_nor="Lang" name_swe="Lång" name_ger="Lang" bottom="1" top="1">
        <script ref="elem/corners/common_script">
          <![CDATA[
function Set( sSettings, guidElem, nCorner )
  SetLongElem( sSettings, guidElem, nCorner )
end


function OnPlanksCreated( sSettings, guidElem, layerType, nCorner )
  DoLongPlanks(layerType, nCorner, 1, guidElem)
end
]]>
        </script>
      </corner>


      <corner id="long2" name="Long 2" name_fin="Pitkä 2" name_nor="Lang 2" name_swe="Lång 2" name_ger="Lang 2" bottom="1" top="1">
        <script ref="elem/corners/common_script">
          <![CDATA[
function Set( sSettings, guidElem, nCorner )
  SetLongElem( sSettings, guidElem, nCorner )
end


function OnPlanksCreated( sSettings, guidElem, layerType, nCorner )
  DoLongPlanks(layerType, nCorner, 6, guidElem)
end
]]>
        </script>
      </corner>


      <corner id="long3" name="Long 3" name_fin="Pitkä 3" name_nor="Lang 3" name_swe="Lång 3" name_ger="Lang 3" bottom="1" top="1">
        <script ref="elem/corners/common_script">
          <![CDATA[
function Set( sSettings, guidElem, nCorner )
  SetLongElem( sSettings, guidElem, nCorner )
end


function OnPlanksCreated( sSettings, guidElem, layerType, nCorner )
  DoLongPlanks(layerType, nCorner, 7, guidElem)
end
]]>
        </script>
      </corner>


      <corner id="long_l_left" name="Long L left" name_fin="Pitkä L vasen" name_nor="Lang L vänster" name_swe="Lång L vänster" name_ger="Lang L links">
        <script ref="elem/corners/common_script">
          <![CDATA[
function Set( sSettings, guidElem, nCorner )
  SetLongElem( sSettings, guidElem, nCorner )
end


function OnPlanksCreated( sSettings, guidElem, layerType, nCorner )
  DoLongPlanks(layerType, nCorner, 2, guidElem)
end
]]>
        </script>
      </corner>


      <corner id="long_l_right" name="Long L right" name_fin="Pitkä L oikea" name_nor="Lang L höger" name_swe="Lång L höger" name_ger="Lang L rechts">
        <script ref="elem/corners/common_script">
          <![CDATA[
function Set( sSettings, guidElem, nCorner )
  SetLongElem( sSettings, guidElem, nCorner )
end


function OnPlanksCreated( sSettings, guidElem, layerType, nCorner )
  DoLongPlanks(layerType, nCorner, 3, guidElem)
end
]]>
        </script>
      </corner>


      <corner id="long_l_left2" name="Long L left layered" name_fin="Pitkä L vasen kerros" name_nor="Lang L vänster 2" name_swe="Lång L vänster 2" name_ger="Lang L links geschichtet">
        <script ref="elem/corners/common_script">
          <![CDATA[
function Set( sSettings, guidElem, nCorner )
  SetLongElem( sSettings, guidElem, nCorner )
end


function OnPlanksCreated( sSettings, guidElem, layerType, nCorner )
  DoLongPlanks(layerType, nCorner, 4, guidElem)
end
]]>
        </script>
      </corner>


      <corner id="long_l_right2" name="Long L right layered" name_fin="Pitkä L oikea kerros" name_nor="Lang L höger 2" name_swe="Lång L höger 2" name_ger="Lang L rechts geschichtet">
        <script ref="elem/corners/common_script">
          <![CDATA[
function Set( sSettings, guidElem, nCorner )
  SetLongElem( sSettings, guidElem, nCorner )
end


function OnPlanksCreated( sSettings, guidElem, layerType, nCorner )
  DoLongPlanks(layerType, nCorner, 5, guidElem)
end
]]>
        </script>
      </corner>



      <corner id="long_l_left3" name="Long L left layered 3" name_fin="Pitkä L vasen kerros 3" name_nor="Lang L vänster 3" name_swe="Lång L vänster 3" name_ger="Lang L links geschichtet 3">
        <script ref="elem/corners/common_script">
          <![CDATA[
function Set( sSettings, guidElem, nCorner )
  SetLongElem( sSettings, guidElem, nCorner, 8 )
end


function OnPlanksCreated( sSettings, guidElem, layerType, nCorner )
  DoLongPlanks(layerType, nCorner, 8, guidElem)
end
]]>
        </script>
      </corner>


      <corner id="long_l_right3" name="Long L right layered 3" name_fin="Pitkä L oikea kerros 3" name_nor="Lang L höger 3" name_swe="Lång L höger 3" name_ger="Lang L rechts geschichtet 3">
        <script ref="elem/corners/common_script">
          <![CDATA[
function Set( sSettings, guidElem, nCorner )
  SetLongElem( sSettings, guidElem, nCorner, 9 )
end


function OnPlanksCreated( sSettings, guidElem, layerType, nCorner )
  DoLongPlanks(layerType, nCorner, 9, guidElem)
end
]]>
        </script>
      </corner>


      <corner id="short" name="Short" name_fin="Lyhyt" name_nor="Kort" name_swe="Kort" name_ger="Kurz" bottom="1" top="1">
        <script ref="elem/corners/common_script">
          <![CDATA[
function Set( sSettings, guidElem, nCorner )
  SetShortElem( sSettings, guidElem, nCorner )
end
]]>
        </script>
      </corner>


      <corner id="short3" name="Short 3" name_fin="Lyhyt 3" name_nor="Kort 3" name_swe="Kort 3" name_ger="Kurz 3">
        <script ref="elem/corners/common_script">
          <![CDATA[
function Set( sSettings, guidElem, nCorner )
  SetShortElem( sSettings, guidElem, nCorner, 8 )
end


function OnPlanksCreated( sSettings, guidElem, layerType, nCorner )
  DoShortPlanks(layerType, nCorner, 9, guidElem)
end

]]>
        </script>
      </corner>


      <corner id="straigt_all" name="Straight" name_fin="Tasattu" sides="1" bottom="1" top="1">
        <script ref="elem/corners/common_script">
          <![CDATA[
function Set( sSettings, guidElem, nCorner )
  SetStraight( guidElem, nCorner )
end
]]>
        </script>
      </corner>

      <corner id="topbottomexoff" name="Top and bottom example 1" name_fin="Ylä ja ala esimerkki 1" name_ger="Oberes u. unteres Beispiel 1" sides="0" bottom="1" top="1">
        <script ref="elem/corners/common_script">
          <![CDATA[
function Set( sSettings, guidElem, nCorner )
  SetTopBottom( guidElem, nCorner, 0.050, 0.050, 0.100, 0.100, 0.150 )
end
]]>
        </script>
      </corner>

      <!-- Raise all layers from core -->
      <corner id="topbottomex1" name="Top and bottom example 2" name_fin="Ylä ja ala esimerkki 2" name_ger="Oberes u. unteres Beispiel 2" sides="0" bottom="1" top="1">
        <script ref="elem/corners/common_script">
          <![CDATA[
function Set( sSettings, guidElem, nCorner )
  SetTopBottomEx( sSettings, guidElem, nCorner )
end
]]>
        </script>
      </corner>
    </corners>


    <panelings>
      <paneling thickness="0.050" height="0.135" rot="90" id="PANEL_VERT_OUTIN" name="Paneling vertical out to in" name_fin="Rimalaudoitus ulkoa sisälle" name_swe="Vertikala paneler ut till in" name_nor="Stående kledning utside til innside" name_ger="Paneelierung senkrecht von außen nach innen">
        <panel thickness="0.025" height="0.125" y1="0.025" y2="0.050" x1="0.000" x2="0.125">
          <profile>
            <point xym="0.00000000 0.05000000 15"/>
            <point xym="0.00000000 0.02500000 15"/>
            <point xym="0.12500000 0.02500000 15"/>
            <point xym="0.12500000 0.05000000 15"/>
            <point xym="0.00000000 0.05000000 -1"/>
          </profile>
        </panel>
        <panel thickness="0.025" height="0.050" y1="0.000" y2="0.025" x1="0.105" x2="0.155">
          <profile>
            <point xym="0.10500000 0.02500000 15"/>
            <point xym="0.10500000 0.00000000 15"/>
            <point xym="0.15500000 0.00000000 15"/>
            <point xym="0.15500000 0.02500000 15"/>
            <point xym="0.10500000 0.02500000 -1"/>
          </profile>
        </panel>
      </paneling>

      <paneling thickness="0.023" height="0.135" rot="0" id="PANEL_HOR_OUTIN" name="Paneling horizontal out to in 23x145/135" name_fin="Vaakalaudoitus ulkoa sisälle 23x145/135" name_swe="Horizontella paneler ut till in 23x145/135" name_nor="Liggende kledning utside til innside 23x145/135" name_ger="Paneelierung wagerecht von außen nach innen 23x145/135">
        <panel id="PANEL 23x135" thickness="0.023" height="0.145" y1="0.000" y2="0.023" x1="0.000" x2="0.135">
          <profile>
            <point xym="-0.01000000 0.01456783 15"/>
            <point xym="-0.01000000 0.00784452 15"/>
            <point xym="0.01413317 0.00784452 15"/>
            <point xym="0.01872867 0.00000000 15"/>
            <point xym="0.13054592 0.00000000 15"/>
            <point xym="0.13497980 0.00787226 15"/>
            <point xym="0.12169031 0.00787226 15"/>
            <point xym="0.12169031 0.01568008 15"/>
            <point xym="0.13500000 0.01568008 15"/>
            <point xym="0.13500000 0.02300000 15"/>
            <point xym="0.09396181 0.02300000 15"/>
            <point xym="0.09396181 0.01682631 15"/>
            <point xym="0.08186436 0.01682631 15"/>
            <point xym="0.08186436 0.02300000 15"/>
            <point xym="0.05409523 0.02300000 15"/>
            <point xym="0.05409523 0.01682631 15"/>
            <point xym="0.04188986 0.01682631 15"/>
            <point xym="0.04188986 0.02300000 15"/>
            <point xym="0.00200068 0.02300000 15"/>
            <point xym="0.00200068 0.01456783 15"/>
            <point xym="-0.01000000 0.01456783 -1"/>
          </profile>
        </panel>
      </paneling>

      <paneling thickness="0.050" height="0.135" rot="90" id="PANEL_VERT_INOUT" name="Paneling vertical in to out" name_fin="Rimalaudoitus sisältä ulos" name_swe="Vertikala paneler in till ut" name_nor="Stående kledning innside til utside" name_ger="Paneelierung senkrecht von innen nach außen">
        <panel thickness="0.1250" height="0.0250" x1="0.0000" x2="0.1250" y1="0.0000" y2="0.0250">
          <profile>
            <point xym="0.000000 0.025000 15"/>
            <point xym="0.000000 0.000000 15"/>
            <point xym="0.125000 0.000000 15"/>
            <point xym="0.125000 0.025000 15"/>
            <point xym="0.000000 0.025000 -1"/>
          </profile>
        </panel>
        <panel thickness="0.0500" height="0.0250" x1="0.1050" x2="0.1550" y1="0.0250" y2="0.0500">
          <profile>
            <point xym="0.105000 0.050000 15"/>
            <point xym="0.105000 0.025000 15"/>
            <point xym="0.155000 0.025000 15"/>
            <point xym="0.155000 0.050000 15"/>
            <point xym="0.105000 0.050000 -1"/>
          </profile>
        </panel>
      </paneling>

      <paneling thickness="0.023" height="0.135" rot="0" id="PANEL_HOR_INOUT" name="Paneling horizontal in to out 23x145/135" name_fin="Vaakalaudoitus sisältä ulos 23x145/135" name_swe="Horizontella paneler in till ut 23x145/135" name_nor="Liggende kledning innside til utside 23x145/135" name_ger="Paneelierung wagerecht von innen nach außen 23x145/135">
        <panel id="PANEL 23x135" thickness="0.023" height="0.145" y1="0.000" y2="0.023" x1="0.000" x2="0.135">
          <profile>
            <point xym="-0.01000000 0.01515500 15"/>
            <point xym="-0.01000000 0.00843200 15"/>
            <point xym="0.00200100 0.00843200 15"/>
            <point xym="0.00200100 0.00000000 15"/>
            <point xym="0.04189000 0.00000000 15"/>
            <point xym="0.04189000 0.00617400 15"/>
            <point xym="0.05409500 0.00617400 15"/>
            <point xym="0.05409500 0.00000000 15"/>
            <point xym="0.08186400 0.00000000 15"/>
            <point xym="0.08186400 0.00617400 15"/>
            <point xym="0.09396200 0.00617400 15"/>
            <point xym="0.09396200 0.00000000 15"/>
            <point xym="0.13500000 0.00000000 15"/>
            <point xym="0.13500000 0.00732000 15"/>
            <point xym="0.12169000 0.00732000 15"/>
            <point xym="0.12169000 0.01512800 15"/>
            <point xym="0.13498000 0.01512800 15"/>
            <point xym="0.13054600 0.02300000 15"/>
            <point xym="0.01872900 0.02300000 15"/>
            <point xym="0.01413300 0.01515500 15"/>
            <point xym="-0.01000000 0.01515500 -1"/>
          </profile>
        </panel>
      </paneling>

      <paneling thickness="0.023" height="0.135" rot="0" id="PANEL_23x145/135_OUTIN" name="Panel gro 23x145/135 outin" name_fin="Paneeli valeura 23x145/135 ulkoa sisälle">
        <panel id="PANEL GRO 23x135" thickness="0.023" height="0.145" y1="0.000" y2="0.023" x1="0.000" x2="0.135">
          <profile>
            <point xym="-0.01000000 0.01459500 15"/>
            <point xym="-0.01000000 0.00787200 15"/>
            <point xym="0.01413300 0.00787200 15"/>
            <point xym="0.01872900 0.00002700 15"/>
            <point xym="0.06329500 0.00000000 15"/>
            <point xym="0.06772900 0.00787200 15"/>
            <point xym="0.08172900 0.00787200 15"/>
            <point xym="0.08616300 0.00000000 15"/>
            <point xym="0.13054600 0.00002700 15"/>
            <point xym="0.13498000 0.00789900 15"/>
            <point xym="0.12169000 0.00789900 15"/>
            <point xym="0.12169000 0.01570700 15"/>
            <point xym="0.13500000 0.01570700 15"/>
            <point xym="0.13500000 0.02302700 15"/>
            <point xym="0.00200100 0.02302700 15"/>
            <point xym="0.00200100 0.01459500 15"/>
            <point xym="-0.01000000 0.01459500 -1"/>
          </profile>
        </panel>
      </paneling>

      <paneling thickness="0.023" height="0.135" rot="0" id="PANEL_23x145/135_INOUT" name="Panel gro 23x145/135 inout" name_fin="Paneeli valeura 23x145/135 sisältä ulos">
        <panel id="PANEL GRO 23x135" thickness="0.023" height="0.145" y1="0.000" y2="0.023" x1="0.000" x2="0.135">
          <profile>
            <point xym="-0.01000000 0.01515500 15"/>
            <point xym="-0.01000000 0.00843200 15"/>
            <point xym="0.00200100 0.00843200 15"/>
            <point xym="0.00200100 0.00000000 15"/>
            <point xym="0.13500000 0.00000000 15"/>
            <point xym="0.13500000 0.00732000 15"/>
            <point xym="0.12169000 0.00732000 15"/>
            <point xym="0.12169000 0.01512800 15"/>
            <point xym="0.13498000 0.01512800 15"/>
            <point xym="0.13054600 0.02300000 15"/>
            <point xym="0.08616300 0.02302700 15"/>
            <point xym="0.08172900 0.01515500 15"/>
            <point xym="0.06772900 0.01515500 15"/>
            <point xym="0.06329500 0.02302700 15"/>
            <point xym="0.01872900 0.02300000 15"/>
            <point xym="0.01413300 0.01515500 15"/>
            <point xym="-0.01000000 0.01515500 -1"/>
          </profile>
        </panel>
      </paneling>


      <!-- 22x145/130 -->
      <paneling thickness="0.0220" height="0.130" rot="0" id="PANEL 22x145/130 OUTIN" name="Panel 22x145/130 outin">
        <panel id="Panel 22x145/130" thickness="0.022" height="0.145" y1="0.000" y2="0.022" x1="0.000" x2="0.130">
          <profile>
            <point xym="0.00200100 0.01456800 15"/>
            <point xym="-0.01500000 0.01456800 15"/>
            <point xym="-0.01500000 0.00784500 15"/>
            <point xym="0.01413300 0.00784500 15"/>
            <point xym="0.01872900 0.00000000 15"/>
            <point xym="0.12554600 0.00000000 15"/>
            <point xym="0.12998000 0.00787200 15"/>
            <point xym="0.11169000 0.00787200 15"/>
            <point xym="0.11169000 0.01568000 15"/>
            <point xym="0.13000000 0.01568000 15"/>
            <point xym="0.13000000 0.02200000 15"/>
            <point xym="0.00200100 0.02200000 15"/>
            <point xym="0.00200100 0.01456800 -1"/>
          </profile>
        </panel>
      </paneling>

      <paneling thickness="0.0220" height="0.130" rot="0" id="PANEL 22x145/130 INOUT" name="Panel 22x145/130 inout">
        <panel id="Panel 22x145/130" thickness="0.022" height="0.145" y1="0.000" y2="0.022" x1="0.000" x2="0.130">
          <profile>
            <point xym="-0.01500000 0.00743200 15"/>
            <point xym="0.00200100 0.00743200 15"/>
            <point xym="0.00200100 0.00000000 15"/>
            <point xym="0.13000000 0.00000000 15"/>
            <point xym="0.13000000 0.00632000 15"/>
            <point xym="0.11169000 0.00632000 15"/>
            <point xym="0.11169000 0.01412800 15"/>
            <point xym="0.12998000 0.01412800 15"/>
            <point xym="0.12554600 0.02200000 15"/>
            <point xym="0.01872900 0.02200000 15"/>
            <point xym="0.01413300 0.01415500 15"/>
            <point xym="-0.01500000 0.01415500 15"/>
            <point xym="-0.01500000 0.00743200 -1"/>
          </profile>
        </panel>
      </paneling>


      <!-- 22x120/105 -->
      <paneling thickness="0.0220" height="0.105" rot="0" id="PANEL 22x120/105 OUTIN" name="Panel 22x120/105 outin">
        <panel id="Panel 22x120/105" thickness="0.022" height="0.120" y1="0.000" y2="0.022" x1="0.000" x2="0.105">
          <profile>
            <point xym="0.00200100 0.01456800 15"/>
            <point xym="-0.01500000 0.01456800 15"/>
            <point xym="-0.01500000 0.00784500 15"/>
            <point xym="0.01413300 0.00784500 15"/>
            <point xym="0.01872900 0.00000000 15"/>
            <point xym="0.10054600 0.00000000 15"/>
            <point xym="0.10498000 0.00787200 15"/>
            <point xym="0.08669000 0.00787200 15"/>
            <point xym="0.08669000 0.01568000 15"/>
            <point xym="0.10500000 0.01568000 15"/>
            <point xym="0.10500000 0.02200000 15"/>
            <point xym="0.00200100 0.02200000 15"/>
            <point xym="0.00200100 0.01456800 -1"/>
          </profile>
        </panel>
      </paneling>

      <paneling thickness="0.0220" height="0.105" rot="0" id="PANEL 22x120/105 INOUT" name="Panel 22x120/105 inout">
        <panel id="Panel 22x120/105" thickness="0.022" height="0.120" y1="0.000" y2="0.022" x1="0.000" x2="0.105">
          <profile>
            <point xym="-0.01500000 0.00743200 15"/>
            <point xym="0.00200100 0.00743200 15"/>
            <point xym="0.00200100 0.00000000 15"/>
            <point xym="0.10500000 0.00000000 15"/>
            <point xym="0.10500000 0.00632000 15"/>
            <point xym="0.08669000 0.00632000 15"/>
            <point xym="0.08669000 0.01412800 15"/>
            <point xym="0.10498000 0.01412800 15"/>
            <point xym="0.10054600 0.02200000 15"/>
            <point xym="0.01872900 0.02200000 15"/>
            <point xym="0.01413300 0.01415500 15"/>
            <point xym="-0.01500000 0.01415500 15"/>
            <point xym="-0.01500000 0.00743200 -1"/>
          </profile>
        </panel>
      </paneling>

      <paneling thickness="0.0150" height="0.110" rot="0" id="PANEL 15x120/110" name="Panel 15x120/110 nogroove">
        <panel id="Panel 15x120/110" thickness="0.015" height="0.120" y1="0.000" y2="0.015" x1="0.000" x2="0.110">
          <profile>
            <point xym="-0.01000000 0.01000000 15"/>
            <point xym="-0.01000000 0.00500000 15"/>
            <point xym="0.00100000 0.00500000 15"/>
            <point xym="0.00100000 0.00000000 15"/>
            <point xym="0.11000000 0.00000000 15"/>
            <point xym="0.11000000 0.00400000 15"/>
            <point xym="0.09900000 0.00400000 15"/>
            <point xym="0.09900000 0.01100000 15"/>
            <point xym="0.11000000 0.01100000 15"/>
            <point xym="0.11000000 0.01500000 15"/>
            <point xym="0.00100000 0.01500000 15"/>
            <point xym="0.00100000 0.01000000 15"/>
            <point xym="-0.01000000 0.01000000 -1"/>
          </profile>
        </panel>
      </paneling>

      <paneling thickness="0.0140" height="0.110" rot="0" id="PANEL 14x120/110" name="Panel 14x120/110 nogroove">
        <panel id="Panel 14x120/110" thickness="0.014" height="0.120" y1="0.000" y2="0.014" x1="0.000" x2="0.110">
          <profile>
            <point xym="-0.01000000 0.00950000 15"/>
            <point xym="-0.01000000 0.00450000 15"/>
            <point xym="0.00100000 0.00450000 15"/>
            <point xym="0.00100000 0.00000000 15"/>
            <point xym="0.11000000 0.00000000 15"/>
            <point xym="0.11000000 0.00350000 15"/>
            <point xym="0.09900000 0.00350000 15"/>
            <point xym="0.09900000 0.01050000 15"/>
            <point xym="0.11000000 0.01050000 15"/>
            <point xym="0.11000000 0.01400000 15"/>
            <point xym="0.00100000 0.01400000 15"/>
            <point xym="0.00100000 0.00950000 15"/>
            <point xym="-0.01000000 0.00950000 -1"/>
          </profile>
        </panel>
      </paneling>

      <paneling thickness="0.0190" height="0.130" rot="90" id="19x148/130 outin" name="19x148/130 outin">
        <panel id="Panel 19x148/130" thickness="0.019" height="0.148" y1="0.000" y2="0.019" x1="0.000" x2="0.130">
          <profile>
            <point xym="-0.00000000 0.01000000 15"/>
            <point xym="-0.01800000 0.01000000 15"/>
            <point xym="-0.01800000 0.00000000 15"/>
            <point xym="0.10000000 0.00000000 15"/>
            <point xym="0.10000000 0.01000000 15"/>
            <point xym="0.13000000 0.01000000 15"/>
            <point xym="0.13000000 0.01900000 15"/>
            <point xym="-0.00000000 0.01900000 15"/>
            <point xym="-0.00000000 0.01000000 -1"/>
          </profile>
        </panel>
      </paneling>

      <paneling thickness="0.0190" height="0.130" rot="90" id="19x148/130 inout" name="19x148/130 inout">
        <panel id="Panel 19x148/130" thickness="0.019" height="0.148" y1="0.000" y2="0.019" x1="0.000" x2="0.130">
          <profile>
            <point xym="-0.01800000 0.00900000 15"/>
            <point xym="-0.00000000 0.00900000 15"/>
            <point xym="-0.00000000 0.00000000 15"/>
            <point xym="0.13000000 0.00000000 15"/>
            <point xym="0.13000000 0.00900000 15"/>
            <point xym="0.10000000 0.00900000 15"/>
            <point xym="0.10000000 0.01900000 15"/>
            <point xym="-0.01800000 0.01900000 15"/>
            <point xym="-0.01800000 0.00900000 -1"/>
          </profile>
        </panel>
      </paneling>


      <paneling thickness="0.0190" height="0.052" rot="90" id="19x70/52 outin" name="19x70/52 outin">
        <panel id="Panel 19x70/52" thickness="0.019" height="0.070" y1="0.000" y2="0.019" x1="0.000" x2="0.052">
          <profile>
            <point xym="0.00000000 0.01000000 15"/>
            <point xym="-0.01800000 0.01000000 15"/>
            <point xym="-0.01800000 0.00000000 15"/>
            <point xym="0.02200000 0.00000000 15"/>
            <point xym="0.02200000 0.01000000 15"/>
            <point xym="0.05200000 0.01000000 15"/>
            <point xym="0.05200000 0.01900000 15"/>
            <point xym="0.00000000 0.01900000 15"/>
            <point xym="0.00000000 0.01000000 -1"/>
          </profile>
        </panel>
      </paneling>


      <paneling thickness="0.0190" height="0.052" rot="90" id="19x70/52 inout" name="19x70/52 inout">
        <panel id="Panel 19x70/52" thickness="0.019" height="0.070" y1="0.000" y2="0.019" x1="0.000" x2="0.052">
          <profile>
            <point xym="-0.01800000 0.00900000 15"/>
            <point xym="0.00000000 0.00900000 15"/>
            <point xym="0.00000000 0.00000000 15"/>
            <point xym="0.05200000 0.00000000 15"/>
            <point xym="0.05200000 0.00900000 15"/>
            <point xym="0.02200000 0.00900000 15"/>
            <point xym="0.02200000 0.01900000 15"/>
            <point xym="-0.01800000 0.01900000 15"/>
            <point xym="-0.01800000 0.00900000 -1"/>
          </profile>
        </panel>
      </paneling>
    </panelings>

  </elem>

</archiframe>
