Skip to content
Permalink
master
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time
---
title: Venn Diagram Generator
layout: page
---
<!-- THIS FILE IS NOT COVERED BY THE LICENSE IN THIS REPOSITORY! -->
<!-- This page is a modification of: https://www.inf.ed.ac.uk/teaching/courses/inf1/cl/tools/venn/ -->
<!-- The creator of this page is unknown. Please send an email to the repository owner if you would like this taken down. -->
<style>
circle.light.amber.on{fill:yellow}
circle.light.red.on{fill:red}
circle.light.green.on{fill:green}
/*body {
font: 12pt sans-serif;
}*/
#vennimage { width:20%; float:left;}
hr {clear:both}
i {font-weight:lighter}
code {font-size:14pt;font-style:normal}
circle { stroke:black;stroke-width:3pt; fill: none;}
circle.universe {stroke-width:5pt;}
path {stroke:black; fill: none;fill-rule:evenodd;}
path.true {fill:red}
input[type=text] {width:500px}
input:invalid { color:red }
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.7/d3.min.js" charset="utf-8"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<section>
<p>This is a tool for exploring Venn diagrams. It is based on <a href="https://www.inf.ed.ac.uk/teaching/courses/inf1/cl/tools/venn/">the official tool provided by The School of Informatics</a>.</p>
<br>
<p><strong>Heads up!</strong> Only WebKit based browsers (Chrome, Safari, Opera, etc) are supported.</p>
<h3>Instructions</h3>
<p><a href="https://betterinformatics.com/resources/inf1-cl/venn/venn.png">This diagram</a> shows the state represented by each region.</p>
<p>Your boolean expression is parsed as JavaScript, and so must be written in valid <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators">JS syntax</a>. However, to make things convenient, words like "AND" are automatically converted to the JavaScript equivalents.</p>
Here's a quick overview (note, lowercase equivalents are valid):
<ul>
<li>
The three propositional letters:
<span class="label label-danger">R</span>
<span class="label label-warning">A</span>
<span class="label label-success">G</span> (may also be written as "red", etc.)
</li>
<li>∨:
<span class="label label-info">or</span>
<span class="label label-info">||</span>
</li>
<li>∧:
<span class="label label-info">and</span>
<span class="label label-info">&amp;&amp;</span>
</li>
<li>¬:
<span class="label label-info">not</span>
<span class="label label-info">!</span>
</li>
<li>T:
<span class="label label-info">true</span>
<span class="label label-info">1</span>
<span class="label label-info">T</span>
</li>
<li>⊥:
<span class="label label-info">false</span>
<span class="label label-info">0</span>
<span class="label label-info">F</span>
</li>
<li>⊕:
<span class="label label-info">xor</span>
<span class="label label-info">^</span>
</li>
<li>↔ (if and only if):
<span class="label label-info">iff</span>
<span class="label label-info">==</span>
</li>
<li>
The <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator">
ternary operator</a>
<code>A ? B : C</code> essentially represents <code>if A then B else C</code>
</li>
</ul>
</section>
<section style="text-align: center;">
<h3 style="text-align: left">Output</h3>
<div id="errs" style="display: none; text-align: left; color: red;"></div>
<form>
<input type="text" id="prop"
inputmode="verbatim"
pattern="((\|\|)|(&&)|(==)|([aA][Nn][dD])|([rR][Ee][Dd])|([Aa][Mm][Bb][Ee][Rr])|([Gg][Rr][Ee][Ee][Nn])|([Ii][Ff][Ff])|([Xx]?[Oo][Rr])|([Nn][Oo][Tt])|[RrAaGgTtFf!01^ ()?:]|[Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee])*"
placeholder="type your expression here" autofocus>
<input type="submit" value="render" onclick="return renderDiagram()">
</form>
<br>
<svg width="256" height="256"> </svg>
</section>
<script type="text/javascript">
const x = 256;
const I = 128;
const R = 2 * I;
const R3 = I * Math.sqrt(3);
const circles = { red: [-I,-R3/3], amber: [I, -R3/3], green: [0, 2*R3/3] };
const s0 = [R,0],
s1 = [-I, R3],
s2 = [-I, -R3];
function onClick(){
var d = (X,Y) => Math.sqrt(Math.pow(X[0]-Y[0],2) + Math.pow(X[1]-Y[1],2));
for (light in circles){
d3.selectAll("circle.light." + light)
.classed("on",d(circles[light],[d3.event.clientX-512,d3.event.clientY-512]) < R)
console.log(light + d(circles[light],[d3.event.clientX-512,d3.event.clientY-512]));
}
}
var double = (xy) => [2*xy[0],2*xy[1]];
var neg = (xy) => [-xy[0],-xy[1]];
var move = (d) => "M" + d.m + (d.c.map((xy) => " a" + [[R,R] , 0, xy[1], xy[0]].join(", "))) + (d.neg == 1 ? ("M" +[0,3.5*I]+ "a" + [3*I ,3*I ,0,0,0,0,-7*I] + "a" + [3*I ,3*I ,0,0,0,0,7*I]) : "");
var svg = d3.select("svg")
.on('click', onClick)
.selectAll("g")
.data(d3.range(1))
.enter()
.append("g")
.attr("id", d=> "g"+d)
.attr("transform", d => "translate(" + [(0.5+d) * x, 0.5 * x] +")scale(0.25)")
.call(venn)
function venn(svg){
svg.selectAll("circle.prop")
.data( ["red","amber","green"])
.enter()
.append("circle")
.attr("class", d => d)
.classed("prop",true)
.attr("cx", d => circles[d][0])
.attr("cy", d => circles[d][1])
.attr("r", R)
svg.append("circle")
.attr("cx", 0)
.attr("cy",0)
.attr("r", 3.5*I)
.classed("universe",true)
// svg.selectAll("circle.light")
// .data(["red","amber","green"])
// .enter()
// .append("circle")
// .attr("class", d => d)
// .classed("light",true)
// .attr("r", 40)
// .attr("cx", 60-512)
// .attr("cy",(d,i) => 60 + 90*i -512)
svg
.selectAll("path")
.data([{m:[-I,-R3/3],c:[[s0,[0,1]],[s1,[0,1]],[s2,[0,1]]],neg:0,id:"111"},
{m:[R,2*R3/3],c:[[s2,[0,0]],[s1,[0,1]],[s0,[0,0]]],neg:0,id:"011"},
{m:[-R,2*R3/3],c:[[neg(s1),[0,1]],[neg(s2),[0,0]],[neg(s0),[0,1]]],neg:0,id:"101"},
{m:[-I,-R3/3],c:[[s0,[0,1]],[s2,[0,0]],[s1,[0,0]]],neg:0,id:"110"},
{m:[0,2*R3/3],c:[[s0,[0,0]],[double(neg(s0)),[1,1]],[s0,[0,0]]],neg:0,id:"001"},
{m:[-I,-R3/3],c:[[s1,[0,0]],[double(neg(s1)),[1,1]],[s1,[0,0]]],neg:0,id:"100"},
{m:[I,-R3/3],c:[[s2,[0,0]],[double(neg(s2)),[1,1]],[s2,[0,0]]],neg:0,id:"010"},
{m:[R,2*R3/3],c:[[double((s2)),[0,0]],[double((s1)),[0,0]],[double((s0)),[0,0]]],neg:1,id:"000"}
])
.enter()
.append("path")
.attr("d",move)
}
function bval (expression, id) {
var r = red = id.charAt(0) == 1;
var a = amber = id.charAt(1) == 1;
var g = green = id.charAt(2) == 1;
var t = 1;
var f = 0;
return eval(expression.toString());
}
function renderDiagram(ev) {
var expression = document.getElementById("prop").value.toLowerCase();
expression = replaceAll(expression, "and", "&&")
expression = replaceAll(expression, "xor", "^")
expression = replaceAll(expression, "or", "||")
expression = replaceAll(expression, "not", "!")
expression = replaceAll(expression, "iff", "==")
console.log("Expression", expression);
try {
bval(expression, "000");
} catch (e) {
$("#errs").show()
$("#errs").html("<strong>" + e.name + ":</strong> " + e.message)
return false;
}
$("#errs").hide()
d3.selectAll("#g0 path").classed("true", d => {
// console.log({e:expression,id: d.id, v:bval(expression, d.id)});
return bval (expression, d.id);
}
);
return false;
}
function replaceAll(str, find, replace) {
const escaped = find.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
return str.replace(new RegExp(escaped, 'g'), replace);
}
</script>