写点什么

Processing:创意编程与可视化的强大工具

  • 2025-10-02
    吉林
  • 本文字数:4734 字

    阅读完需:约 16 分钟

Processing:创意编程与可视化的强大工具

最近经常能看到一些很漂亮的绘图,通过软件绘制各种静态或动态的曲线,例如本文封面的蝴蝶(这只是其中比较简单的一种)。除了感叹数学之美,本篇将介绍用什么工具,以及怎样使用,让你快速实现一个自己的函数可视化。

1. Processing 简介

1.1 起源

Processing 由 Casey Reas 与 Ben Fry 于 2001 年在 MIT Media Lab 的 “Design by Numbers” 项目组中创建,旨在让艺术家、设计师和学生能够用简洁的代码快速实现交互式图形、动画和可视化。Processing 的核心理念是把编程当作“电子速写本”,提供统一的 API,让创意项目的原型开发变得像绘画一样直观。

1.2 主要应用领域

  1. 艺术与交互装置:生成动态图形、声音可视化、实时交互装置(如 Arduino、传感器)。

  2. 数据可视化:利用 CSV、JSON、Table 等结构把数据映射为图形,常用于教学、科研和信息设计。

  3. 教学与创意编程:作为入门语言,广泛用于高校艺术与设计课程、创意编程工作坊。

  4. 原型与快速实验:因为 IDE 自带示例、库丰富,适合在几分钟内完成概念验证。

1.3 与同类创意编程工具的对比(优缺点)

与 Processing 功能相同或类似的工具有:openFrameworks、Cinder、p5.js (Web 版)等,以下对这几个工具在学习曲线、运行效率、跨平台部署等方面做个简单比较。


总结

  • Processing 的优势:上手快、IDE 完整、丰富的教学资源和示例,适合艺术创作和数据可视化。

  • 局限:相对 C++ 系列工具性能较低,桌面版依赖 Java 虚拟机,移动端支持不佳。

  • openFrameworks / Cinder:性能强大、适合专业级实时渲染,但学习成本高,社区相对小。

  • p5.js:把 Processing 的语法迁移到浏览器,便于分享和跨平台,但在大规模绘制和高级特效上仍受限。

2. 软件安装指南(macOS M4 芯片)

2.1 系统要求与准备

对于搭载 M4 芯片的 Mac,Processing 提供了完整的 ARM 原生支持,确保最佳性能。

2.2 安装步骤

步骤 1:下载安装包

# 访问Processing官网下载最新版# 网址:https://processing.org/download# 选择macOS ARM 64-bit版本
复制代码

步骤 2:安装与配置

  1. mac 下载的是直接可安装的 dmg 文件,点击安装

  2. 将 Processing 应用拖入"应用程序"文件夹

  3. 首次运行时,系统可能提示未知开发者,需要在"系统设置 > 隐私与安全性"中授权

步骤 3:验证安装

  • 启动 Processing IDE

  • 创建新文件并输入测试代码:

java

void setup() {  size(400, 400);  background(255, 0, 0);  println("Processing在M4 Mac上运行成功!");}
复制代码
  • 点击运行按钮,确认程序正常执行。这段代码是设置红色背景,并且设置窗口大小为 400*400。

3. 基础使用方法

3.1 IDE 界面概览

Processing IDE 包含以下主要区域:

  • 代码编辑器(下图中的代码编辑区域,sketch 251002m 标签下面的代码编辑器)

  • 消息区域

  • 控制台(console 和 error,控制台 和 错误信息)

  • 工具栏(代码编辑器上方的运行、停止按钮,菜单的文件、编辑、速写本等等)

3.2 第一个可视化程序

让我们创建一个简单的动态图形程序:

// 全局变量float circleSize = 50;float speed = 2;
void setup() { // 初始化画布 - 800x600像素 size(800, 600); // 设置平滑抗锯齿 smooth(); // 设置帧率 frameRate(60);}
void draw() { // 半透明背景(创建拖尾效果) fill(0, 25); rect(0, 0, width, height); // 更新圆圈大小 circleSize = 100 + 50 * sin(millis() * 0.005); // 设置填充颜色(RGB) fill(255, 100, 100, 150); // 设置边框颜色 stroke(255, 200); // 设置边框粗细 strokeWeight(3); // 在鼠标位置绘制圆圈 ellipse(mouseX, mouseY, circleSize, circleSize); // 在控制台输出信息 println("帧率: " + frameRate + " | 圆圈大小: " + circleSize);}
// 鼠标点击交互void mousePressed() { // 随机改变背景色 background(random(255), random(255), random(255));}
// 键盘交互void keyPressed() { if (key == ' ') { // 空格键保存截图 saveFrame("screenshot-####.png"); }}
复制代码

在代码编辑器中输入上述代码后,点击上面的运行图标,会弹出一个窗口展示可视化效果:


3.3 Processing 核心函数详解:setup() 与 draw()

Processing 的程序执行基于一个简单而强大的事件驱动模型,其中 setup() 和 draw() 是两个最核心的函数,构成了绝大多数 Processing 程序的基础骨架。

3.3.1 setup() 函数详解

setup() 函数在程序启动时仅执行一次,主要用于初始化设置:

java

void setup() {  // 设置画布尺寸(必须)  size(800, 600);    // 设置背景色  background(255);    // 设置绘制模式  smooth();          // 抗锯齿  noCursor();        // 隐藏光标  frameRate(30);     // 设置帧率    // 加载资源  PImage img = loadImage("texture.jpg");  PFont font = createFont("Arial", 16);    // 初始化变量  circleX = width/2;  circleY = height/2;    println("程序初始化完成!");}
复制代码

执行特点:

  • 在程序生命周期中只运行一次

  • 必须是程序中第一个被调用的函数(在 draw() 之前)

  • 用于所有一次性初始化操作

必须包含的操作:size(400, 400); // 必须设置画布大小


坐标系统:

原点(0,0)在左上角

X 轴向右递增,Y 轴向下递增

3.3.2 draw() 函数详解

draw() 函数在 setup() 执行完毕后持续重复执行,形成程序的主循环:

void draw() {  // 1. 清空画布(可选)  background(0);    // 2. 更新状态  updatePhysics();    // 3. 绘制图形  drawShapes();    // 4. 处理交互  handleInteraction();    // 5. 显示信息  displayStats();}
复制代码

执行流程详解

默认行为:

  • 每秒执行 60 次(可通过 frameRate() 调整)

  • 每次调用都会重新绘制整个画面

  • 自动维护双缓冲,避免闪烁


常用绘图函数:

point(x, y): 绘制点

line(x1, y1, x2, y2): 绘制线

rect(x, y, width, height): 绘制矩形

ellipse(x, y, width, height): 绘制椭圆

3.4 官方示例

与其他成熟的框架或软件一样,processing 提供了丰富的示例(https://processing.org/examples)。从基础的数组、颜色设置、图片,到复杂一些的函数展示、变形(Transform)、3D 动画等都包含其中。你可以从浅到深,逐个尝试运行这些示例并学习代码。


4 进阶数学可视化示例

4.1 复杂数学曲线可视化

以下是一个结合多种数学函数的艺术可视化示例,实现效果:

代码如下:

/** * 数学艺术:参数曲线场可视化 * 结合了李萨如曲线、正弦波和噪声函数 */
float time = 0;int resolution = 200;float noiseScale = 0.02;
void setup() { size(1000, 800, P2D); colorMode(HSB, 360, 100, 100, 100); background(0); strokeWeight(1.5);}
void draw() { // 创建渐变背景 drawGradientBackground(); // 绘制参数曲线网络 drawParametricNetwork(); // 更新时间 time += 0.02; // 显示信息 displayInfo();}
void drawGradientBackground() { // 禁用描边 noStroke(); // 创建径向渐变 for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // 计算距离中心的距离 float dist = dist(x, y, width/2, height/2); float hue = map(sin(time + dist * 0.01), -1, 1, 200, 300); float brightness = map(dist, 0, width/2, 80, 10); // 设置像素颜色 stroke(hue, 70, brightness, 10); point(x, y); } }}
void drawParametricNetwork() { // 绘制主参数曲线 for (int i = 0; i <= resolution; i++) { float t = map(i, 0, resolution, 0, TWO_PI); // 计算多条曲线的参数 for (int layer = 1; layer <= 3; layer++) { float layerScale = 0.5 + layer * 0.3; // 参数曲线方程 float x1 = width/2 + 150 * layerScale * sin(2 * t + time) * cos(3 * t); float y1 = height/2 + 150 * layerScale * cos(4 * t + time) * sin(2 * t); float x2 = width/2 + 150 * layerScale * sin(3 * t - time) * cos(2 * t); float y2 = height/2 + 150 * layerScale * cos(5 * t - time) * sin(3 * t); // 添加Perlin噪声 float noiseVal = noise(x1 * noiseScale, y1 * noiseScale, time); x1 += 30 * (noiseVal - 0.5); y1 += 30 * (noiseVal - 0.5); // 设置颜色(基于极坐标) float hue = map(t, 0, TWO_PI, 0, 360); float alpha = map(layer, 1, 3, 40, 80); stroke(hue, 80, 90, alpha); // 绘制曲线段 if (i > 0) { float prevT = map(i-1, 0, resolution, 0, TWO_PI); float prevX1 = width/2 + 150 * layerScale * sin(2 * prevT + time) * cos(3 * prevT); float prevY1 = height/2 + 150 * layerScale * cos(4 * prevT + time) * sin(2 * prevT); line(prevX1, prevY1, x1, y1); } // 绘制连接线 stroke(hue, 60, 80, 20); line(x1, y1, x2, y2); } } // 绘制动态粒子 drawParticles();}
void drawParticles() { int particleCount = 50; for (int i = 0; i < particleCount; i++) { float angle = time + i * TWO_PI / particleCount; float radius = 100 + 50 * sin(time * 2 + i * 0.5); // 粒子位置(极坐标转笛卡尔坐标) float x = width/2 + radius * cos(angle); float y = height/2 + radius * sin(angle); // 粒子大小和颜色 float size = 3 + 2 * sin(time * 3 + i); float hue = (angle * 180/PI + time * 50) % 360; // 绘制粒子 noStroke(); fill(hue, 90, 100, 80); ellipse(x, y, size, size); // 粒子轨迹 stroke(hue, 80, 100, 30); strokeWeight(1); if (frameCount > 1) { float prevX = width/2 + radius * cos(angle - 0.1); float prevY = height/2 + radius * sin(angle - 0.1); line(prevX, prevY, x, y); } }}
void displayInfo() { // 显示帧率和时间信息 fill(0, 0, 100, 60); rect(10, 10, 180, 60); fill(0, 0, 100); textSize(12); text("帧率: " + nf(frameRate, 0, 1), 20, 30); text("时间: " + nf(time, 0, 2), 20, 50); text("分辨率: " + resolution + "x" + resolution, 20, 70);}
// 交互功能void mousePressed() { // 鼠标点击时重置背景并添加效果 background(0); time = 0;}
void keyPressed() { if (key == ' ') { // 空格键保存高分辨率截图 saveFrame("math_art_####.png"); } else if (key == 'r' || key == 'R') { // R键重置 background(0); time = 0; } else if (key == CODED) { if (keyCode == UP) { resolution = min(500, resolution + 10); } else if (keyCode == DOWN) { resolution = max(50, resolution - 10); } }}
复制代码

4.3 其他官方学习资源

  1. OpenProcessing 网站:搜索 "mathematical curves" 或 "generative art"

  2. Nature of Code:Daniel Shiffman 的经典教程,包含大量数学可视化

  3. Coding Train YouTube 频道:有很多数学艺术的教学视频

4.4 更多曲线方程

  • 摆线 (Cycloid)

  • 星形线 (Astroid)

  • 双纽线 (Lemniscate)

  • 螺线 (Spirals):阿基米德螺线、对数螺线

  • 混沌系统:洛伦兹吸引子、若斯勒吸引子

这些曲线不仅美丽,还能帮助你理解数学与艺术的深刻联系。你可以通过调整参数、添加颜色渐变和动画效果来创造属于自己的数学艺术作品!


发布于: 刚刚阅读数: 5
用户头像

磨炼中成长,痛苦中前行 2017-10-22 加入

微信公众号【程序员架构进阶】。多年项目实践,架构设计经验。曲折中向前,分享经验和教训

评论

发布
暂无评论
Processing:创意编程与可视化的强大工具_可视化_程序员架构进阶_InfoQ写作社区