Service information

Plans

free

Platforms

Description

Penrose is a free online service that allows users to generate venn diagrams, hypercube diagrams, and mobius strip diagrams. Simply type notation in plain text to create beautiful diagrams and gain deeper insight into technical concepts. Accessible through the website.

Examples

🔄📊

Generate Mobius Strip Diagram

inputs

Node n0_i for i in [0,15]

Node n1_i for i in [0,15]

Node n2_i for i in [0,15]

Node n3_i for i in [0,15]

Node n4_i for i in [0,15]

Node n5_i for i in [0,15]

-- horizontal edges

Edge u0_i := MakeEdge( n0_i, n0_j ) for i in [0,15], j in [0,14] where j == (i + 1) mod 16

Edge u1_i := MakeEdge( n1_i, n1_j ) for i in [0,15], j in [0,14] where j == (i + 1) mod 16

Edge u2_i := MakeEdge( n2_i, n2_j ) for i in [0,15], j in [0,14] where j == (i + 1) mod 16

Edge u3_i := MakeEdge( n3_i, n3_j ) for i in [0,15], j in [0,14] where j == (i + 1) mod 16

Edge u4_i := MakeEdge( n4_i, n4_j ) for i in [0,15], j in [0,14] where j == (i + 1) mod 16

Edge u5_i := MakeEdge( n5_i, n5_j ) for i in [0,15], j in [0,14] where j == (i + 1) mod 16

-- join last column with opposite identification

Edge u0_f := MakeEdge( n0_14, n5_15 )

Edge u1_f := MakeEdge( n1_14, n4_15 )

Edge u2_f := MakeEdge( n2_14, n3_15 )

Edge u3_f := MakeEdge( n3_14, n2_15 )

Edge u4_f := MakeEdge( n4_14, n1_15 )

Edge u5_f := MakeEdge( n5_14, n0_15 )

-- vertical edges

Edge v0_i := MakeEdge( n0_i, n1_i ) for i in [0,15]

Edge v1_i := MakeEdge( n1_i, n2_i ) for i in [0,15]

Edge v2_i := MakeEdge( n2_i, n3_i ) for i in [0,15]

Edge v3_i := MakeEdge( n3_i, n4_i ) for i in [0,15]

Edge v4_i := MakeEdge( n4_i, n5_i ) for i in [0,15]

type Node

type Edge

constructor MakeEdge(Node a, Node b) -> Edge

canvas {

 width = 900

 height = 900

}

colors {

 scalar hue = ?

 color background = hsva(hue, 80, 40, 1)

 color bloom = hsva(hue, 50, 80, .6)

 color center = hsva(hue, 0, 100, 1)

 color edge = hsva(hue, 20, 90, 0.5)

 color black = #000000ff

}

camera {

 -- Camera viewpoint

 vec3 eye = (500, 500, 500)

 vec3 center = (0, 0, 0)

 vec3 up = (0, 1, 0)

 mat4x4 model = lookAt( eye, center, up )

 -- Camera projection

 scalar fovy = 10

 scalar aspect = canvas.width / canvas.height

 scalar near = 1

 scalar far = 4

 mat4x4 proj = perspective( fovy, aspect, near, far )

 -- Viewport

 list view = [ -canvas.width/2, -canvas.height/2, canvas.width, canvas.height ]

}

global {

 shape background = Rectangle {

  center: (0,0)

  width: canvas.width

  height: canvas.height

  fillColor: colors.background

  ensureOnCanvas: false

 }

 shape shade = Circle {

  center: (0,0)

  r: canvas.width / 2

  fillColor: colors.black

  style: "filter:blur(100px);"

  ensureOnCanvas: false

 }

 shade above background

}

forall Node n {

 vec3 n.center = (?, ?, ?)

 vec2 n.center2 = project( n.center, camera.model, camera.proj, camera.view )

 scalar n.normsq = normsq(n.center)

 scalar n.size = max(5, (-820 + vdist(camera.eye, n.center)) / 7)

 shape n.icon = Circle {

  center: n.center2

  r: n.size

  fillColor: colors.bloom

  style: "filter:blur(1.8px);"

  ensureOnCanvas: false

 }

 shape n.icon2 = Circle {

  center: n.center2

  r: 0.5 * n.size

  fillColor: colors.center

  style: "filter:blur(0.4px);"

  ensureOnCanvas: false

 }

 n.icon2 above n.icon

}

forall Edge e; Node a; Node b

where e := MakeEdge(a, b) {

 scalar e.distsq = vdistsq(a.center, b.center)

 scalar e.size = 0.5 * (a.size + b.size)

 shape e.icon = Line {

  start: a.icon.center

  end: b.icon.center

  strokeWidth: 0.3 * e.size

  strokeColor: colors.edge

  style: "filter:blur(0.3px);"

  ensureOnCanvas: false

 }

}

forall Node n; Edge e {

 e.icon below n.icon

}

collect Node n into nodes {

 normsqs = listof normsq from nodes

 centers = listof center from nodes

 scalar scaleFactor = 30

 scalar scale = (canvas.width / scaleFactor) * (canvas.height / scaleFactor)

 ensure sum(normsqs) / count(normsqs) == scale

 ensure norm(sumVectors(centers)) == 0

}

collect Edge e into edges

where e := MakeEdge(a, b)

foreach Node a; Node b {

 distsqs = listof distsq from edges

 encourage sum(distsqs) == 0

}

outputs
🔲🔳

Generate Hypercube Diagram

inputs

canvas {

 width = 400

 height = 400

}

colors {

 contour = #00000093

}

global {

  scalar colorOffset = random(0, 100)

  shape background = Rectangle {

    center: (0, 0)

    width: canvas.width

    height: canvas.height

    fillColor: hsva(colorOffset, 10, 100, 1)

    ensureOnCanvas: false

  } 

}

forall Node n {

  vec2 n.center = (?, ?)

  scalar n.normsq = normsq(n.center)

  scalar fillHue = global.colorOffset + 1.7 * norm(n.center)

  shape n.icon = Circle {

    center: n.center

    r: 6 - 0.03 * norm(n.center)

    fillColor: hsva(fillHue, 100, 100, 1)

    strokeColor: colors.contour

    strokeWidth: 2.6 - 0.008 * norm(n.center)

    ensureOnCanvas: false

  }

  shape n.bloom = Circle {

    center: n.icon.center

    r: n.icon.r

    fillColor: n.icon.fillColor

    strokeColor: n.icon.strokeColor

    strokeWidth: n.icon.strokeWidth

    ensureOnCanvas: false

  }

}

collect Node n into nodes {

  blooms = listof bloom from nodes

  

  shape nodeShadows = Group {

   shapes: blooms

   style: "filter:blur(3px);"

  }

}

forall Edge e; Node a; Node b

where e := MakeEdge(a, b) {

  scalar e.distsq = vdistsq(a.center, b.center)

  shape e.icon = Line {

    start: a.center

    end: b.center

    strokeWidth: 75 / vdist(a.center, b.center)

    strokeColor: colors.contour

    ensureOnCanvas: false

  }

  shape e.bloom = Line {

    start: e.icon.start

    end: e.icon.end

    strokeWidth: e.icon.strokeWidth

    strokeColor: e.icon.strokeColor

    ensureOnCanvas: false

  }

  layer e.bloom below a.icon

  layer e.bloom below b.icon

}

collect Edge e into edges {

  blooms = listof bloom from edges

  

  shape nodeShadows = Group {

   shapes: blooms

   style: "filter:blur(2px);"

  }

}

forall Node n; Edge e {

  e.icon below n.icon

}

collect Node n into nodes {

  normsqs = listof normsq from nodes

  centers = listof center from nodes

  scalar scale = (canvas.width / 5) * (canvas.height / 5)

  ensure sum(normsqs) / count(normsqs) == scale

  ensure norm(sumVectors(centers)) == 0

}

collect Edge e into edges

where e := MakeEdge(a, b)

foreach Node a; Node b {

  distsqs = listof distsq from edges

  encourage sum(distsqs) == 0

}

Node n0x0x0x0

Node n0x0x0x1

Node n0x0x1x0

Node n0x0x1x1

Node n0x1x0x0

Node n0x1x0x1

Node n0x1x1x0

Node n0x1x1x1

Node n1x0x0x0

Node n1x0x0x1

Node n1x0x1x0

Node n1x0x1x1

Node n1x1x0x0

Node n1x1x0x1

Node n1x1x1x0

Node n1x1x1x1

Edge e0 := MakeEdge(n0x0x0x0, n1x0x0x0)

Edge e1 := MakeEdge(n0x0x0x0, n0x1x0x0)

Edge e2 := MakeEdge(n0x0x0x0, n0x0x1x0)

Edge e3 := MakeEdge(n0x0x0x0, n0x0x0x1)

Edge e4 := MakeEdge(n0x0x0x1, n1x0x0x1)

Edge e5 := MakeEdge(n0x0x0x1, n0x1x0x1)

Edge e6 := MakeEdge(n0x0x0x1, n0x0x1x1)

Edge e7 := MakeEdge(n0x0x1x0, n1x0x1x0)

Edge e8 := MakeEdge(n0x0x1x0, n0x1x1x0)

Edge e9 := MakeEdge(n0x0x1x0, n0x0x1x1)

Edge e10 := MakeEdge(n0x0x1x1, n1x0x1x1)

Edge e11 := MakeEdge(n0x0x1x1, n0x1x1x1)

Edge e12 := MakeEdge(n0x1x0x0, n1x1x0x0)

Edge e13 := MakeEdge(n0x1x0x0, n0x1x1x0)

Edge e14 := MakeEdge(n0x1x0x0, n0x1x0x1)

Edge e15 := MakeEdge(n0x1x0x1, n1x1x0x1)

Edge e16 := MakeEdge(n0x1x0x1, n0x1x1x1)

Edge e17 := MakeEdge(n0x1x1x0, n1x1x1x0)

Edge e18 := MakeEdge(n0x1x1x0, n0x1x1x1)

Edge e19 := MakeEdge(n0x1x1x1, n1x1x1x1)

Edge e20 := MakeEdge(n1x0x0x0, n1x1x0x0)

Edge e21 := MakeEdge(n1x0x0x0, n1x0x1x0)

Edge e22 := MakeEdge(n1x0x0x0, n1x0x0x1)

Edge e23 := MakeEdge(n1x0x0x1, n1x1x0x1)

Edge e24 := MakeEdge(n1x0x0x1, n1x0x1x1)

Edge e25 := MakeEdge(n1x0x1x0, n1x1x1x0)

Edge e26 := MakeEdge(n1x0x1x0, n1x0x1x1)

Edge e27 := MakeEdge(n1x0x1x1, n1x1x1x1)

Edge e28 := MakeEdge(n1x1x0x0, n1x1x1x0)

Edge e29 := MakeEdge(n1x1x0x0, n1x1x0x1)

Edge e30 := MakeEdge(n1x1x0x1, n1x1x1x1)

Edge e31 := MakeEdge(n1x1x1x0, n1x1x1x1)

type Node

type Edge

constructor MakeEdge(Node a, Node b) -> Edge

outputs
🔵🔘

Generate Venn Diagram

inputs

Set A, B, C, D, E, F, G

IsSubset(B, A)

IsSubset(C, A)

IsSubset(D, B)

IsSubset(E, B)

IsSubset(F, C)

IsSubset(G, C)

NotIntersecting(E, D)

NotIntersecting(F, G)

NotIntersecting(B, C)

AutoLabel All

canvas {

width = 800

height = 700

}

forall Set x {

shape x.icon = Circle { }

shape x.text = Equation {

string : x.label

fontSize : "32px"

}

ensure contains(x.icon, x.text)

encourage norm(x.text.center - x.icon.center) == 0

layer x.text above x.icon

}

forall Set x; Set y

where IsSubset(x, y) {

ensure disjoint(y.text, x.icon, 10)

ensure contains(y.icon, x.icon, 5)

layer x.icon above y.icon

}

forall Set x; Set y

where NotIntersecting(x, y) {

ensure disjoint(x.icon, y.icon)

}

forall Set x; Set y

where Intersecting(x, y) {

ensure overlapping(x.icon, y.icon)

ensure disjoint(y.text, x.icon)

ensure disjoint(x.text, y.icon)

}

type Set

predicate NotIntersecting(Set s1, Set s2)

predicate Intersecting(Set s1, Set s2)

predicate IsSubset(Set s1, Set s2)

outputs
Share this page: