Surpac Tip – TCL/SCL macro series (2 of 10)

Part 2 – Layers, data and procedures

SCL provides a number of excellent functions to create, add, import and manipulate layers.  There is also great reference material in the Surpac->Help menu.  My aim in this series is to introduce some of these features in more layman’s terms.  Some knowledge of how macro’s work with variables and commands will certainly be helpful but is not essential.

In the following tip;

  • My comments in the code blocks will have a # in front of them. They are also in bold and italicized.
  • If you would like to test this code in Surpac, the entire code block has been added to the end of the tip.  Copy it into any text editor and save it with a .tcl extension to use it in Surpac.  The final result will look similar (but not the same due to styles) as the screen capture below.

Following on from part 1, lets create some more layers to accept new data.

#Create a layer called square_2 that can be manipulated/inquired with the "square2Swa" reference variable
SclCreateSwa square2Swa "square_2" 
sclGraphicsLayers SclAdd $square2Swa $vh
# Using the reference to "square2Swa", create a reference variable "square2Str" and make the string number 6
$square2Swa SclCreateString square2Str 6
# Create a new segment.  See details from part 1 about how this works.
$square2Str SclCreateSegment square2Seg [$square2Str SclCountItems]

Now each point we want to create takes 4 lines of code. (See part 1 of this macro series) These four lines are almost identical except for the reference to the segment plus the coordinates. We can create something called a procedure to eliminate the repetition of code. TCL procedures are like new commands and are defined once. The command/procedure is given a name and some parameters that you want to pass to it. The procedure executes using your parameters and in some cases will return a value back to you for use later on.

# Procedure is called "newPoint" and takes 4 parameters.  
# 1. The segment reference 2. The X coord, 3. The Y coord and 4. the Z coord
proc newPoint {segHandle x y z} {
  # The rest of the code is exactly the same as what we did in part one when creating a new point
  # The only difference being that we are using variables i.e. $x that are input when the procedure is called.
  $segHandle SclCreatePoint pntHandle [$segHandle SclCountItems]
  $pntHandle SclSetValueByName X $x
  $pntHandle SclSetValueByName Y $y
  $pntHandle SclSetValueByName Z $z
  return $pntHandle
}

Now that the procedure is created, we can create new points with one line of code instead of four. Just call the procedure and list the parameters separated by white space. Remember, procedure name is “newPoint” and the parameters are segment handle, x, y and z.

newPoint $square2Seg 11 11 10;# First point, note that we are using square2seg as the segment reference
newPoint $square2Seg 11 19 10
newPoint $square2Seg 19 19 10
newPoint $square2Seg 19 11 10
newPoint $square2Seg 11 11 10;# Closing point is same as first point

We’ll save drawing the data on the screen until the end of the macro so for now lets create another layer with a smaller square.

# Create a layer called square_3 that can be manipulated/inquired with the "square3Swa" reference variable
SclCreateSwa square3Swa "square_3"
sclGraphicsLayers SclAdd $square3Swa $vh
# Using the reference to "square3Swa", create a reference variable "square3Str" and make the string number 9
$square3Swa SclCreateString square3Str 9
# See details from part 1 about how SclCreateSegment works.
$square3Str SclCreateSegment square3Seg [$square3Str SclCountItems]

Use our procedure to create the square.

newPoint $square3Seg 13 13 10;# First point, note that we are using square3seg as the segment reference
newPoint $square3Seg 13 17 10
newPoint $square3Seg 17 17 10
newPoint $square3Seg 17 13 10
newPoint $square3Seg 13 13 10;# Closing point is same as first point

Now draw the squares. Note that they don’t have to be the active layer as I’m using the reference variable to the string. Note also that I can override the styles file and draw these shapes how I want using the SclDraw options as below.

$square2Str SclDraw
$square3Str SclDraw "style=ssi_method=line,HGS_color=line=red,HGS_line_weight=2"

Entire code block – Parts 1 and 2 – Copy into text editor and run in Surpac with .tcl extension

####### PART 1 #######
# Get a reference to the active viewport (You can have more than one) store it in reference variable "vh"
SclGetActiveViewport vh
# Using the "vh" reference, get the active layer and store the reference in the "initialSwa" variable
$vh SclGetActiveLayer initialSwa
# Extract the layer name into the layerName variable using the SCL command "SclGetId"
set layerName [$initialSwa SclGetId]
# Print the layer name to the message window
puts "Layer name is $layerName"

# Create a layer called design that can be manipulated/inquired with the "designSwa" reference variable
SclCreateSwa designSwa "design"

# Use the SclAdd function to add the layer into the layer panel
sclGraphicsLayers SclAdd $designSwa $vh

# Using the reference to "designSwa", create a reference variable "designStr" and make the string number 8
$designSwa SclCreateString designStr 8


# Using the reference to the "designStr" create a reference variable "designSeg" and count how many items (i.e. segments) already
# exist for string 8. If there are 5 existing segments in string number 8, [$designStr SclCountItems] will return a value of 5.
# 5 will become the new segment number.  Now, why doesn't this clash with the existing segments if there are already 5 of them?
# This is because the segments are stored as an index position which starts at zero. i.e. segment 1 = index 0, segment 2 = index 1
# ... segment 5 = index 4 and so on.
# All of this to say that when we count how many items are in string 8, the number returned will work as the next index position
# which is what the "SclCreateSegment" function requires. So if I write it manually it becomes
# $designStr SclCreateSegment designSeg 5 
$designStr SclCreateSegment designSeg [$designStr SclCountItems]

# Using the reference variable "designSeg" count how many points there are and add this one to the end
$designSeg SclCreatePoint designPnt [$designSeg SclCountItems]
$designPnt SclSetValueByName X 10
$designPnt SclSetValueByName Y 10
$designPnt SclSetValueByName Z 10
$designPnt SclSetValueByName d1 "Testing SCL layer commands"

# Using the reference variable "designSeg" count how many points there are and add this one to the end
$designSeg SclCreatePoint designPnt [$designSeg SclCountItems]
$designPnt SclSetValueByName X 10
$designPnt SclSetValueByName Y 20
$designPnt SclSetValueByName Z 10

# Using the reference variable "designSeg" count how many points there are and add this one to the end
$designSeg SclCreatePoint designPnt [$designSeg SclCountItems]
$designPnt SclSetValueByName X 20
$designPnt SclSetValueByName Y 20
$designPnt SclSetValueByName Z 10

# Using the reference variable "designSeg" count how many points there are and add this one to the end
$designSeg SclCreatePoint designPnt [$designSeg SclCountItems]
$designPnt SclSetValueByName X 20
$designPnt SclSetValueByName Y 10
$designPnt SclSetValueByName Z 10

# To close the shape, make the x,y and z the same as the first point.
$designSeg SclCreatePoint designPnt [$designSeg SclCountItems]
$designPnt SclSetValueByName X 10
$designPnt SclSetValueByName Y 10
$designPnt SclSetValueByName Z 10

# Using the reference to the design layer (designSwa), use the command "SclDraw" to draw everything in the design layer.
$designSwa SclDraw
SclFunction "ZOOM ALL" {}

# Now, the active layer is still the initial layer that was active when the macro was first run.  Let's make it the design layer
$vh SclSetActiveLayer $designSwa

####### PART 2 #######

#Create a layer called square_2 that can be manipulated/inquired with the "square2Swa" reference variable
SclCreateSwa square2Swa "square_2" 
sclGraphicsLayers SclAdd $square2Swa $vh
# Using the reference to "square2Swa", create a reference variable "square2Str" and make the string number 6
$square2Swa SclCreateString square2Str 6
# Create a new segment.  See details from part 1 about how this works.
$square2Str SclCreateSegment square2Seg [$square2Str SclCountItems]

# Procedure is called "newPoint" and takes 4 parameters.  
# 1. The segment reference 2. The X coord, 3. The Y coord and 4. the Z coord
proc newPoint {segHandle x y z} {

  # The rest of the code is exactly the same as what we did in part one when creating a new point

  # The only difference being that we are using variables i.e. $x that are input when the procedure is called.
  $segHandle SclCreatePoint pntHandle [$segHandle SclCountItems]
  $pntHandle SclSetValueByName X $x
  $pntHandle SclSetValueByName Y $y
  $pntHandle SclSetValueByName Z $z
  return $pntHandle
}

newPoint $square2Seg 11 11 10;# First point, note that we are using square2seg as the segment reference
newPoint $square2Seg 11 19 10
newPoint $square2Seg 19 19 10
newPoint $square2Seg 19 11 10
newPoint $square2Seg 11 11 10;# Closing point is same as first point

# Create a layer called square_3 that can be manipulated/inquired with the "square3Swa" reference variable
SclCreateSwa square3Swa "square_3"
sclGraphicsLayers SclAdd $square3Swa $vh
# Using the reference to "square3Swa", create a reference variable "square3Str" and make the string number 9
$square3Swa SclCreateString square3Str 9
# See details from part 1 about how SclCreateSegment works.
$square3Str SclCreateSegment square3Seg [$square3Str SclCountItems]

newPoint $square3Seg 13 13 10;# First point, note that we are using square3seg as the segment reference
newPoint $square3Seg 13 17 10
newPoint $square3Seg 17 17 10
newPoint $square3Seg 17 13 10
newPoint $square3Seg 13 13 10;# Closing point is same as first point

$square2Str SclDraw
$square3Str SclDraw "style=ssi_method=line,HGS_color=line=red,HGS_line_weight=2"

Related posts

Surpac tip – Achieving faster Solids Conditioning

Surpac tip – Merging DTMs

Surpac Tip – TCL/SCL macro series (4 of 10)