如何利用C语言输出3D立体感心形图详解

目录
  • ★头文件部分:
  • ★主函数外自定义函数部分:
  • ★主函数部分:
  • 总结

首先我先在每行(除空白以及{}外)代码上标上序号(无序号源码放在了文末)

#include <stdio.h>
#include <math.h>

float f(float x, float y, float z)
{
    float a = x*x + 9.0f/4.0f*y*y + z*z - 1;
    return a*a*a - x*x*z*z*z - 9.0f/80.0f*y*y*z*z*z;
}

float h(float x, float z)
{
    for (float y = 1.0f; y >= 0.0f; y -= 0.001f)
    {
        if (f(x, y, z) <= 0.0f)
            return y;
    }
    return 0.0f;
}

int main()
{
    for (float z = 1.5f; z > -1.5f; z -= 0.1f)
    {
        for (float x = -1.5f; x < 1.5f; x += 0.05f)
        {
            float v = f(x, 0.0f, z);
            if (v <= 0.0f)
            {
                float y0 = h(x, z);
                float ny = 0.01f;
                float nx = h(x + ny, z) - y0;
                float nz = h(x, z + ny) - y0;
                float nd = 1.0f / sqrtf(nx*nx + ny*ny + nz*nz);
                float d = (nx + ny - nz)*nd*0.5f + 0.5f;
                putchar(".:-=+*#%@"[(int)(d * 5.0f)]);
            }
            else
                putchar(' ');
        }
        putchar('\n');
    }
    return 0;
}

此次空白行以及语句块{}空白花括号就不再多加赘述,简要来说,就是为了整体的完整性与可读性。

首先先说一下数值后面加f的问题,例如: y=1.0f 1.0后面的f用于强调前面的1.0是一个float量。 如果不加,默认为double,加了之后,赋值给y时会自动转换为float 的。

逐行分析(除空白以及{}空白行外):

★头文件部分:

1.头文件的定义,可以说是老朋友了,stdio头文件,非常常用的头文件。

2.math头文件,看到math,我们应该会想起数学这个名字,其实没错,math.h头文件定义了各种数学函数和一个宏。此处定义这个头文件的原因就是用到了数学函数sqrtf。

★主函数外自定义函数部分:

3.定义了一个float类型的函数f,有三个float类型的形参x,y,z。

4.定义了一个float类型的变量a,将其赋值为x * x + 9.0f / 4.0f* y * y + z * z - 1;

5.返回一个表达式的值:return a *a * a - x * x * z * z * z - 9.0f/80.0f * y * y * z * z * z;

有关4和5的解释:这其实跟上一次平面心形图方程类型,只不过增加到了第三维度,此处为立体感心形方程:

x * x + 9.0f / 4.0f* y * y + z * z - 1;

return a *a * a - x * x * z * z * z - 9.0f/80.0f * y * y * z * z * z;

6.定义了一个float类型的函数h,有两个float类型的形参x,z。

7.float定义y=1.0f,1.0后面的f用于强调前面的1.0是一个float量。 如果不加,默认为double,加了之后,赋值给y时会自动转换为float 的。

y>=0.0f 判断条件;

z-=0.1f; 也就是z=z-0.1f; 可以类比i-=2; 即 i=i-2;

8.if (f(x, y, z) <= 0.0f)条件判断,调用函数f传参x,y,z看函数返回值是否小于等于0,如果小于,说明y的值就对了,返回y的值到主函数。

9.见8.

10.return返回0.0f表示结束了该函数的执行。

★主函数部分:

11.主函数的定义。

12.见7.分析

​ ps:12和13不再多加阐述,和7道理相同。

13.见7.分析

14.float定义了一个v变量,接收了y=0.0f即y为定值时函数f的返回值。

15.条件判断,看函数返回的v值是否小于等于0,如果小于等于0,则执行语句块内容,输出所设定字符。

16.由15可知,15成立则进入语句16的执行,此处定义变量y0来接收返回值。

17.定义浮点型变量ny,并给它赋值为0.01f。

18.float nx = h(x + ny, z) - y0; 经h函数返回之后相当于,nx=y(x变化)-y0;

19.float nz = h(x, z + ny) - y0; 经h函数返回之后相当于,nz=y(z变化)-y0;

20.float nd = 1.0f / sqrtf(nx * nx + ny * ny + nz * nz); 这里的nd的值就相当于(x * x+y * y+z * z)开方再取倒数。

21.float d = (nx + ny - nz) * nd * 0.5f + 0.5f; d值相当于 d=(x+y-z)*1.0f/sqrtf(x * x+y * y+z * z)+0.5f。

22.putchar(".:-=+*#%@"[(int)(d * 5.0f)]); 输出所设定字符,更好地呈现出立体感心形。

关于17——22这些都是为了更好的呈现立体感图形所写,关联到输出的位置,输出的形状等多个方面,可以说,是立体感心形代码中核心代码之一(而且是很关键的)。

23.if else中else否则部分;

24.如果执行else语句,则输出空白;

25.输出换行;

26.return 0; return语句结束main()函数的执行,把0返还给操作系统。

无序号源码:

#include <stdio.h>
#include <math.h>

float f(float x, float y, float z)
{
    float a = x*x + 9.0f/4.0f*y*y + z*z - 1;
    return a*a*a - x*x*z*z*z - 9.0f/80.0f*y*y*z*z*z;
}

float h(float x, float z)
{
    for (float y = 1.0f; y >= 0.0f; y -= 0.001f)
    {
        if (f(x, y, z) <= 0.0f)
            return y;
    }
    return 0.0f;
}

int main()
{
    for (float z = 1.5f; z > -1.5f; z -= 0.1f)
    {
        for (float x = -1.5f; x < 1.5f; x += 0.05f)
        {
            float v = f(x, 0.0f, z);
            if (v <= 0.0f)
            {
                float y0 = h(x, z);
                float ny = 0.01f;
                float nx = h(x + ny, z) - y0;
                float nz = h(x, z + ny) - y0;
                float nd = 1.0f / sqrtf(nx*nx + ny*ny + nz*nz);
                float d = (nx + ny - nz)*nd*0.5f + 0.5f;
                putchar(".:-=+*#%@"[(int)(d * 5.0f)]);
            }
            else
                putchar(' ');
        }
        putchar('\n');
    }
}

希望这篇文章对你有所帮助!

总结

到此这篇关于如何利用C语言输出3D立体感心形图的文章就介绍到这了,更多相关C语言输出3D立体感心形图内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 如何利用C语言输出3D立体感心形图详解

    目录 ★头文件部分: ★主函数外自定义函数部分: ★主函数部分: 总结 首先我先在每行(除空白以及{}外)代码上标上序号(无序号源码放在了文末) #include <stdio.h> #include <math.h> float f(float x, float y, float z) { float a = x*x + 9.0f/4.0f*y*y + z*z - 1; return a*a*a - x*x*z*z*z - 9.0f/80.0f*y*y*z*z*z; } floa

  • 如何利用C语言实现最简单的HTTP服务器详解

    此段代码的特点 <h1>Hello!</h1> 如何编译运行? 编译: gcc -o hello_server hello_server.c 运行: ./hello_server 请求: curl http://localhost:8888/any 源文件 hello_server.c #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/so

  • 利用Python如何制作好玩的GIF动图详解

    前言 之前我们分享过用Python进行可视化的9种常见方式.其实我们还能让可视化图形逼格更高一些,今天就分享一下如何让可视化秀起来:用Python和matplotlib制作GIF图表. 假如电脑上没有安装ImageMagick,先去这里按照自己的电脑系统下载对应版本,大家也可以通过我们下载:https://www.jb51.net/softs/140766.html,如果我们想用matplotlib的save方法渲染GIF动图,就需要安装ImageMagick. 下图是我们制作的一个动图示例:

  • 利用php输出不同的心形图案

    首先为大家分享php输出心形曲线的代码,代码如下 <?php for($t=0;$t<360;$t++) { $y=2*cos($t)-cos(2*$t); //笛卡尔心形曲线函数 $x=2*sin($t)-sin(2*$t); $x+=3; $y+=3; $x*=70; $y*=70; $x=round($x); $y=round($y); $str[]=$x; $y=$y+2*(180-$y);//图像上下翻转 $x=$y; $str[]=$x; } $im=imagecreate(400

  • R语言利用ggplot2绘制QQ图和箱线图详解

    目录 绘制qq图 函数介绍 例子 绘制boxplot 函数介绍 例子 利用分位点绘制箱线图 将QQ图和箱线图进行融合 函数介绍 参数介绍 注意事项 例子 绘制qq图 在ggplot2中绘制qq图需要两步,geom_qq()将绘制样本分位点,geom_qq_line()将绘制标准正态线 函数介绍 geom_qq() geom_qq( mapping = NULL, data = NULL, geom = "point", position = "identity",

  • C语言文件操作中 fgets与fputs 函数详解

    C语言文件操作中 fgets.fputs 函数详解 先给出api fgets 语法: #include <stdio.h> char *fgets( char *str, int num, FILE *stream ); 函数fgets()从给出的文件流中读取[num - 1]个字符并且把它们转储到str(字符串)中. fgets()在到达行末时停止,在这种情况下,str(字符串)将会被一个新行符结束. 如果fgets()达到[num - 1]个字符或者遇到EOF, str(字符串)将会以nu

  • go语言context包功能及操作使用详解

    目录 Context包到底是干嘛用的? context原理 什么时候应该使用 Context? 如何创建 Context? 主协程通知有子协程,子协程又有多个子协程 context核心接口 emptyCtx结构体 Backgroud TODO valueCtx结构体 WithValue向context添加值 Value向context取值 示例 WithCancel可取消的context cancelCtx结构体 WithDeadline-超时取消context WithTimeout-超时取消

  • Go语言函数的延迟调用(Deferred Code)详解

    目录 基本功能 示例一:延迟调用执行顺序 示例二:多defer使用方法 实例三:defer与局部变量.返回值的关系 先解释一下这篇Blog延期的原因,本来已经准备好了全部内容,但是当我重新回顾实例三的时候,发现自己还是存在认知不足的地方,于是为了准确表述,查阅了大量的资料,重新编写了第三部分,导致延期.感谢持续关注本笔记更新的朋友,后期我将逐步通过3-5分钟视频方式为大家对笔记内容进行讲解,帮助更多的朋友能够快速掌握Go语言的基础. 本节将介绍Go语言函数和方法中的延迟调用,正如名称一样,这部分

  • Go语言中函数可变参数(Variadic Parameter)详解

    目录 基本语法 示例一:函数中获取可变参数 示例二:将切片传给可变参数 示例三:多参数 基本语法 在Python中,在函数参数不确定数量的情况下,可以使用如下方式动态在函数内获取参数,args实质上是一个list,而kwargs是一个dict def myFun(*args, **kwargs): 在Go语言中,也有类似的实现方式,只不过Go中只能实现类似*args的数组方式,而无法实现**kwargs的方式.实现这种方式,其实也是利用数组的三个点表达方式,我们这里来回忆一下. 关于三个点(…)

  • Go语言学习之context包的用法详解

    目录 前言 需求一 需求二 Context 接口 emptyCtx valueCtx 类型定义 WithValue cancelCtx 类型定义 cancelCtx WithCancel timerCtx 类型定义 WithDeadline WithTimeout 总结 前言 日常 Go 开发中,Context 包是用的最多的一个了,几乎所有函数的第一个参数都是 ctx,那么我们为什么要传递 Context 呢,Context 又有哪些用法,底层实现是如何呢?相信你也一定会有探索的欲望,那么就跟

随机推荐