Multilayered Tank Display

We have a tank with Oil and water, is it possible to show both of these levels in one cylindrical tank?

you can show as many levels as you want.
Draw the tank, put 1,2 or 200 level indicators on it, bind tags to the level indicators.

I used a paintable canvas on top of a cylindrical tank to draw a second volume that appears to be inside of the tank. I aligned the top left corners of the 2 components and had to make the paintable canvas about 10px wider than the tank before it looked right.

The code I’m using to draw the 2nd level:

from java.awt import Color
from java.awt import BasicStroke
from java.awt.geom import Rectangle2D
from java.awt.geom import Ellipse2D
from java.awt.geom import Area

debug = 0
g =

width = int(event.source.width * .929)
topTagValue = event.source.parent.getComponent('Cylindrical Tank').value

# bottomValue is a custom property on this tank
bottomTagValue =  event.source.parent.getComponent('Cylindrical Tank').bottomValue
bottomColor = Color(25, 25, 25)

if topTagValue is not None and bottomTagValue is not None:
	# Get values needed for positioning of shapes
	capacity = event.source.parent.getComponent('Cylindrical Tank').capacity
	if bottomTagValue > capacity:
		levelPercentage = capacity
		levelPercentage = bottomTagValue / capacity
	ellipse_height = event.source.height * .1134
	range = event.source.height - ellipse_height
	level = range * levelPercentage
	top_x = event.source.width * .0138
	top_y = int(range - level)
	if top_y < 0:
		top_y = 0
	if debug:
		tank_label = event.source.parent.tankName
		print "== %s values ==" % tank_label
		print "component height = %s" % range
		print "capacity = %s" % capacity
		print "levelPercentage = %s" % levelPercentage
		print "range = %s" % range
		print "level = %s" % level
		print "top_y = %s" % top_y
	# These shapes will be created but not rendered. 
	# They will be used to create areas based on the shape they overlap
	volumeRect = Rectangle2D.Float(top_x, top_y + (event.source.height * .0515), width + 1, range - top_y)
	bottomEllipse = Ellipse2D.Float(top_x,range, width, ellipse_height)
	# Draw the border around the top of the 'column'
	# and the top surface area 
	g.draw(Ellipse2D.Float(top_x, top_y, width, ellipse_height))
	clipEllipse = Ellipse2D.Float(top_x, top_y, width, ellipse_height)
	if debug:
		# Differentiate the locations of all of the shapes involed
		if round(bottomTagValue, 1) > round(topTagValue, 1):
			colorSurface = Color(0.9, 0.0, 0.0, 0.40)
			colorVolume = Color(0.9, 0.0, 0.0, 0.7)
			colorSurface = Color(bottomColor.getRed(), bottomColor.getBlue(), bottomColor.getGreen(), 102)
			colorVolume = Color(bottomColor.getRed(), bottomColor.getBlue(), bottomColor.getGreen(), 178)		
		areaTopEllipse = Area(clipEllipse)
		areaVolumeRect = Area(volumeRect)
		areaBottomEllipse = Area(bottomEllipse)

is this script running under the “paint, repaint” folder ? Also, which tag, variable, or value is driving or telling this image to change ?


The script should be placed in the repaint event handler.

topTagVaue is the value of the Cylindrical Tank value.

bottomTagValue is a custom property on the Cylindrical Tank.

1 Like

Thanks for your reply, if you don’t mind helping me out a bit more. I am a novice with this system and coding too, but I think I can make sense of most of the stuff you are doing but I have some questions. “topTagValue” and “bottomTagValue” are tags in your “Tag Browser” or is that something internal of that “Component Scripting [Paintable Canvas]”. Like under any of this menu options ?


These are variables in the script. Near the top of the script, each is linked to the cylindrical tank component (you’ll have to update that name in script if your cylindrical tank has a different name). As @lrose notes, the script grabs the value property of your cylindrical tank and copies it to the topTagValue variable in the script. bottomValue was added as a custom property on the cylindrical tank. You’ll need to add it on yours. The script grabs that custom property value from the cylindrical tank and copies it to bottomTagValue variable in the script.

lrose and witman are correct. The script references those properties of the cylindrical tank component that I have placed on the screen.

I have the topTagValue and bottomValue properties of the cylindrical tank component bound to 2 different tank level tags in our system.

A paintable canvas component was then placed on top of the cylindrical tank component in order to draw another cylinder on top of the cylindrical tank component.