Skip to content

Instantly share code, notes, and snippets.

@elbosso
Last active January 1, 2021 13:15
Show Gist options
  • Save elbosso/8e6cf0fb700f6be6452399c1b399c6c5 to your computer and use it in GitHub Desktop.
Save elbosso/8e6cf0fb700f6be6452399c1b399c6c5 to your computer and use it in GitHub Desktop.
Truchet tiling - conceived after going down yet another rabbithole because of operation mindfuck@rc3 (https://media.ccc.de/v/rc3-501024-operation_mindfuck_vol_4)
/*
* Copyright (c) 2021.
*
* Juergen Key. Alle Rechte vorbehalten.
*
* Weiterverbreitung und Verwendung in nichtkompilierter oder kompilierter Form,
* mit oder ohne Veraenderung, sind unter den folgenden Bedingungen zulaessig:
*
* 1. Weiterverbreitete nichtkompilierte Exemplare muessen das obige Copyright,
* die Liste der Bedingungen und den folgenden Haftungsausschluss im Quelltext
* enthalten.
* 2. Weiterverbreitete kompilierte Exemplare muessen das obige Copyright,
* die Liste der Bedingungen und den folgenden Haftungsausschluss in der
* Dokumentation und/oder anderen Materialien, die mit dem Exemplar verbreitet
* werden, enthalten.
* 3. Weder der Name des Autors noch die Namen der Beitragsleistenden
* duerfen zum Kennzeichnen oder Bewerben von Produkten, die von dieser Software
* abgeleitet wurden, ohne spezielle vorherige schriftliche Genehmigung verwendet
* werden.
*
* DIESE SOFTWARE WIRD VOM AUTOR UND DEN BEITRAGSLEISTENDEN OHNE
* JEGLICHE SPEZIELLE ODER IMPLIZIERTE GARANTIEN ZUR VERFUEGUNG GESTELLT, DIE
* UNTER ANDEREM EINSCHLIESSEN: DIE IMPLIZIERTE GARANTIE DER VERWENDBARKEIT DER
* SOFTWARE FUER EINEN BESTIMMTEN ZWECK. AUF KEINEN FALL IST DER AUTOR
* ODER DIE BEITRAGSLEISTENDEN FUER IRGENDWELCHE DIREKTEN, INDIREKTEN,
* ZUFAELLIGEN, SPEZIELLEN, BEISPIELHAFTEN ODER FOLGENDEN SCHAEDEN (UNTER ANDEREM
* VERSCHAFFEN VON ERSATZGUETERN ODER -DIENSTLEISTUNGEN; EINSCHRAENKUNG DER
* NUTZUNGSFAEHIGKEIT; VERLUST VON NUTZUNGSFAEHIGKEIT; DATEN; PROFIT ODER
* GESCHAEFTSUNTERBRECHUNG), WIE AUCH IMMER VERURSACHT UND UNTER WELCHER
* VERPFLICHTUNG AUCH IMMER, OB IN VERTRAG, STRIKTER VERPFLICHTUNG ODER
* UNERLAUBTE HANDLUNG (INKLUSIVE FAHRLAESSIGKEIT) VERANTWORTLICH, AUF WELCHEM
* WEG SIE AUCH IMMER DURCH DIE BENUTZUNG DIESER SOFTWARE ENTSTANDEN SIND, SOGAR,
* WENN SIE AUF DIE MOEGLICHKEIT EINES SOLCHEN SCHADENS HINGEWIESEN WORDEN SIND.
*
*/
//inspired by
//https://christophercarlson.com/portfolio/multi-scale-truchet-patterns/
//https://media.ccc.de/v/rc3-501024-operation_mindfuck_vol_4
package de.elbosso.scratch.algorithms.graphics;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
public class Truchet extends java.lang.Object
{
private final java.util.Random rand=new java.util.Random(System.currentTimeMillis());
public Truchet(java.awt.Dimension dim,int tilesize,boolean evenOdd,java.io.File f) throws IOException
{
super();
int minTilesize=tilesize/8+1;
java.awt.image.BufferedImage bimg=produceImage(dim,tilesize,minTilesize,evenOdd);
javax.imageio.ImageIO.write(bimg,"png",f);
}
public static void main(java.lang.String[] args) throws IOException
{
java.io.File f=java.io.File.createTempFile("truchet",".png");
System.out.println(f);
Truchet truchet=new Truchet(new java.awt.Dimension(4,4),256,true,f);
}
private java.awt.image.BufferedImage produceImage(java.awt.Dimension dim,int tilesize,int minTilesize,boolean evenOdd)
{
java.awt.image.BufferedImage bimg=new java.awt.image.BufferedImage((dim.width+1)*tilesize,(dim.height+1)*tilesize, BufferedImage.TYPE_INT_ARGB);
java.awt.Graphics2D g2=bimg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,RenderingHints.VALUE_COLOR_RENDER_QUALITY);
int size=bimg.getHeight();
for(int y=0;y<dim.height;++y)
{
double ycoord=(double)y/(double)(dim.height+1)*(double)size;
for(int x=0;x<dim.width;++x)
{
double xcoord=(double)x/(double)(dim.width+1)*(double)size;
g2.drawImage(produceTile(tilesize, rand.nextBoolean(), evenOdd?Color.black:Color.WHITE,evenOdd? Color.white: Color.black),(int)xcoord,(int)ycoord,null);
}
}
for(int y=0;y<dim.height;++y)
{
double ycoord=(double)y/(double)(dim.height+1)*(double)size;
for(int x=0;x<dim.width;++x)
{
double xcoord=(double)x/(double)(dim.width+1)*(double)size;
if((rand.nextBoolean())&&(minTilesize<tilesize/2))
g2.drawImage(produceImage(new java.awt.Dimension(2,2),tilesize/2,minTilesize,!evenOdd),(int)xcoord+tilesize/4,(int)ycoord+tilesize/4,null);
}
}
g2.dispose();
return bimg;
}
private BufferedImage produceTile(int size,boolean rotated,java.awt.Paint a, java.awt.Paint b)
{
java.awt.image.BufferedImage rv=new java.awt.image.BufferedImage(size*2,size*2, BufferedImage.TYPE_INT_ARGB);
java.awt.Graphics2D g2=rv.createGraphics();
double oneThird=.333333*(double)size;
double onesixth=0.5*oneThird;
double twoThirds=.666667*(double)size;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,RenderingHints.VALUE_COLOR_RENDER_QUALITY);
if(rotated==true)
{
g2.setTransform(AffineTransform.getQuadrantRotateInstance(1,size,size));
}
g2.setPaint(a);
g2.fillRect(size/2,size/2,size,size);
g2.setPaint(b);
g2.fillArc(-(int)onesixth,-(int)onesixth,size+(int)oneThird,size+(int)oneThird,0,-90);
g2.fillArc(size-(int)onesixth,size-(int)onesixth,size+(int)oneThird,size+(int)oneThird,90,90);
g2.fillOval(size-(int)onesixth,size/2-(int)onesixth,(int)oneThird,(int)oneThird);
g2.fillOval(size-(int)onesixth,size*3/2-(int)onesixth,(int)oneThird,(int)oneThird);
g2.fillOval((int)oneThird,size-(int)onesixth,(int)oneThird,(int)oneThird);
g2.fillOval((int)oneThird+size,size-(int)onesixth,(int)oneThird,(int)oneThird);
g2.setPaint(a);
g2.fillOval(size/2+(int)-oneThird,size/2+(int)-oneThird,(int)twoThirds,(int)twoThirds);
g2.fillOval(size/2+(int)twoThirds,size/2+(int)twoThirds,(int)twoThirds,(int)twoThirds);
g2.fillOval(size/2+(int)+twoThirds,size/2+(int)-oneThird,(int)twoThirds,(int)twoThirds);
g2.fillOval(size/2+(int)-oneThird,size/2+(int)twoThirds,(int)twoThirds,(int)twoThirds);
g2.dispose();
return rv;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment