# Multilayered Tank Display

**URL:** <https://forum.inductiveautomation.com/t/multilayered-tank-display/12793>\
**Category:** Ignition\
**Created:** [March 15, 2017, 3:18pm UTC](https://forum.inductiveautomation.com/t/multilayered-tank-display/12793 "2017-03-15T15:18:53Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Alturex](https://avatars.discourse-cdn.com/v4/letter/a/cab0a1/32.png) [@Alturex](https://forum.inductiveautomation.com/u/Alturex)\
**Post date:** [March 15, 2017, 3:18pm UTC](https://forum.inductiveautomation.com/t/multilayered-tank-display/12793/1 "2017-03-15T15:18:53Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![MMaynard](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mmaynard/32/3366_2.png) [@MMaynard](https://forum.inductiveautomation.com/u/MMaynard)\
**Post date:** [March 15, 2017, 6:03pm UTC](https://forum.inductiveautomation.com/t/multilayered-tank-display/12793/2 "2017-03-15T18:03:07Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![JGJohnson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jgjohnson/32/29582_2.png) [@JGJohnson](https://forum.inductiveautomation.com/u/JGJohnson)\
**Post date:** [March 15, 2017, 7:30pm UTC](https://forum.inductiveautomation.com/t/multilayered-tank-display/12793/3 "2017-03-15T19:30:15Z")

</div>

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.

![](https://us1.discourse-cdn.com/inductiveautomation/original/2X/d/d86e80fe12b0c96eb44a96214b05f7491c1b0c2c.png)

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

```auto
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 = event.graphics

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
	else:	
		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.setColor(Color.BLACK)	
	g.setStroke(BasicStroke(1.0))
	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
		g.setColor(Color.RED)
		g.fill(clipEllipse)
		g.setColor(Color.GREEN)
		g.fill(bottomEllipse)
		g.setColor(Color.BLUE)
		g.fill(volumeRect)
	else:
		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)
		else:
			colorSurface = Color(bottomColor.getRed(), bottomColor.getBlue(), bottomColor.getGreen(), 102)
			colorVolume = Color(bottomColor.getRed(), bottomColor.getBlue(), bottomColor.getGreen(), 178)		
		
		g.setColor(colorSurface)
		g.fill(clipEllipse)
		 
		areaTopEllipse = Area(clipEllipse)
		areaVolumeRect = Area(volumeRect)
		areaBottomEllipse = Area(bottomEllipse)
		
		areaVolumeRect.subtract(areaTopEllipse)
		areaVolumeRect.add(areaBottomEllipse)
		g.setColor(colorVolume)
		g.fill(areaVolumeRect)
```

---

<div class="post-metadata">

**Author:** ![Raymundo\_Villa](https://avatars.discourse-cdn.com/v4/letter/r/b77776/32.png) [@Raymundo\_Villa](https://forum.inductiveautomation.com/u/Raymundo_Villa)\
**Post date:** [June 21, 2022, 2:54pm UTC](https://forum.inductiveautomation.com/t/multilayered-tank-display/12793/4 "2022-06-21T14:54:40Z")

</div>

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

thanks.

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [June 21, 2022, 3:01pm UTC](https://forum.inductiveautomation.com/t/multilayered-tank-display/12793/5 "2022-06-21T15:01:19Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Raymundo\_Villa](https://avatars.discourse-cdn.com/v4/letter/r/b77776/32.png) [@Raymundo\_Villa](https://forum.inductiveautomation.com/u/Raymundo_Villa)\
**Post date:** [June 21, 2022, 8:16pm UTC](https://forum.inductiveautomation.com/t/multilayered-tank-display/12793/6 "2022-06-21T20:16:53Z")

</div>

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 ?  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/d/d/dd6ce913d69511db1413125b8d6eed482c9e6443.png)

Thanks.

---

<div class="post-metadata">

**Author:** ![witman](https://avatars.discourse-cdn.com/v4/letter/w/d2c977/32.png) [@witman](https://forum.inductiveautomation.com/u/witman)\
**Post date:** [June 21, 2022, 9:29pm UTC](https://forum.inductiveautomation.com/t/multilayered-tank-display/12793/7 "2022-06-21T21:29:24Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![JGJohnson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jgjohnson/32/29582_2.png) [@JGJohnson](https://forum.inductiveautomation.com/u/JGJohnson)\
**Post date:** [June 22, 2022, 1:09pm UTC](https://forum.inductiveautomation.com/t/multilayered-tank-display/12793/8 "2022-06-22T13:09:24Z")

</div>

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.
