我正在尝试了解由cambridgesoft开发的行业领先的化学工具ChemDraw如何构造Bezier曲线,以便可以将其他程序/例程(例如自制的Delphi/C#实用程序)中的Bezier曲线点手动转换为ChemDraw可识别的曲线数据。在开始之前,我必须承认我在询问某些黑盒在内部如何工作,因此希望对任何麻烦表示歉意,并感谢任何帮助!
我在ChemDraw中制作了四种最简单的贝塞尔曲线,并将它们保存为.CDXML文件,该文件的曲线部分已粘贴到最后。 .CDXML文件和相应的图片都可以从fileserve下载。 Download Bezier_curve_ChemDraw_sample here。 ChemDraw trial edition can be downloaded here。
问题
问题1.以“直线”类型的曲线点为例,在制作此曲线时,总共使用了两个点。为什么ChemDraw为此存储6个积分? ChemDraw如何准确地解释这些观点?其他三种类型也存在相同的问题,它们最多使用四个显式点。
问题2.如果在ChemDraw中显示“使用三点的贝塞尔曲线-第一类”的内容,则可以看到第一个点不能为(12.22,104.25)。我的意思是,它的X坐标明显大于12。为什么会发生这种情况? ChemDraw是否对数据进行一些转换?对于“使用四个点的贝塞尔曲线”,存在相同的问题。
问题3。CurvePoints属性末尾的多余空白字符似乎有所不同。到底有什么区别?
有人能启发我这些问题吗?
ChemDraw .CDXML文件中的曲线部分
============行==============
<curve
id="2"
Z="1"
ArrowheadType="Solid"
CurvePoints="143.47 116.25 143.47 116.25 143.47 116.25 300.22 117.75 300.22 117.75 300.22 117.75"
/>
=============使用三个点的贝塞尔曲线-第一种类型===============
<curve
id="2"
Z="1"
ArrowheadType="Solid"
CurvePoints="12.22 104.25 121.72 106.5 231.22 108.75 230.47 204 230.47 204 230.47 204"
/>
=======================================================================================
<curve
id="2"
Z="1"
ArrowheadType="Solid"
CurvePoints="134.47 97.5 134.47 97.5 134.47 97.5 231.22 60.75 229.72 109.5 228.22 158.25"
/>
============使用四个点的贝塞尔曲线===============
<curve
id="2"
Z="1"
ArrowheadType="Solid"
CurvePoints="5.47 93.75 123.22 93.75 240.97 93.75 351.22 177.75 236.47 177.75 121.72 177.75"
/>
示例C#程序生成相同的曲线
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WinForms_2_DrawBezier
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Text = "Draw Bezier Curve";
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
// DrawBezier_1(this, e);
// DrawBezier_2(this, e);
// DrawBezier_3(this, e);
DrawBezier_4(this, e);
}
private void DrawBezier_1(object sender, PaintEventArgs e)
{
Pen l_pen = new Pen(Color.Black);
PointF l_pt1 = new PointF(143.47f, 116.25f);
PointF l_pt2 = new PointF(l_pt1.X, l_pt1.Y);
PointF l_pt3 = new PointF(l_pt1.X, l_pt1.Y);
PointF l_pt4 = new PointF(300.22f, 117.75f);
PointF l_pt5 = new PointF(l_pt4.X, l_pt4.Y);
PointF l_pt6 = new PointF(l_pt4.X, l_pt4.Y);
PointF[] l_pts = new PointF[6];
l_pts[0] = l_pt1;
l_pts[1] = l_pt2;
l_pts[2] = l_pt3;
l_pts[3] = l_pt4;
l_pts[4] = l_pt5;
l_pts[5] = l_pt6;
// e.Graphics.DrawBezier(l_pen, l_pt1, l_pt2, l_pt5, l_pt6);
e.Graphics.DrawBezier(l_pen, l_pt1, l_pt3, l_pt4, l_pt6); // As suggested by Dani
// e.Graphics.DrawBeziers(l_pen, l_pts);
}
private void DrawBezier_2(object sender, PaintEventArgs e)
{
Pen l_pen = new Pen(Color.Black);
PointF l_pt1 = new PointF(12.22f, 104.25f);
PointF l_pt2 = new PointF(121.72f, 106.5f);
PointF l_pt3 = new PointF(231.22f, 108.75f);
PointF l_pt4 = new PointF(230.47f, 204f);
PointF l_pt5 = new PointF(l_pt4.X, l_pt4.Y);
PointF l_pt6 = new PointF(l_pt4.X, l_pt4.Y);
PointF[] l_pts = new PointF[6];
l_pts[0] = l_pt1;
l_pts[1] = l_pt2;
l_pts[2] = l_pt3;
l_pts[3] = l_pt4;
l_pts[4] = l_pt5;
l_pts[5] = l_pt6;
// e.Graphics.DrawBezier(l_pen, l_pt1, l_pt2, l_pt3, l_pt4);
e.Graphics.DrawBezier(l_pen, l_pt1, l_pt3, l_pt4, l_pt6); // As suggested by Dani
// e.Graphics.DrawBeziers(l_pen, l_pts);
}
private void DrawBezier_3(object sender, PaintEventArgs e)
{
Pen l_pen = new Pen(Color.Black);
PointF l_pt1 = new PointF(134.47f, 97.5f);
PointF l_pt2 = new PointF(l_pt1.X, l_pt1.Y);
PointF l_pt3 = new PointF(l_pt1.X, l_pt1.Y);
PointF l_pt4 = new PointF(231.22f, 60.75f);
PointF l_pt5 = new PointF(229.72f, 109.5f);
PointF l_pt6 = new PointF(228.22f, 158.25f);
PointF[] l_pts = new PointF[6];
l_pts[0] = l_pt1;
l_pts[1] = l_pt2;
l_pts[2] = l_pt3;
l_pts[3] = l_pt4;
l_pts[4] = l_pt5;
l_pts[5] = l_pt6;
// e.Graphics.DrawBezier(l_pen, l_pt3, l_pt4, l_pt5, l_pt6);
e.Graphics.DrawBezier(l_pen, l_pt1, l_pt3, l_pt4, l_pt6); // As suggested by Dani
// e.Graphics.DrawBeziers(l_pen, l_pts);
}
private void DrawBezier_4(object sender, PaintEventArgs e)
{
Pen l_pen = new Pen(Color.Black);
PointF l_pt1 = new PointF(5.47f, 93.75f);
PointF l_pt2 = new PointF(123.22f, 93.75f);
PointF l_pt3 = new PointF(240.97f, 93.75f);
PointF l_pt4 = new PointF(351.22f, 177.75f);
PointF l_pt5 = new PointF(236.47f, 177.75f);
PointF l_pt6 = new PointF(121.72f, 177.75f);
PointF[] l_pts = new PointF[6];
l_pts[0] = l_pt1;
l_pts[1] = l_pt2;
l_pts[2] = l_pt3;
l_pts[3] = l_pt4;
l_pts[4] = l_pt5;
l_pts[5] = l_pt6;
// e.Graphics.DrawBezier(l_pen, l_pt1, l_pt4, l_pt5, l_pt6);
e.Graphics.DrawBezier(l_pen, l_pt1, l_pt3, l_pt4, l_pt6); // As suggested by Dani
// e.Graphics.DrawBeziers(l_pen, l_pts);
}
}
}
但是,除了第一个
Line
类型之外,我无法使此C#实用程序生成与ChemDraw显示相同的曲线。 最佳答案
它使用标准的贝塞尔曲线算法,该算法可以采用任意数量的点来构建曲线。看Bézier curve
编辑:
C#DrawBezier仅支持二次(四个点)贝塞尔曲线。您的四点贝塞尔曲线将使用以下命令转换为C#:
float[] CurvePoints = GetCurvePoints();
DrawBezier(Pen, CurvePoints[0], CurvePoints[1], CurvePoints[4], CurvePoints[5],
CurvePoints[6], CurvePoints[7], CurvePoints[10], CurvePoints[11]);
GetCurvePoints()
仅提供CurvePoints
xml属性的点列表。编辑2:
生成最后一条曲线所有曲线的代码:
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Linq;
using System.Collections.Generic;
public class Bezier : Form
{
static public void Main ()
{
Application.Run (new Bezier ());
}
protected override void OnPaint (PaintEventArgs e)
{
// The input with all points
string CurveDataString = "5.47 93.75 123.22 93.75 240.97 93.75 351.22 177.75 236.47 177.75 121.72 177.75";
string[] CurveDataStringParts = CurveDataString.Split(' ');
int[] Keep = {2, 3, 4, 5, 6, 7, 8, 9};
float[] CurveData = (from i in Keep select float.Parse(CurveDataStringParts[i])).ToArray();
e.Graphics.DrawBezier(Pens.Black, CurveData[0], CurveData[1], CurveData[2], CurveData[3],
CurveData[4], CurveData[5], CurveData[6], CurveData[7]);
for(int i = 0; i < CurveData.Length; i += 2)
{
e.Graphics.FillEllipse(Brushes.Black, new RectangleF(CurveData[i] - 2, CurveData[i + 1] - 2, 4, 4));
}
base.OnPaint (e);
}
}
结果:
关于c# - 帮助分析软件/程序如何构建贝塞尔曲线,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7140789/