65.9K
CodeProject 正在变化。 阅读更多。
Home

通过 ICAS (Inner Centered Arcs) 表示曲线

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.80/5 (13投票s)

2011 年 11 月 13 日

CPOL

7分钟阅读

viewsIcon

31332

downloadIcon

1768

关于另一种曲线表示法的建议

引言

您认为曲线绘制的重要性是什么?

请与您的专长进行比较。

  1. 它通过输入点。
  2. 它需要更少的控制点,更少的限制。
  3. 它具有尽可能高的连续性。(Cn 类)
  4. 它具有灵活的生成点密度。
  5. 它支持精确的圆。

在我提供的示例程序中,以上五个属性是

  1. 它通过输入点。
  2. 它使一个控制点自动对应一对输入点。
  3. 它在连接点的圆弧处具有 C1 连续性。
  4. 它具有灵活的生成点密度。
  5. 它支持精确的圆。

为了快速入门,请从“如何使用它?”开始。我们每天都很忙,随时……

背景

去年,我突然获得了一个短暂而深刻的闪光,并将其发展为“内切圆弧”。我尝试了一年多,并决心将其报告给 Code Project 的各位女士们、先生们。关于新技术,请阅读另一份文档“内切圆弧 (ICAS)”。我可能最终会从只读会员毕业。

ICAS 如何工作?

它将您输入的点连接成一系列圆弧,生成一个控制点,对应您的一对点。假设您有三个点 (P1, P2, P3)。它们创建两个 ICAS,在中间点 (P2) 处具有 C1 连续性。两个 ICAS 数据 △P1C1P2,其中 C1 对应 P1、P2;△P2C2P3,其中 C2 对应 P2、P3。图 1。

Series of arcs

当然,您以后可以编辑控制点。在我的示例程序中,控制点是链接编辑的。它们在中间点 (P2) 处保持 C1 连续性。图 2。

Editing control points

但这并非 ICAS 的自然特性。一个 ICAS 数据由三个点组成:起始点 (P1)、控制点 (C1) 和终点 (P2)。它基本上是三角形信息,因为其内切圆心至关重要。(内切圆心意味着内接圆的圆心。)一个 ICAS 在三角形内部生成两条圆弧,这两条圆弧在其内切圆心处具有 C1 连续性。某个过程生成密铺的三角形及其内切圆心。我们将看到每个内切圆心都位于圆弧上。图 3。抱歉我的重复,请阅读“ICAS”了解详情。我不想在这里扩展话题。这就是“内切圆弧”的起源,也是我第一次向像 Code Project 这样的开放社会解释这个主题。

Basis of ICAS

现在我提到了生成点的灵活密度和精确的圆。在图中,它们具有相同的点 (P1, P2, P3)。图 4。开放曲线仅由两个 ICAS 组成,它们的密铺度(或后缀)不同;另一方面,闭合曲线由三个 ICAS 组成。

如果三角形是正三角形,并且三个控制点处于同质状态,则闭合曲线将是一个圆。(在这种情况下,控制点也构成正三角形。)此外,每个正多边形都可以构成一个外接圆。

Attribution makes difference

当您以 Z 字形输入点时,我的示例程序会在您的两个点 (P2, P3) 之间插值中间点 (M)。图 5。因此,整个 S 形曲线在所有连接点处都是平滑的,没有尖角。请注意,插值并非 ICAS 的特性。这只是一个实现示例。

Interpolation M

如果您想要曲线和直线混合,您需要在直线上绘制中间点 (P4)。图 6。我的示例程序使曲线在两个端点 (P3, P5) 处与三点直线 (P3P4P5) 相切。正如您所考虑的,这不是 ICAS 的特性,而是实现示例。

Mixture line&curve

示例程序实现了什么?

我的概念非常简单

  1. 检查 ICAS 特性
  2. 寻找有效的 ICAS 输入-编辑方法

我一直在我熟悉的开发环境 MFC/View Document 架构中尝试这些概念。我主要将 C 语言函数、三角形密铺、内切圆心和控制点的计算与 GUI 部分分开编写(IcasBase.h, c)。我将它们用在 CIcas 类中(IcasFig.h, cpp)。您可能会期待一些可移植性,尽管我无法保证……

在此,我解释了控制点的计算。它需要四个点:起始点 (S)、终点 (E)、前一个起始点 (SS) 和后一个终点 (EE)。图 7。控制点 (C) 是线C-PreC和线C-PostC上的交点。SS、S 和 E 的位置决定了线的方向C-PreC。类似地,EE、E 和 S 的位置决定了线的方向C-PostC.

。请注意,PreC 和 PostC 的精确位置并非必需。仅一个通过点 (S 或 E) 和线的方向即可完成计算。

如果四个点构成 Z 形,我们需要在中间两个点 (S, E) 之间插入一个插值点 (M)。图 8。S 形曲线同时产生两个控制点 (C1, C2)。

Mixture line&curve

//
//calculate control point
int GetCntl(ICASWORK *SS, ICASWORK *S,
            ICASWORK *E,  ICASWORK *EE,
            ICASPOINT *C1, ICASPOINT *C2, ICASPOINT *M )
{
	double Vx,Vy,Sx,Sy,Ex,Ey,s,t,u;

	int sts = ChkCntl(SS, S, E, EE, C1, M );//set M
	if (0 > sts) return sts;//MULTIPLE check valid

	Work2Vector(SS,S);//A
	Work2Vector(S,E); //B
	Work2Vector(E,EE);//C

	//vector product
	//S-SS(A) vs S-E(B)
	s = S->vx * E->vy  - S->vy * E->vx;
	if (fabs(s) < EPS) {//M = SE middle point
		return -1;//S-SS and S-E are the identical line
	}
	//S-E(B)  vs E-EE(C)
	t = E->vx * EE->vy - E->vy * EE->vx;
	if (fabs(t) < EPS) {//M = SE middle point
		return -2;//S-E and E-EE are the identical line
	}
	//E-EE(C) vs S-SS(A)
	u = S->vx * EE->vy - S->vy * EE->vx;

	Sx = S->ex + E->ex; //A.ex + B.ex;//unit vector
	Sy = S->ey + E->ey; //A.ey + B.ey;
	Ex = E->ex + EE->ex;//B.ex + C.ex;
	Ey = E->ey + EE->ey;//B.ey + C.ey;
	Vx = E->vx;
	Vy = E->vy;

	if (L_PARALLEL == SS->typ) {//point SS on the identical line
		Sx = S->ex; //A.ex;
		Sy = S->ey; //A.ey;
	}
	if (L_PARALLEL == EE->typ) {//point EE on the identical line
		Ex = EE->ex;//C.ex;
		Ey = EE->ey;//C.ey;
	}
	//identical turning direction
	if (s*t > 0)
	{
		if (fabs(u) < EPS && (L_PARALLEL == SS->typ && L_PARALLEL == EE->typ)) {
			double l = E->l * 0.5;
			C1->x = S->x + S->ex * l; //A.ex * l;
			C1->y = S->y + S->ey * l; //A.ey * l;
			C2->x = E->x - EE->ex * l;//C.ex * l;
			C2->y = E->y - EE->ey * l;//C.ey * l;
			//boxy
			M->x = (C1->x + C2->x)*0.5;//C1C2 middle point
			M->y = (C1->y + C2->y)*0.5;
			return 2;
		}
		s  = (Ey*Vx - Ex*Vy)/(Sx*Ey - Ex*Sy);
		C1->x = S->x + (Sx*s);
		C1->y = S->y + (Sy*s);
		return 1;
	}
	//vector SS-S || vector E-EE (|| = parallel)
	else if (fabs(u) < EPS) {
		double l = E->l * 0.5;
		C1->x = S->x + S->ex * l; //Ax * l;
		C1->y = S->y + S->ey * l; //Ay * l;
		C2->x = E->x - EE->ex * l;//Cx * l;
		C2->y = E->y - EE->ey * l;//Cy * l;
		//Z fold//M = SE middle point
		return 2;
	}
	//Z fold
	else {
		double Ax,Ay,Cx,Cy;
		double C12x,C12y,w,v;
		double l = E->l * 0.5;
		w = sqrt(Sx*Sx + Sy*Sy);
		v = sqrt(Ex*Ex + Ey*Ey);
		Ax = Sx / w;
		Ay = Sy / w;
		Cx = Ex / v;
		Cy = Ey / v;
		C1->x = S->x + Ax * l;
		C1->y = S->y + Ay * l;
		C2->x = E->x - Cx * l;
		C2->y = E->y - Cy * l;
		C12x = C2->x - C1->x;
		C12y = C2->y - C1->y;
		u = Vx * C12y - Vy * C12x;

		if (fabs(u) < EPS) {//fail safe//M = SE middle point
		}
		//cross point SE and C1C2
		else {
			s = ((S->y - C1->y)*C12x - C12y*(S->x - C1->x))/u;
			M->x = S->x + (Vx*s);
			M->y = S->y + (Vy*s);
		}
		return 2;
	}
}
...

如何使用?

构建 ICAS.exe

我的开发环境是 Visual Studio 2008 日语版。此外,VS 6.0J 也可以,只是有一些警告。我用英语重写了注释。但主菜单项、下拉菜单仍然是日文。抱歉。

启动 ICAS.exe

在 VIEW 上单击鼠标右键。出现第一个菜单。

“ICAS Input”(ICAS 输入)和“ICAS Attribute”(ICAS 属性)

“ICAS Input”引导您输入点,要完成输入,需要“双击”。“ICAS Attribute”引导您设置常规属性。

First menu

输入曲线点

单击“ICAS Input”。鼠标光标从箭头变为十字准星。当您在点位置单击鼠标左键时,它会用红色折线跟随您的点轨迹。同时,它会用蓝色折线显示控制点。棕色折线是曲线,并且它具有初始属性(单选按钮“0”表示原始折线)。图 9。要完成输入,您需要在最后一个点位置双击。它将以初始属性闭合图形。图 10。

您可以从“ICAS Attribute”中选择您的输入样式,这仅仅是我的测试环境。图 11。

Input curve point

Third degree density

注意 Lattice(网格)表示网格引导。在六边形 FRINGE 区域,它倾向于错过网格,W. Bishop 博士向我报告了这个问题。Walter,抱歉这个 bug。

编辑 ICAS 属性

在您的图形内部单击鼠标左键。它会显示您选择的内容为一个红色多边形。然后在此内部单击鼠标右键。出现第二个菜单。“Icas Information”(Icas 信息)、“Move Icas Data”(移动 Icas 数据)和“Delete Icas Data”(删除 Icas 数据)。

Edit ICAS atribution

单击“Icas Information”以编辑选定的 ICAS 属性。例如,如果您想要一条开放曲线和三度密度顶点,您应该选择如下所示,然后单击“APPLY”(应用)。

Open & Third Density

注意第五度单选按钮表示我们使用相邻两个点的最小距离。右侧的编辑框显示其像素数。左侧的文本框显示曲线的整个逻辑长度(闭合图形)。在这种情况下,中间编辑框中的 4.0 显示了您仅半长度的曲线,带有红色网格,请检查“Param”(参数)和“APPLY”。

如果您觉得有什么不对,请尝试从“ICAS attribute edit”(ICAS 属性编辑)对话框中选择“ReCalculation”(重新计算)。此功能会清理 ICAS 数据,并根据您输入的点重新计算。这使我能够避免混乱,复杂的输入-编辑 GUI 调试。抱歉我偷工减料。

编辑 ICAS 三角形

为了检查 ICAS 的特性,我不得不尝试各种情况。因此,我编写了“ICAS Triangle”(ICAS 三角形)对话框。它对应于每个三角形。它允许您独立控制控制点、直线和曲线的混合、更改切线方向等。在目标三角形内部单击鼠标左键。它会显示您选择的内容为一个蓝色三角形。然后在此内部单击鼠标右键。出现第三个菜单。“Triangle information”(三角形信息)和“Insert Segment Point”(插入段点)。

Edit ICAS triangle

单击“Triangle Information”以编辑选定的 ICAS 三角形。如果您选中“0x10 LEFT_TAN”,它会更改起始切线向量。某些标志在单击“OK”(确定)按钮后不会立即更改。它们需要移动控制点才能改变形状。总之,请尝试一下。并记住“ReCalculation”(重新计算)按钮。

LEFT_TAN checked

结论

我长期以来一直熟悉 Bézier 曲线。有时,我会被一系列 Bézier 曲线、与圆的共存或其复杂应用程序设计弄得心烦意乱。当然,NURBS 超出了我项目的范围。

我们每天都很忙,随时随地。

所以,当我想到 ICAS 的想法时,我简直不敢相信。我仔细研究了它,并确认了其有效性。然后我有一个问题。“我是第一个吗?难道没有其他伟大的人想到这个?”然后我冲到 Google 网站,搜索了关于“inner center”(内切圆心)、“biarc”(双圆弧)、“curve passes through”(曲线通过)等所有内容,但一无所获。接着我变得非常怀疑。“每个人都知道,只有我”我问了我的同事。“这只是个晦涩的琐事,不是吗?”他说,“我不知道!”

坦白说,我认为这是一个 alpha 版本。仍然存在一些小 bug。无论如何,请尝试一下。我认为这将是一种非常有用的技术。如果您给我一些建议,我将非常感激。非常感谢。

历史

  • 2011 年 11 月 12 日:初始版本
© . All rights reserved.