public static class Spline
{
[System.Diagnostics.DebuggerDisplay("({X},{Y})")]
public partial struct Vec2
{
public float X, Y; public Vec2(float x, float y) { this.X = x; this.Y = y; } public static implicit operator PointF(Vec2 v) { return new PointF(v.X, v.Y); } public static implicit operator Vec2(PointF p) { return new Vec2(p.X, p.Y); } public static Vec2 operator +(Vec2 v1, Vec2 v2) { return new Vec2(v1.X + v2.X, v1.Y + v2.Y); } public static Vec2 operator -(Vec2 v1, Vec2 v2) { return new Vec2(v1.X - v2.X, v1.Y - v2.Y); } public static Vec2 operator *(Vec2 v, float f) { return new Vec2(v.X * f, v.Y * f); } public static Vec2 operator /(Vec2 v, float f) { return new Vec2(v.X / f, v.Y / f); } }
    
       /// <summary>
        /// '贝塞尔'内插。结果不包括头尾点
        /// </summary>
     public static PointF[] InterpolateBezier(PointF p0, PointF p1, PointF p2, PointF p3, int samples)
{
PointF[] result = new PointF[samples];
for (int i = ; i < samples; i++)
{
float t = (i + ) / (samples + 1.0f);
result[i] =
(Vec2)p0 * ( - t) * ( - t) * ( - t) +
(Vec2)p1 * ( * ( - t) * ( - t) * t) +
(Vec2)p2 * ( * ( - t) * t * t) +
(Vec2)p3 * (t * t * t);
}
return result;
} public static PointF[] InterpolateCardinalSpline(PointF p0, PointF p1, PointF p2, PointF p3, int samples)
{
const float tension = 0.5f;
Vec2 u = ((Vec2)p2 - (Vec2)p0) * (tension / ) + p1;
Vec2 v = ((Vec2)p1 - (Vec2)p3) * (tension / ) + p2;
return InterpolateBezier(p1, u, v, p2, samples);
}
    

      /// <summary>
      /// '基数样条'内插法。 points为通过点,samplesInSegment为两个样本点之间的内插数量。
      /// </summary>

public static PointF[] CardinalSpline(PointF[] points, int samplesInSegment)
{
List<PointF> result = new List<PointF>();
for (int i = ; i < points.Length - ; i++)
{
result.Add(points[i]);
result.AddRange(InterpolateCardinalSpline(
points[Math.Max(i - , )],
points[i],
points[i + ],
points[Math.Min(i + , points.Length - )],
samplesInSegment
));
}
result.Add(points[points.Length - ]);
return result.ToArray();
}
}

测试方法

public partial class Form1 : Form
{
protected override void OnPaint(PaintEventArgs e)
{
PointF[] ps = {new PointF(,), new PointF(, ), new PointF(, ), new PointF(,)};
// 系统的Graphics.DrawCurve,桃色
e.Graphics.DrawCurve(new Pen(Brushes.PeachPuff, ), ps);
// 自己取样,蓝色
e.Graphics.DrawLines(Pens.Blue, Spline.CardinalSpline(ps, ));
}
}

原文地址:https://blog.csdn.net/zheng558888/article/details/15816009

【转】Graphics.DrawCurve的算法的更多相关文章

  1. 戏说 .NET GDI+系列学习教程(二、Graphics类的方法)

    一.DrawBezier 画立体的贝尔塞曲线 private void frmGraphics_Paint(object sender, PaintEventArgs e) { Graphics g ...

  2. 从零开始学习GDI+ (二) 基本概念与基本操作

    从零开始学习GDI+ (一)我的第一个GDI+程序 上文给新手学习GDI+讲述了vs环境等的准备工作,并且可以直接用GDI+绘图了.本文开始,讲述的可能偏理论,建议学习的过程中大胆尝试,多使用API. ...

  3. [译]处理文本数据(scikit-learn 教程3)

    原文网址:http://scikit-learn.org/stable/tutorial/text_analytics/working_with_text_data.html 翻译:Tacey Won ...

  4. GDI+ 笔记

    1.GDI+模板 #include<windows.h> #include<GdiPlus.h> #include <time.h> #include <ma ...

  5. {Reship}{C#}{GDI+}GDI+画笔,线,区域类型

    =================================================================================== This article is ...

  6. Java实验三报告

    一.  实验内容 (一)敏捷开发与XP 摘要:一项实践在XP环境中成功使用的依据通过XP的法则呈现,包括:快速反馈.假设简单性.递增更改.提倡更改.优质工作.XP软件开发的基石是XP的活动,包括:编码 ...

  7. .Net验证码实现基础--Draw

    命名空间 using System.Draw; using System.Draw.Drawing2D; 在form等控件的 事件中 添加 paint事件 ///////画各种形状(空心)////// ...

  8. C#窗体程序画倾斜一定角度的椭圆

    using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...

  9. GDI+: Curved Shapes

    原文 http://www.functionx.com/vcsharp2003/gdi/curves.htm Curves   Introduction to Curves   A curve is ...

随机推荐

  1. HTTP模块SuperAgent

    superagent它是一个强大并且可读性很好的轻量级ajaxAPI,是一个关于HTTP方面的一个库,而且它可以将链式写法玩的出神入化. var superagent = require('super ...

  2. Bootstrap FileInput中文API整理

    这段时间做项目用到bootstrap fileinput插件上传文件,在用的过程中,网上能查到的api都不是很全,所以想着整理一份比较详细的文档,方便自己今后使用,也希望能给大家带来帮助,如有错误,希 ...

  3. scikit-learn:6. Strategies to scale computationally: bigger data

    參考:http://scikit-learn.org/stable/modules/scaling_strategies.html 对于examples.features(或者两者)数量非常大的情况, ...

  4. EditText: android:focusable和android:focusableInTouchMode的区别

    android:focusable之所以有这个属性主要是因为Android系统不仅仅是针对手机的,有可能在电视.手表等等的非触摸输入设备上(如Android TV),这些设备只有物理上下键不具备触摸功 ...

  5. View:Android View的scrollTo(),scrollBy(),getScrollX(), getScrollY()的理解

    Android系统手机屏幕的左上角为坐标系,同时y轴方向与笛卡尔坐标系的y轴方向想反.提供了 getLeft(), getTop(), getBottom(), getRight() 这些API来获取 ...

  6. PCA,SVD

    PCA的数学原理 https://www.zhihu.com/question/34143886/answer/196294308 奇异值分解的揭秘(二):降维与奇异向量的意义 奇异值分解的揭秘(一) ...

  7. Asp.net Core 项目API接口服务器部署

    Windows server 2008服务器部署: DotNetCore.1.0.0.RC2-WindowsHosting 或者DotNetCore.1.0.5_1.1.2-WindowsHostin ...

  8. python-zip方法

    zip 返回一个将多个可迭代对象组合成一个元组序列的迭代器. 1.  循环多个list的数据: letters = ['a', 'b', 'c'] nums = [1, 2, 3] for lette ...

  9. running boot2docker -> error in run: Failed to get machine “boot2docker-vm”: machine does not exist

    登陆和使用.详细请看.....https://github.com/boot2docker/boot2docker boot2docker start error in run: Failed to ...

  10. Oracle事务与锁

    Oracle事务与锁 2017-12-13 目录 1 数据库事务概括  1.1 事务定义  1.2 事务生命周期  1.3 事物的特性  1.4 死锁2 事务相关语句  2.1 事务相关语句概括  2 ...