Venn diagrams are well known for data visualization. They are used to show the intersection between sets of data. As an example, you could have two groups of objects: one object could belong to both groups, while another could only belong to the first group. Venn diagrams help show that relationship. In this recipe, we will demonstrate how to create Venn diagrams that use two, three, and four sets of data.
Reading the Wikipedia page on Venn diagrams could help you to understand the background behind those diagrams: http://en.wikipedia.org/wiki/Venn_diagram.
The following are the steps required to make a Venn diagram:
public class VennEllipse extends Sprite { public function VennEllipse(circleWidth:Number, color:uint) { graphics.beginFill(color, 0.5); graphics.drawEllipse(-circleWidth/2, -circleWidth/4, circleWidth, circleWidth / 2); graphics.endFill(); } }
public function createGraph():void { var circle1:VennCircle = new VennCircle(_graphWidth * 0.6, 0xff0000); addChild(circle1); var circle2:VennCircle = new VennCircle(_graphWidth * 0.6, 0x0000ff); circle2.x = _graphWidth * 0.4; addChild(circle2); var textFormat:TextFormat = new TextFormat("Arial", 14); var label1:TextField = new TextField(); label1.defaultTextFormat = textFormat; label1.text = _labels[0]; label1.width = label1.textWidth + 5; label1.height = label1.textHeight + 3; label1.x = _graphWidth * 0.6 / 2 - label1.width / 2; label1.y = _graphWidth * 0.6 + 10; addChild(label1); var label2:TextField = new TextField(); label2.defaultTextFormat = textFormat; label2.text = _labels[1]; label2.width = label2.textWidth + 5; label2.height = label2.textHeight + 3; label2.x = _graphWidth * 0.6 / 2 - label2.width / 2 + _graphWidth*0.4; label2.y = _graphWidth * 0.6 + 10; addChild(label2); }
var ellipse1:VennEllipse = new VennEllipse(_graphWidth * 0.75, 0xff0000); ellipse1.y = _graphWidth * 0.45; ellipse1.x = _graphWidth * 0.52; ellipse1.rotation = 45; addChild(ellipse1); var ellipse2:VennEllipse = new VennEllipse(_graphWidth * 0.75, 0x0000ff); ellipse2.y = _graphWidth * 0.45; ellipse2.x = _graphWidth * 0.52; ellipse2.rotation = -45; addChild(ellipse2); var ellipse3:VennEllipse = new VennEllipse(_graphWidth * 0.75, 0xffff00); ellipse3.y = _graphWidth * 0.40 + _graphWidth * 0.2; ellipse3.x = _graphWidth * 0.52 + _graphWidth * 0.2; ellipse3.rotation = -45; addChild(ellipse3); var ellipse4:VennEllipse = new VennEllipse(_graphWidth * 0.75, 0x00ff00); ellipse4.y = _graphWidth * 0.40 + _graphWidth * 0.2; ellipse4.x = _graphWidth * 0.52 - _graphWidth * 0.2; ellipse4.rotation = 45; addChild(ellipse4);
public interface IVennDiagram { function createGraph():void; function setLabels(labels:Vector.<String>):void; function setGraphWidth(graphWidth:Number):void; }
VennDiagram.as
file, which is basically a switch
statement depending on how many labels are present.Main.as
class shows the created Venn diagram and the data.The thing with Venn diagrams is that depending on how many sets (groups) they illustrate, they are very different. To palliate to that, we will create a different class for each number of sets that our data will represent: Venn2Circles.as
, Venn3Circles.as
, and Venn4Ellipses.as
.
Venn2Circles.as
and Venn3Circles.as
are simple. We just need to position the circles and the labels correctly and we are done. Note that the fill color of the circles is semitransparent so that the intersecting region gets its own color (a mix of the other circle's color).
When we use four sets it gets a bit more complicated. We need to use ellipses instead of circles if we want a diagram that has all the possible intersecting regions and is still easy to understand. Ellipses are different than circles; you draw them from their top-left corner instead of their center. Since we are going to rotate them, we will offset them so that the rotation point is at the center of the ellipse. After that it is only a matter of positioning the ellipses.
Once we have those three classes done, we will create an interface for them so that the VennDiagram.as
class that we will create thereafter can use any of them interchangeably and it will also keep the code very clean. The VennDiagram.as
class is only a switch
statement that looks at how many labels were given to the graph and decides which of the classes, Venn2Circles.as
, Venn3Circles.as
, or Venn4Ellipses.as
, can be used.
The Main.as
class shows how to create the labels (in this case, the labels are the data) and uses the similar syntax we have been using to create the graph.
By making it interactive and adding the possibilities to use more sets we could improve on this recipe.
One very good feature that could be implemented would be the one where if you mouse over one region of the diagram, then a label would open up and indicate which intersection of sets it is. This could be done using hitTestPoint
and testing against all the circles or ellipses.
As we introduce more sets, the diagram gets more complex and harder to understand. If we wanted our VennDiagram.as
class to support five or six sets, we would need to use different shapes other than circles and ellipses. I would advise going with Edwards' Venn diagrams, available at http://en.wikipedia.org/wiki/Venn_diagram, because they are much clearer and could be done using the curveTo
calls (a lot of them could use the curveTo
calls, but it could still be done).
52.14.204.142