/*
* GraphPaper: PDF graph paper generator.
*
* Draws multi-weight grid lines, borders and cross grid,
* using metric or imperial measures.
*
* Copyright (c) Daniel Jones 2010.
*
*
* This program can be freely distributed and modified under the
* terms of the GNU General Public License version 2.
*
*
*--------------------------------------------------------------*/
import processing.core.*;
import processing.pdf.*;
/*-----------------------------------------------------------------
* Config: grid lines
*----------------------------------------------------------------*/
boolean drawLines = true;
float majorLinesPerUnit = 0.5;
float minorLinesPerUnit = 2;
float microLinesPerUnit = 10;
int majorLineColor = color(255, 0, 0);
int minorLineColor = color(128);
int microLineColor = color(192);
float majorLineWeight = 1.f;
float minorLineWeight = 0.8f;
float microLineWeight = 0.3f;
/*-----------------------------------------------------------------
* Config: borders
*----------------------------------------------------------------*/
boolean drawBorders = true;
int outerLineColor = color(0);
float outerLineWeight = 2.0f;
/*-----------------------------------------------------------------
* Config: dots or pluses
*----------------------------------------------------------------*/
boolean drawPluses = false;
float majorPlusesPerUnit = 0.5f;
float minorPlusesPerUnit = 2.0f;
int majorPlusColor = color(0);
int minorPlusColor = color(128);
float majorPlusWeight = 2.0f;
float minorPlusWeight = 1.0f;
float majorPlusLength = 0.2f;
float minorPlusLength = 0.1f;
/*-----------------------------------------------------------------
* Config: margins, pages, units
*----------------------------------------------------------------*/
float marginUnits = 2.5f;
int pages = 2;
boolean useImperial = false;
/*-----------------------------------------------------------------
* Config: page size (mapped to pixels at 300 DPI)
*----------------------------------------------------------------*/
int [] PAPER_SIZE_A4 = new int[] { 2480, 3508 }; // int'l A4
int [] PAPER_SIZE_A3 = new int[] { 3508, 4961 }; // int'l A3
int [] PAPER_SIZE_LETTER = new int[] { 2550, 3300 }; // US letter (8.5 x 11)
int [] PAPER_SIZE_TABLOID = new int[] { 3300, 5100 }; // US tabloid (11 x 17)
int [] paperSize = PAPER_SIZE_A4; // change me
/*-----------------------------------------------------------------
* Misc fields
*----------------------------------------------------------------*/
float oneCentimetre = 118.0f;
float oneInch = 300.0f;
float oneUnit = oneCentimetre;
static Hashtable paperSizes;
void setup()
{
size(paperSize[0], paperSize[1], PDF, "sheet.pdf");
this.setImperial(useImperial);
}
public void draw()
{
background(255);
noFill();
drawGraph();
PGraphicsPDF pdf = (PGraphicsPDF) g;
if (frameCount == pages)
exit();
else
pdf.nextPage();
}
public void drawGraph()
{
/*-----------------------------------------------------------------
* Calculate global measurements, truncating to nearest integer
* number of major lines.
*----------------------------------------------------------------*/
PVector totalAvailableSize = new PVector
(
(float) Math.floor(width - (2 * marginUnits * oneUnit)),
(float) Math.floor(height - (2 * marginUnits * oneUnit))
);
float majorLineWidth = oneUnit / majorLinesPerUnit;
float minorLineWidth = oneUnit / minorLinesPerUnit;
float microLineWidth = oneUnit / microLinesPerUnit;
PVector totalMajorLineCount = new PVector
(
(float) Math.floor(totalAvailableSize.x / majorLineWidth),
(float) Math.floor(totalAvailableSize.y / majorLineWidth)
);
PVector totalMinorLineCount = new PVector
(
totalMajorLineCount.x * (minorLinesPerUnit / majorLinesPerUnit),
totalMajorLineCount.y * (minorLinesPerUnit / majorLinesPerUnit)
);
PVector totalMicroLineCount = new PVector
(
totalMajorLineCount.x * (microLinesPerUnit / majorLinesPerUnit),
totalMajorLineCount.y * (microLinesPerUnit / majorLinesPerUnit)
);
PVector totalGraphSize = new PVector
(
(float) totalMajorLineCount.x * majorLineWidth,
(float) totalMajorLineCount.y * majorLineWidth
);
translate(marginUnits * oneUnit, marginUnits * oneUnit);
/*-----------------------------------------------------------------
* Draw: lines
*----------------------------------------------------------------*/
if (drawLines)
{
stroke(microLineColor);
strokeWeight(microLineWeight);
for (int x = 0; x <= totalMicroLineCount.x; x++)
line(x * microLineWidth, 0, x * microLineWidth, totalGraphSize.y);
for (int y = 0; y <= totalMicroLineCount.y; y++)
line(0, y * microLineWidth, totalGraphSize.x, y * microLineWidth);
stroke(minorLineColor);
strokeWeight(minorLineWeight);
for (int x = 0; x <= totalMinorLineCount.x; x++)
line(x * minorLineWidth, 0, x * minorLineWidth, totalGraphSize.y);
for (int y = 0; y <= totalMinorLineCount.y; y++)
line(0, y * minorLineWidth, totalGraphSize.x, y * minorLineWidth);
stroke(majorLineColor);
strokeWeight(majorLineWeight);
for (int x = 0; x <= totalMajorLineCount.x; x++)
line(x * majorLineWidth, 0, x * majorLineWidth, totalGraphSize.y);
for (int y = 0; y <= totalMajorLineCount.y; y++)
line(0, y * majorLineWidth, totalGraphSize.x, y * majorLineWidth);
}
/*-----------------------------------------------------------------
* Draw: outer border
*----------------------------------------------------------------*/
if (drawBorders)
{
stroke(outerLineColor);
strokeWeight(outerLineWeight);
rect(0, 0, totalGraphSize.x, totalGraphSize.y);
}
/*-----------------------------------------------------------------
* Draw: pluses
*----------------------------------------------------------------*/
if (drawPluses)
{
float majorPlusWidth = oneUnit / majorPlusesPerUnit;
float minorPlusWidth = oneUnit / minorPlusesPerUnit;
PVector totalMajorPlusCount = new PVector
(
(float) Math.floor(totalAvailableSize.x / majorPlusWidth),
(float) Math.floor(totalAvailableSize.y / majorPlusWidth)
);
PVector totalMinorPlusCount = new PVector
(
(float) totalMajorPlusCount.x * (minorPlusesPerUnit / majorPlusesPerUnit),
(float) totalMajorPlusCount.y * (minorPlusesPerUnit / majorPlusesPerUnit)
);
stroke(minorPlusColor);
strokeWeight(minorPlusWeight);
float halfMinorPlus = minorPlusLength * oneUnit * 0.5f;
float halfMajorPlus = majorPlusLength * oneUnit * 0.5f;
for (int x = 1; x < totalMinorPlusCount.x; x++)
for (int y = 1; y < totalMinorPlusCount.y; y++)
{
line(x * minorPlusWidth - halfMinorPlus, y * minorPlusWidth, x * minorPlusWidth + halfMinorPlus, y * minorPlusWidth);
line(x * minorPlusWidth, y * minorPlusWidth - halfMinorPlus, x * minorPlusWidth, y * minorPlusWidth + halfMinorPlus);
}
stroke(majorPlusColor);
strokeWeight(majorPlusWeight);
for (int x = 1; x < totalMajorPlusCount.x; x++)
for (int y = 1; y < totalMajorPlusCount.y; y++)
{
line(x * majorPlusWidth - halfMajorPlus, y * majorPlusWidth, x * majorPlusWidth + halfMajorPlus, y * majorPlusWidth);
line(x * majorPlusWidth, y * majorPlusWidth - halfMajorPlus, x * majorPlusWidth, y * majorPlusWidth + halfMajorPlus);
}
}
}
public void setImperial(boolean value)
{
useImperial = value;
oneUnit = useImperial ? oneInch : oneCentimetre;
}