HARMONYOS应用实例273:分形几何之科赫雪花
·
- 分形几何之科赫雪花
- 功能:迭代绘制科赫雪花,展示有限面积、无限周长的数学悖论。
科赫雪花应用通过迭代绘制科赫雪花,展示有限面积、无限周长的数学悖论。科赫雪花是由瑞典数学家海里格·冯·科赫于1904年提出的一种分形曲线,具有惊人的特性:在有限的空间内可以拥有无限长的周长,这是分形几何中最著名的例子之一。本应用通过可视化方式展示科赫雪花的生成过程,帮助用户理解这一神奇的数学现象。
- 功能:迭代绘制科赫雪花,展示有限面积、无限周长的数学悖论。
// 分形几何之科赫雪花
// 功能:迭代绘制科赫雪花,展示有限面积、无限周长的数学悖论。
// 科赫雪花是由瑞典数学家海里格·冯·科赫于1904年提出的一种分形曲线。
// 它具有惊人的特性:在有限的空间内可以拥有无限长的周长,这是分形几何中最著名的例子之一。
// 本应用通过可视化方式展示科赫雪花的生成过程,帮助用户理解这一神奇的数学现象。
// 点接口
interface KochPoint {
x: number;
y: number;
}
// 线段接口
interface LineSegment {
start: KochPoint;
end: KochPoint;
}
@Entry
@Component
struct KochSnowflake {
@State iteration: number = 3;
@State maxIteration: number = 6;
@State isAnimating: boolean = false;
@State animationProgress: number = 0;
@State showConstruction: boolean = false;
@State canvasWidth: number = 350;
@State canvasHeight: number = 350;
@State snowflakeColor: string = '#2196F3';
@State lineWidth: number = 1.5;
private canvasContext: CanvasRenderingContext2D = new CanvasRenderingContext2D();
private colors: string[] = ['#E91E63', '#2196F3', '#4CAF50', '#FF9800', '#9C27B0', '#00BCD4'];
private calculateKochPoints(start: KochPoint, end: KochPoint, iteration: number): KochPoint[] {
if (iteration === 0) {
return [start, end];
}
const dx = end.x - start.x;
const dy = end.y - start.y;
const p1: KochPoint = {
x: start.x + dx / 3,
y: start.y + dy / 3
};
const p2: KochPoint = {
x: start.x + 2 * dx / 3,
y: start.y + 2 * dy / 3
};
const midX = (start.x + end.x) / 2;
const midY = (start.y + end.y) / 2;
const height = Math.sqrt(3) / 6 * Math.sqrt(dx * dx + dy * dy);
const perpX = -dy / Math.sqrt(dx * dx + dy * dy);
const perpY = dx / Math.sqrt(dx * dx + dy * dy);
const p3: KochPoint = {
x: midX + height * perpX,
y: midY + height * perpY
};
const points1 = this.calculateKochPoints(start, p1, iteration - 1);
const points2 = this.calculateKochPoints(p1, p3, iteration - 1);
const points3 = this.calculateKochPoints(p3, p2, iteration - 1);
const points4 = this.calculateKochPoints(p2, end, iteration - 1);
return [...points1.slice(0, -1), ...points2.slice(0, -1), ...points3.slice(0, -1), ...points4];
}
private generateSnowflakePoints(centerX: number, centerY: number, radius: number, iteration: number): KochPoint[] {
const points: KochPoint[] = [];
for (let i = 0; i < 3; i++) {
const angle1 = (i * 2 * Math.PI) / 3 - Math.PI / 2;
const angle2 = ((i + 1) * 2 * Math.PI) / 3 - Math.PI / 2;
const start: KochPoint = {
x: centerX + radius * Math.cos(angle1),
y: centerY + radius * Math.sin(angle1)
};
const end: KochPoint = {
x: centerX + radius * Math.cos(angle2),
y: centerY + radius * Math.sin(angle2)
};
const segmentPoints = this.calculateKochPoints(start, end, iteration);
points.push(...segmentPoints.slice(0, -1));
}
points.push(points[0]);
return points;
}
private calculatePerimeter(iteration: number, initialLength: number): number {
return initialLength * Math.pow(4 / 3, iteration);
}
private calculateArea(iteration: number, initialLength: number): number {
const initialArea = (Math.sqrt(3) / 4) * initialLength * initialLength;
let area = initialArea;
for (let i = 0; i < iteration; i++) {
area += (initialArea / Math.pow(3, 2 * i + 1)) * Math.pow(4, i);
}
return area;
}
private drawSnowflake(ctx: CanvasRenderingContext2D, iteration: number, progress: number = 1) {
const centerX = this.canvasWidth / 2;
const centerY = this.canvasHeight / 2;
const radius = Math.min(this.canvasWidth, this.canvasHeight) * 0.4;
const points = this.generateSnowflakePoints(centerX, centerY, radius, iteration);
const visiblePoints = Math.floor(points.length * progress);
if (visiblePoints < 2) return;
ctx.strokeStyle = this.snowflakeColor;
ctx.lineWidth = this.lineWidth;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
for (let i = 1; i < visiblePoints; i++) {
ctx.lineTo(points[i].x, points[i].y);
}
ctx.stroke();
if (this.showConstruction && iteration > 0) {
this.drawConstructionLines(ctx, centerX, centerY, radius, iteration);
}
}
private drawConstructionLines(ctx: CanvasRenderingContext2D, centerX: number, centerY: number, radius: number, iteration: number) {
ctx.strokeStyle = '#E0E0E0';
ctx.lineWidth = 0.5;
ctx.setLineDash([3, 3]);
for (let i = 0; i < 3; i++) {
const angle1 = (i * 2 * Math.PI) / 3 - Math.PI / 2;
const angle2 = ((i + 1) * 2 * Math.PI) / 3 - Math.PI / 2;
const start: KochPoint = {
x: centerX + radius * Math.cos(angle1),
y: centerY + radius * Math.sin(angle1)
};
const end: KochPoint = {
x: centerX + radius * Math.cos(angle2),
y: centerY + radius * Math.sin(angle2)
};
ctx.beginPath();
ctx.moveTo(start.x, start.y);
ctx.lineTo(end.x, end.y);
ctx.stroke();
}
ctx.setLineDash([]);
}
private drawCanvas() {
const ctx = this.canvasContext;
const width = this.canvasWidth;
const height = this.canvasHeight;
ctx.clearRect(0, 0, width, height);
ctx.fillStyle = '#FAFAFA';
ctx.fillRect(0, 0, width, height);
this.drawSnowflake(ctx, this.iteration, this.animationProgress);
this.drawGrid(ctx);
}
private drawGrid(ctx: CanvasRenderingContext2D) {
const width = this.canvasWidth;
const height = this.canvasHeight;
ctx.strokeStyle = '#E0E0E0';
ctx.lineWidth = 1;
for (let x = 0; x <= width; x += 50) {
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, height);
ctx.stroke();
}
for (let y = 0; y <= height; y += 50) {
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(width, y);
ctx.stroke();
}
}
private startAnimation() {
if (this.isAnimating) return;
this.isAnimating = true;
this.animationProgress = 0;
const duration = 2000;
const startTime = Date.now();
const animate = () => {
const elapsed = Date.now() - startTime;
this.animationProgress = Math.min(1, elapsed / duration);
this.drawCanvas();
if (this.animationProgress < 1) {
setTimeout(animate, 16);
} else {
this.isAnimating = false;
}
};
animate();
}
private reset() {
this.isAnimating = false;
this.animationProgress = 1;
this.drawCanvas();
}
private updateIteration(value: number) {
this.iteration = value;
this.reset();
}
build() {
Column({ space: 15 }) {
Text('科赫雪花')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.fontColor('#2196F3')
.margin({ top: 10 })
Text('迭代绘制科赫雪花,展示有限面积、无限周长的数学悖论。科赫雪花是由瑞典数学家海里格·冯·科赫于1904年提出的一种分形曲线,具有惊人的特性:在有限的空间内可以拥有无限长的周长。')
.fontSize(14)
.fontColor('#666')
.textAlign(TextAlign.Center)
.padding({ left: 15, right: 15 })
Scroll() {
Column({ space: 15 }) {
Column({ space: 10 }) {
Text('控制面板')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#333')
.width('100%')
Column({ space: 5 }) {
Text(`迭代次数:${this.iteration}`)
.fontSize(14)
.fontColor('#333')
.width('100%')
Slider({
value: this.iteration,
min: 0,
max: this.maxIteration,
step: 1,
style: SliderStyle.OutSet
})
.width('100%')
.blockColor('#2196F3')
.trackColor('#E3F2FD')
.selectedColor('#2196F3')
.showSteps(true)
.onChange((value: number) => {
this.updateIteration(value);
})
}
.width('100%')
.padding(10)
.backgroundColor('#F5F5F5')
.borderRadius(8)
Row({ space: 15 }) {
Toggle({ type: ToggleType.Switch, isOn: this.showConstruction })
.selectedColor('#2196F3')
.onChange((isOn: boolean) => {
this.showConstruction = isOn;
this.drawCanvas();
})
Text('显示构造线')
.fontSize(14)
.fontColor('#333')
}
.width('100%')
.justifyContent(FlexAlign.Start)
}
.width('100%')
.padding(15)
.backgroundColor('#FAFAFA')
.borderRadius(10)
Column({ space: 10 }) {
Text('科赫雪花')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#333')
.width('100%')
Canvas(this.canvasContext)
.width(this.canvasWidth)
.height(this.canvasHeight)
.backgroundColor('#FFFFFF')
.border({ width: 2, color: '#333' })
.borderRadius(4)
.onReady(() => {
this.reset();
})
}
.width('100%')
.padding(15)
.backgroundColor('#FAFAFA')
.borderRadius(10)
Row({ space: 10 }) {
Button(this.isAnimating ? '绘制中...' : '开始绘制')
.width('50%')
.height(50)
.backgroundColor(this.isAnimating ? '#9E9E9E' : '#2196F3')
.fontSize(16)
.enabled(!this.isAnimating)
.onClick(() => {
this.startAnimation();
})
Button('重置')
.width('50%')
.height(50)
.backgroundColor('#FF9800')
.fontSize(16)
.onClick(() => {
this.reset();
})
}
.width('100%')
Column({ space: 10 }) {
Text('数学特性')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#333')
.width('100%')
Column({ space: 5 }) {
Row({ space: 10 }) {
Text('当前迭代:')
.fontSize(14)
.fontColor('#333')
.width(100)
Text(this.iteration.toString())
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#2196F3')
.layoutWeight(1)
}
.width('100%')
Row({ space: 10 }) {
Text('边数:')
.fontSize(14)
.fontColor('#333')
.width(100)
Text((3 * Math.pow(4, this.iteration)).toString())
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#4CAF50')
.layoutWeight(1)
}
.width('100%')
Row({ space: 10 }) {
Text('周长倍数:')
.fontSize(14)
.fontColor('#333')
.width(100)
Text(Math.pow(4 / 3, this.iteration).toFixed(4) + 'x')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#E91E63')
.layoutWeight(1)
}
.width('100%')
Row({ space: 10 }) {
Text('面积倍数:')
.fontSize(14)
.fontColor('#333')
.width(100)
Text((1 + (3 / 5) * (1 - Math.pow(4 / 9, this.iteration))).toFixed(4) + 'x')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#9C27B0')
.layoutWeight(1)
}
.width('100%')
}
.width('100%')
.padding(10)
.backgroundColor('#F5F5F5')
.borderRadius(8)
}
.width('100%')
.padding(15)
.backgroundColor('#FAFAFA')
.borderRadius(10)
Column({ space: 10 }) {
Text('数学悖论')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#333')
.width('100%')
Column({ space: 5 }) {
Text('• 无限周长:当迭代次数趋近于无穷大时,科赫雪花的周长也趋近于无穷大')
.fontSize(14)
.fontColor('#666')
.width('100%')
Text('• 有限面积:尽管周长无限,但科赫雪花的面积始终有限,收敛于初始三角形面积的8/5倍')
.fontSize(14)
.fontColor('#666')
.width('100%')
Text('• 分形维度:科赫雪花的分形维度为log(4)/log(3)≈1.26,介于1维和2维之间')
.fontSize(14)
.fontColor('#666')
.width('100%')
Text('• 自相似性:科赫雪花的任意局部都与整体相似,这是分形的基本特征')
.fontSize(14)
.fontColor('#666')
.width('100%')
}
.width('100%')
.padding(10)
.backgroundColor('#F5F5F5')
.borderRadius(8)
}
.width('100%')
.padding(15)
.backgroundColor('#FAFAFA')
.borderRadius(10)
Column({ space: 5 }) {
Text('历史与应用')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#2196F3')
Text('• 发现者:瑞典数学家海里格·冯·科赫(Helge von Koch)于1904年提出')
.fontSize(12)
.fontColor('#666')
.width('100%')
Text('• 数学意义:科赫雪花是最早被描述的分形曲线之一,是分形几何的经典例子')
.fontSize(12)
.fontColor('#666')
.width('100%')
Text('• 自然界应用:雪花、海岸线、山脉等自然现象都具有类似的分形特征')
.fontSize(12)
.fontColor('#666')
.width('100%')
Text('• 计算机图形:分形几何广泛应用于计算机图形学、图像压缩和艺术设计')
.fontSize(12)
.fontColor('#666')
.width('100%')
}
.width('100%')
.padding(15)
.backgroundColor('#E3F2FD')
.borderRadius(10)
}
.width('100%')
.padding(10)
}
.width('100%')
.height('100%')
}
.width('100%')
.height('100%')
.backgroundColor('#FFFFFF')
}
}
更多推荐


所有评论(0)