今天我们来用C语言画一只小猪佩奇---社会、社会....
在画小猪佩奇之前,我们先使用带符号的距离长 (signed distance field,SDF) 来画一个圆形。

使用这个方法表示形状,但是这次我们使用 ASCⅡ 字符 \/=\ 画出形状的外框,并填充内部,类似这样:

  =====


//.....\\


||.....||

\\....//
   

  =====

SDF 的梯度(gradient)代表 SDF 变化最大的方向,可用这个方向去决定用哪一个字符。

我们通过差分求 SDF 的梯度近似值,然后用 atan2() 求出梯度的角度:

用 C 语言简单实现,在 [-1, 1] x [-1, 1] 画布中画一个半径 0.8 并带有 0.1 宽度外框的圆形: 
#include <math.h>
#include <stdio.h>
#define T double

T f(T x, T y)
{
  return sqrt(x x + y y) - 0.8f;
}

char outline(T x, T y)
{

   T delta = 0.001;
  if (fabs(f(x, y)) < 0.05)
  {
    T dx = f(x + delta, y) - f(x - delta, y);
    T dy = f(x, y + delta) - f(x, y - delta);
    return "|/=\|/=\|"[(int)((atan2(dy, dx) / 6.2831853072 + 0.5) * 8 + 0.5)];
  }
  else if (f(x, y) < 0)
  {
    return '.';
  }
  else
  {
  return ' ';

  }
}

int main()
{
  for (T i = -1; i < 1; i += 0.05, putchar('\n'))
  {
    for (T j = -1; j < 1; j += 0.025)
    {
      putchar(outline(j, i));
    } 

  }
  getchar();
  return 0;
}

然后,我们就可以通过画多个圆形,把它们适当地旋转和缩放,用构造实体几何比它们组合起来,从而就可以画出小猪佩奇了:


#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#define T double

T c(T x, T y, T r)
{
  return sqrt(x x + y y) - r;
}

T u(T x, T y, T t)
{
  return x cos(t) + y sin(t);
}

T v(T x, T y, T t)
{
  return y cos(t) - x sin(t);

}

T fa(T x, T y)

{

   return fmin(c(x, y, 0.5), c(x * 0.47 + 0.15, y + 0.25, 0.3));

}

T no(T x, T y)
{
  return c(x * 1.2 + 0.97, y + 0.25, 0.2);
}

T nh(T x, T y)

{
  

   return fmin(c(x + 0.9, y + 0.25, 0.03), c(x + 0.75, y + 0.25, 0.03));

}

T ea(T x, T y)
{
  return fmin(c(x 1.7 + 0.3, y + 0.7, 0.15), c(u(x, y, 0.25) 1.7, v(x, y, 0.25) + 0.65, 0.15));
}

T ey(T x, T y)
{
  return fmin(c(x + 0.4, y + 0.35, 0.1), c(x + 0.15, y + 0.35, 0.1));
}

T pu(T x, T y)
{
  return fmin(c(x + 0.38, y + 0.33, 0.03), c(x + 0.13, y + 0.33, 0.03));
}

T fr(T x, T y)
{
  return c(x * 1.1 - 0.3, y + 0.1, 0.15);
}

T mo(T x, T y)
{
  return fmax(c(x + 0.15, y - 0.05, 0.2), -c(x + 0.15, y, 0.25));
}

T o(T x, T y, T(f)(T, T), T i)
{
  
T r =f(x, y);

  return fabs(r) < 0.02 ? (atan2(f(x, y + 1e-3) - r, f(x + 1e-3, y) - r) + 0.3) 1.273 + 6.5 : r < 0 ? i : 0;
}

T s(T x, T y, T(*f)(T, T), T i)
{
  return f(x, y) < 0 ? i : 0;
}

T f(T x, T y)
{
  return o(x, y, no, 1) ? fmax(o(x, y, no, 1), s(x, y, nh, 12)) : fmax(o(x, y, fa, 1), fmax(o(x, y, ey, 11), fmax(o(x, y, ea, 1), fmax(o(x, y, mo, 1), fmax(s(x, y, fr, 13), s(x, y, pu, 12))))));
}

int main(int a, char **b)
{
  for (T y = -1, s = a > 1 ? strtod(b[1], 0) : 1; y < 0.6; y += 0.05 / s, putchar('\n'))
  {
    for (T x = -1; x < 0.6; x += 0.025 / s)
    {
      putchar(" .|/=\|/=\| @!"[(int)f(u(x, y, 0.3), v(x, y, 0.3))]);
    }  
  }
  getchar();
  return 0;
}

两倍:

四倍:

参考:

知乎Milo Yip

如何优雅的使用C语言绘制一只小猪佩奇的更多相关文章

  1. R语言绘制相对性关系图

    准备 第一步就是安装R语言环境以及RStudio 图绘制准备 首先安装库文件,敲入指令,回车 install.packages('corrplot') 然后安装excel导入的插件,点击右上角impo ...

  2. 一幅图解决R语言绘制图例的各种问题

    一幅图解决R语言绘制图例的各种问题 用R语言画图的小伙伴们有木有这样的感受,"命令写的很完整,运行没有报错,可图例藏哪去了?""图画的很美,怎么总是图例不协调?" ...

  3. 实例15_C语言绘制万年历

    实例说明:

  4. 运用python绘制小猪佩奇

    用python绘制小猪佩奇 1.打开idle 2.点击File-New Files 3.输入以下代码 1. from turtle import * 2. 3. def nose(x,y):#鼻子 4 ...

  5. FastDFS是纯C语言实现,只支持Linux,适合以中小文件为载体的在线服务,还可以冗余备份和负载均衡

    一.理论基础 FastDFS比较适合以中小文件为载体的在线服务,比如跟NGINX(APACHE)配合搭建图片服务器. 分布式文件系统FastDFS FastDFS是纯C语言实现,只支持Linux.Fr ...

  6. R语言绘制空间热力图

    先上图 R语言的REmap包拥有非常强大的空间热力图以及空间迁移图功能,里面内置了国内外诸多城市坐标数据,使用起来方便快捷. 开始 首先安装相关包 install_packages("dev ...

  7. R语言绘制花瓣图flower plot

    R语言中有很多现成的R包,可以绘制venn图,但是最多支持5组,当组别数大于5时,venn图即使能够画出来,看上去也非常复杂,不够直观: 在实际的数据分析中,组别大于5的情况还是经常遇到的,这是就可以 ...

  8. R语言绘制沈阳地铁线路图

    ##使用leaflet绘制地铁线路图,要求 ##(1)图中绘制地铁线路 library(dplyr) library(leaflet) library(data.table) stations< ...

  9. R语言绘制直方图,

    直方图: 核密度函数: 练习题目1: 绘制出15位同学体重的直方图和核密度估计图,并与正态分布的概率密度函数作对比 代码如下: > w <- c(75.0, 64.0, 47.4, 66. ...

随机推荐

  1. content-box跟border-box的区别

    content-box: padding和border不被包含在定义的width和height之内.对象的实际宽度等于设置的width值和border.padding之和,即 ( Element wi ...

  2. Windows核心编程(第5版)----关闭内核对象

    无论怎样创建内核对象,都要向系统指明将通过调用 CloseHandle 来结束对该对象的操作: BOOL CloseHandle(HANDLE hobj); 该函数首先检查调用进程的句柄表,以确保传递 ...

  3. ArrayList排序Sort()方法(转)

    //使用Sort方法,可以对集合中的元素进行排序.Sort有三种重载方法,声明代码如下所//示. public void Sort(); //使用集合元素的比较方式进行排序 public void S ...

  4. Maven库下载很慢解决办法,利用中央仓库

    以下四个都是可用的: http://mirrors.ibiblio.org/maven2/ http://mvnrepository.com/ http://repository.jboss.org/ ...

  5. onchange,onfocus ,oninput事件

    compositionstart 在输入一段需要确认的文本如拼音to汉字.语音时会触发 compositionend  在拼音选词完成.语音输入完毕时会触发 addEventListener() 方法 ...

  6. yii2.0的gradview点击按钮通过get方式传参

    1.直接看views层里的代码就可以了 , <!--?= GridView::widget([ 'dataProvider' =--> $dataProvider, 'filterMode ...

  7. Hibernate缓存策略

    Hibernate的一级缓存又称为Session缓存,其适用范围是在当前的会话之中,其生命周期和Session相同,随着Session的销毁,一级缓存也会随之销毁.一级缓存是不能取消的,Hiberna ...

  8. System IPC 与Posix IPC(semaphore信号灯)

    POSIX下IPC主要包括三种: posix message queue posix semaphores posix shared memory sysytem v IPC包括: system v ...

  9. 跨域问题时的Filter无效

    我页面用Web Uploader进行图片上传,后台使用一个过滤器解决跨域的options问题,然后我给入口类加上了这个过滤器注解配置,但是无效页面代码: <body> <div id ...

  10. poj1322 Chocolate 【 概率DP 】

    题目链接:poj1322 Chocolate [概率DP ] 题意:袋中有C种颜色巧克力,每次从其中拿出一块放桌上,如果桌上有两块相同颜色巧克力则吃掉,问取出N块巧克力后,求桌上正好剩下M块巧克力的概 ...