Cam*_*n S 8 javascript python algorithm 3d matlab
首先请注意:在我没有其他信誉点之前,他们不会让我嵌入图像(对不起),但是所有链接都是在imgur上发布的图像!:) 谢谢
我已经复制了一种使用傅立叶变换为任何单个路径(1条闭合路径)设置动画的方法。这样就创建了一个史诗般的动画(旋转的圆圈),它们彼此围绕旋转,并跟随插补点,以连续的循环/功能追踪路径。
我想将此系统用于3D。我可以想到的两种方法是使用球坐标系(两个复平面)或3个Epicycles->每个轴(x,y,z)一个,并带有各自的参数方程式。这可能是最好的开始方式!
2个周期,一个用于X,一个用于Y: 
图片:一个周期->复数->对于X和Y 
傅立叶变换背景!!!:
•Eulers公式使我们能够将复杂平面中的每个点分解为一个角度(指数函数的自变量)和一个振幅(Cn系数)
•从这个意义上讲,与上面的无穷级数中的每个项的成像有关,代表半径为cn的圆上的点,偏移2?nt / T弧度
•下图显示了如何将相位/振幅方面的复数之和可视化为复平面中的一组串联曲线。每条红线是一个矢量,表示和序列中的一项:cne2?i(nT)t
•添加和数对应于简单地将复杂空间中的每个这些红色矢量串联起来:
动画旋转圆: 
圆到动画图纸:
•如果在2D(xy)空间中有线条图,则可以将该路径数学上描述为参数函数。(两个单独的单变量函数,均以辅助变量(在这种情况下为T表示):

•例如,以下是一匹马的简单线条图,以及穿过图像中黑色像素的参数路径,然后将该路径分为其X和Y分量:

•此时,我们需要计算这两个路径的傅立叶近似,并使用该近似的系数来确定最终可视化所需的圆的相位和振幅。
Python代码:用于此示例的python代码可在guithub上找到。
我已经成功地以2D动画化了此过程,但我想将其应用于3D。
以下代码表示2D动画->我已经在使用的东西:
[使用JavaScript和P5.js库]
傅里叶算法(fourier.js):
// a + bi
class Complex {
constructor(a, b) {
this.re = a;
this.im = b;
}
add(c) {
this.re += c.re;
this.im += c.im;
}
mult(c) {
const re = this.re * c.re - this.im * c.im;
const im = this.re * c.im + this.im * c.re;
return new Complex(re, im);
}
}
function dft(x) {
const X = [];
const Values = [];
const N = x.length;
for (let k = 0; k < N; k++) {
let sum = new Complex(0, 0);
for (let n = 0; n < N; n++) {
const phi = (TWO_PI * k * n) / N;
const c = new Complex(cos(phi), -sin(phi));
sum.add(x[n].mult(c));
}
sum.re = sum.re / N;
sum.im = sum.im / N;
let freq = k;
let amp = sqrt(sum.re * sum.re + sum.im * sum.im);
let phase = atan2(sum.im, sum.re);
X[k] = { re: sum.re, im: sum.im, freq, amp, phase };
Values[k] = {phase};
console.log(Values[k]);
}
return X;
}
Run Code Online (Sandbox Code Playgroud)
素描功能/动画(Sketch.js):
let x = [];
let fourierX;
let time = 0;
let path = [];
function setup() {
createCanvas(800, 600);
const skip = 1;
for (let i = 0; i < drawing.length; i += skip) {
const c = new Complex(drawing[i].x, drawing[i].y);
x.push(c);
}
fourierX = dft(x);
fourierX.sort((a, b) => b.amp - a.amp);
}
function epicycles(x, y, rotation, fourier) {
for (let i = 0; i < fourier.length; i++) {
let prevx = x;
let prevy = y;
let freq = fourier[i].freq;
let radius = fourier[i].amp;
let phase = fourier[i].phase;
x += radius * cos(freq * time + phase + rotation);
y += radius * sin(freq * time + phase + rotation);
stroke(255, 100);
noFill();
ellipse(prevx, prevy, radius * 2);
stroke(255);
line(prevx, prevy, x, y);
}
return createVector(x, y);
}
function draw() {
background(0);
let v = epicycles(width / 2, height / 2, 0, fourierX);
path.unshift(v);
beginShape();
noFill();
for (let i = 0; i < path.length; i++) {
vertex(path[i].x, path[i].y);
}
endShape();
const dt = TWO_PI / fourierX.length;
time += dt;
Run Code Online (Sandbox Code Playgroud)
最重要的是!路径/坐标:( 这个是三角形)
let drawing = [
{ y: -8.001009734 , x: -50 },
{ y: -7.680969345 , x: -49 },
{ y: -7.360928956 , x: -48 },
{ y: -7.040888566 , x: -47 },
{ y: -6.720848177 , x: -46 },
{ y: -6.400807788 , x: -45 },
{ y: -6.080767398 , x: -44 },
{ y: -5.760727009 , x: -43 },
{ y: -5.440686619 , x: -42 },
{ y: -5.12064623 , x: -41 },
{ y: -4.800605841 , x: -40 },
...
...
{ y: -8.001009734 , x: -47 },
{ y: -8.001009734 , x: -48 },
{ y: -8.001009734 , x: -49 },
];
Run Code Online (Sandbox Code Playgroud)
这个答案是为了回应:“你认为 [third.js] 可以通过旋转圆圈和其他东西来复制我在 2D 和 3D 中拥有的东西吗?”
我不确定您是否想从头开始学习 3D 建模(即创建您自己的矢量例程库、齐次坐标变换、渲染透视等),或者您是否只是想生产最终产品。对于后者,two.js 是一个基于 webGL 构建的强大图形库,在我看来,它对于初学者来说足够简单,但具有很大的深度,可以产生非常复杂的 3D 效果。(仔细阅读https://trijs.org/examples/上的示例,您就会亲眼看到。)
我碰巧正在开发自己的 Three.js 项目,并制作了一个周转圆的快速示例作为热身练习。这涉及从以下参考文献中提取零件和零件......
https://trijs.org/docs/index.html#manual/en/introduction/Creating-a-scene
https://trijs.org/examples/#webgl_geometry_shapes (这个 Three.js 示例是一个很好的资源,展示了渲染形状的各种方式。)
结果是一个简单的场景,一个圆圈绕着另一个圆圈运行,允许鼠标控制围绕场景旋转,从不同的角度和距离查看它。
<html>
<head>
<title>Epicyclic Circles</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script src="https://rawgit.com/mrdoob/three.js/dev/build/three.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/controls/OrbitControls.js"></script>
<script>
// Set up the basic scene, camera, and lights.
var scene = new THREE.Scene();
scene.background = new THREE.Color( 0xf0f0f0 );
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
scene.add(camera)
var light = new THREE.PointLight( 0xffffff, 0.8 );
camera.add( light );
camera.position.z = 50;
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
// Add the orbit controls to permit viewing the scene from different angles via the mouse.
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled
controls.dampingFactor = 0.25;
controls.screenSpacePanning = false;
controls.minDistance = 0;
controls.maxDistance = 500;
// Create center and epicyclic circles, extruding them to give them some depth.
var extrudeSettings = { depth: 2, bevelEnabled: true, bevelSegments: 2, steps: 2, bevelSize: .25, bevelThickness: .25 };
var arcShape1 = new THREE.Shape();
arcShape1.moveTo( 0, 0 );
arcShape1.absarc( 0, 0, 15, 0, Math.PI * 2, false );
var holePath1 = new THREE.Path();
holePath1.moveTo( 0, 10 );
holePath1.absarc( 0, 10, 2, 0, Math.PI * 2, true );
arcShape1.holes.push( holePath1 );
var geometry1 = new THREE.ExtrudeBufferGeometry( arcShape1, extrudeSettings );
var mesh1 = new THREE.Mesh( geometry1, new THREE.MeshPhongMaterial( { color: 0x804000 } ) );
scene.add( mesh1 );
var arcShape2 = new THREE.Shape();
arcShape2.moveTo( 0, 0 );
arcShape2.absarc( 0, 0, 15, 0, Math.PI * 2, false );
var holePath2 = new THREE.Path();
holePath2.moveTo( 0, 10 );
holePath2.absarc( 0, 10, 2, 0, Math.PI * 2, true );
arcShape2.holes.push( holePath2 );
var geometry2 = new THREE.ExtrudeGeometry( arcShape2, extrudeSettings );
var mesh2 = new THREE.Mesh( geometry2, new THREE.MeshPhongMaterial( { color: 0x00ff00 } ) );
scene.add( mesh2 );
// Define variables to hold the current epicyclic radius and current angle.
var mesh2AxisRadius = 30;
var mesh2AxisAngle = 0;
var animate = function () {
requestAnimationFrame( animate );
// During each animation frame, let's rotate the objects on their center axis,
// and also set the position of the epicyclic circle.
mesh1.rotation.z -= 0.02;
mesh2.rotation.z += 0.02;
mesh2AxisAngle += 0.01;
mesh2.position.set ( mesh2AxisRadius * Math.cos(mesh2AxisAngle), mesh2AxisRadius * Math.sin(mesh2AxisAngle), 0 );
renderer.render( scene, camera );
};
animate();
</script>
</body>
</html>Run Code Online (Sandbox Code Playgroud)
请注意,我在函数中使用了基本三角学animate来将周转圆定位在中心圆周围,并捏造了圆的旋转速率(而不是进行精确的数学计算),但可能有一个更好的“三.js”-通过矩阵或内置函数来做到这一点的方法。鉴于您显然拥有强大的数学背景,我认为您在移植到 3D 时使用基本三角学转换多周转圆的 2D 模型不会有任何问题。
希望这有助于您决定如何继续进行 3D 版本的程序。