Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/BasicExample/BasicExample.pde
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ void setup() {
2*margin + size + 2*size/3, 6*margin + 5*size + 3*size/4, // Third point
2*margin + 2*size, 6*margin + 5*size + size/2 // Fourth point
};
pp.spline(fadePoints, true);
pp.spline(fadePoints, true, false);
labelText("Full fade", 2*margin + size + size/2, 6*margin + 6*size + 20);

float[] firstSegmentFadePoints = {
Expand Down
144 changes: 51 additions & 93 deletions src/paperandpencil/PaperAndPencil.java
Original file line number Diff line number Diff line change
Expand Up @@ -150,18 +150,6 @@ public void line(float x1, float y1, float x2, float y2, boolean fade) {
}
}

/**
* Draws a line with a pencil-like effect.
*
* @param x1 x-coordinate of the start point
* @param y1 y-coordinate of the start point
* @param x2 x-coordinate of the end point
* @param y2 y-coordinate of the end point
*/
public void line(float x1, float y1, float x2, float y2) {
line(x1, y1, x2, y2, false);
}

/**
* Draws a rectangle with a pencil-like effect.
*
Expand Down Expand Up @@ -205,20 +193,19 @@ public void fillCircle(float centerX, float centerY, float diameter) {
}

/**
* Draws a cubic Bézier curve with a pencil-like effect.
*
* @param x1 x-coordinate of the start point
* @param y1 y-coordinate of the start point
* @param cx1 x-coordinate of the first control point
* @param cy1 y-coordinate of the first control point
* @param cx2 x-coordinate of the second control point
* @param cy2 y-coordinate of the second control point
* @param x2 x-coordinate of the end point
* @param y2 y-coordinate of the end point
* @param fade if true, applies a fade effect from start to end
* Helper method to calculate fade alpha value based on progress
*/
public void bezier(float x1, float y1, float cx1, float cy1,
float cx2, float cy2, float x2, float y2, boolean fade) {
private float calculateFadeAlpha(float progress, float fadeStart, float fadeEnd) {
float fadeProgress = fadeStart + (fadeEnd - fadeStart) * progress;
return p.alpha(pencilColor) * fadeProgress;
}

/**
* Helper method to plot points along a Bézier curve with fade control
*/
private void plotBezierCurve(float x1, float y1, float cx1, float cy1,
float cx2, float cy2, float x2, float y2,
boolean fade, float fadeStart, float fadeEnd) {
p.noStroke();
p.fill(pencilColor);

Expand All @@ -227,19 +214,14 @@ public void bezier(float x1, float y1, float cx1, float cy1,
p.dist(cx1, cy1, cx2, cy2) +
p.dist(cx2, cy2, x2, y2);

// Scale increment based on approximate curve length
float increment = 0.15f / approxLength;

// Use smaller increments for print mode
if (printMode) {
increment *= 0.5f;
}
// Scale increment based on approximate curve length and print mode
float increment = (printMode ? 0.075f : 0.15f) / approxLength;

for (float t = 0; t <= 1; t += increment) {
if (fade) {
float alpha = calculateFadeAlpha(t, fadeStart, fadeEnd);
p.fill(p.hue(pencilColor), p.saturation(pencilColor),
p.brightness(pencilColor),
p.alpha(pencilColor) * t);
p.brightness(pencilColor), alpha);
}

float x = p.bezierPoint(x1, cx1, cx2, x2, t);
Expand All @@ -248,6 +230,33 @@ public void bezier(float x1, float y1, float cx1, float cy1,
}
}

/**
* Draws a cubic Bézier curve with a pencil-like effect.
*
* @param x1 x-coordinate of the start point
* @param y1 y-coordinate of the start point
* @param cx1 x-coordinate of the first control point
* @param cy1 y-coordinate of the first control point
* @param cx2 x-coordinate of the second control point
* @param cy2 y-coordinate of the second control point
* @param x2 x-coordinate of the end point
* @param y2 y-coordinate of the end point
* @param fade if true, applies a fade effect from start to end
*/
public void bezier(float x1, float y1, float cx1, float cy1,
float cx2, float cy2, float x2, float y2, boolean fade) {
plotBezierCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, fade, 0, 1);
}

/**
* Internal method to draw a bezier segment with fade range control
*/
private void bezierSegment(float x1, float y1, float cx1, float cy1,
float cx2, float cy2, float x2, float y2,
boolean fade, float fadeStart, float fadeEnd) {
plotBezierCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, fade, fadeStart, fadeEnd);
}

/**
* Draws a smooth spline through a series of points using connected bézier curves.
* The spline will pass through all given points while maintaining smooth transitions.
Expand Down Expand Up @@ -286,70 +295,19 @@ public void spline(float[] points, boolean fade, boolean fadeFirstSegmentOnly) {
float fadeStart = 1;
float fadeEnd = 1;

if (fade) {
if (fadeFirstSegmentOnly) {
// Only fade if this is the first segment
if (currentSegment == 0) {
fadeStart = 0;
fadeEnd = 1;
}
} else {
// Fade the entire spline
if (fade && fadeFirstSegmentOnly && currentSegment == 0) {
// Use the simple bezier function for the first segment
bezier(x1, y1, cx1, cy1, cx2, cy2, x2, y2, true);
} else {
if (fade) {
// Fade the entire spline or subsequent segments
fadeStart = currentSegment / numSegments;
fadeEnd = (currentSegment + 1) / numSegments;
}
// Draw the bezier curve segment with the appropriate fade range
bezierSegment(x1, y1, cx1, cy1, cx2, cy2, x2, y2, fade, fadeStart, fadeEnd);
}

// Draw the bezier curve segment with the appropriate fade range
bezierSegment(x1, y1, cx1, cy1, cx2, cy2, x2, y2, fade, fadeStart, fadeEnd);
currentSegment++;
}
}

/**
* Draws a smooth spline through a series of points using connected bézier curves.
* This overload applies the fade effect to the entire spline when fade is true.
*
* @param points Array of x,y coordinates in the format [x1,y1,x2,y2,...]. Must have at least 4 elements (2 points).
* @param fade if true, applies a fade effect along the entire spline
*/
public void spline(float[] points, boolean fade) {
spline(points, fade, false);
}

/**
* Internal method to draw a bezier segment with fade range control
*/
private void bezierSegment(float x1, float y1, float cx1, float cy1,
float cx2, float cy2, float x2, float y2,
boolean fade, float fadeStart, float fadeEnd) {
p.noStroke();
p.fill(pencilColor);

// Approximate curve length by using the polygon length of control points
float approxLength = p.dist(x1, y1, cx1, cy1) +
p.dist(cx1, cy1, cx2, cy2) +
p.dist(cx2, cy2, x2, y2);

// Scale increment based on approximate curve length
float increment = 0.15f / approxLength;

// Use smaller increments for print mode
if (printMode) {
increment *= 0.5f;
}

for (float t = 0; t <= 1; t += increment) {
if (fade) {
float fadeProgress = fadeStart + (fadeEnd - fadeStart) * t;
p.fill(p.hue(pencilColor), p.saturation(pencilColor),
p.brightness(pencilColor),
p.alpha(pencilColor) * fadeProgress);
}

float x = p.bezierPoint(x1, cx1, cx2, x2, t);
float y = p.bezierPoint(y1, cy1, cy2, y2, t);
dot(x, y);
}
}
}