模拟汽车运动,怎么把一个转角改成弧度呢?

lappidoth 2016-01-15 03:41:32

我做了一个软件,根据用户在窗口上点击的位置生成路线,然后汽车沿着路线行驶,但现在发现转弯的时候太生硬了,所以想把转折点的地方改为弧线,就像公路转弯一样,可是现在不知道怎么办,连怎么画都不知道,求助。
...全文
306 15 打赏 收藏 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
xuzuning 2016-01-17
  • 打赏
  • 举报
回复
根据这个思路,有
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace 转角弧
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

protected override void OnPaint(PaintEventArgs e)
{
var g = e.Graphics;
var r = 20f; //端点距离
var t = 0.3; //曲率系数
var d = new Point[]
{
new Point(10, 10),
new Point(120, 200),
new Point(150, 100),
new Point(200, 110),
new Point(280, 180),
new Point(100, 230)
};
g.SmoothingMode = SmoothingMode.AntiAlias;//抗锯齿
g.DrawLines(Pens.DimGray, d); //画出折线

using (var p = new GraphicsPath())
{
p.AddLines(new Point[]{d[0], d[0]});

int i;
for (i = 1; i < d.Length-1; i++)
{
var b = new Point[4];
var dx = d[i-1].X - d[i].X;
var dy = d[i-1].Y - d[i].Y;
var k = r / Math.Sqrt(dx * dx + dy * dy);
b[0] = new Point((int)(dx * k + d[i].X), (int)(dy * k + d[i].Y));
b[1] = new Point((int)(dx * k * t + d[i].X), (int)(dy * k * t + d[i].Y));

dx = d[i + 1].X - d[i].X;
dy = d[i + 1].Y - d[i].Y;
k = r / Math.Sqrt(dx * dx + dy * dy);
b[2] = new Point((int)(dx * k * t + d[i].X), (int)(dy * k * t + d[i].Y));
b[3] = new Point((int)(dx * k + d[i].X), (int)(dy * k + d[i].Y));

p.AddBeziers(b);
}
p.AddLines(new Point[] { d[i], d[i] });
g.DrawPath(Pens.Red, p);

p.Flatten(); //曲线变折线
foreach(var x in p.PathPoints)
{
//g.DrawArc(Pens.Green, x.X - 1, x.Y - 1, 3, 3, 0, 360);//标记每个节点
}
}
}
}
}
xuzuning 2016-01-17
  • 打赏
  • 举报
回复

控制点坐标相同时:
DrawBeziers 红线
DrawCurve 蓝线

#11 示意的解法,数学推导是很复杂的
无论是求取那两条平行线的交点(圆心),还是从切点反推圆心,多比较复杂
还有一个在用 DrawArc 绘图时的起始角和终止角的计算问题

即便是用迭代器,计算量也还是很大的

现在示意的算法,是指定曲线起(终)点到线路交点的距离
通过比例就可求出曲线端点坐标和控制点坐标,计算量极小

你需要的只是一段示意性的曲线,是否是真正的弧并不重要
而动画通过曲线时所需的坐标点可通过 GraphicsPath.StartFigure 方法转换得到
早起晚睡 2016-01-17
  • 打赏
  • 举报
回复
你那个弧度的半径要根据小车的长宽确定,那样比较切合实际
  • 打赏
  • 举报
回复
找两个平行线,其实也不容易。而且用此方法找到内接圆的圆心,你还是要计算出汽车走弧线的起点和终点(结束弧线)的坐标点的。 因此其实最省事的做法,不是找两个平行线。而是直接计算出弧线起点和终点距离原来的拐点的长度,然后直接沿着两个原始线段去找到(例如使用逐步逼近方法)这两个点的坐标。 假设给你一条直线(段),以及直线上的一个点,让你用解析几何方式来写出在这一点上的外切圆(半径是固定的),是不是很容易? 这样来确定内接圆的方程,要比找两个平行线,更简单。
  • 打赏
  • 举报
回复
在一条线段上,如果你要找到距离其一个端点x 距离为k 的那个点,如果你懒得推导公式,也不需要太快的速度,完全可以采取”逼近“的做法。选择起点a、终点b,中间点c,计算c距离x的距离,然后根据它与k的大小对比,来判断是从ac逼近结果还是从cb逼近结果。经过几次计算,就能找到在线端上距离端点x的距离非常接近k的点的坐标了。
  • 打赏
  • 举报
回复
引用 7 楼 Lappidoth 的回复:
涉及到好多角度的计算,有点乱
给出任意一个线段的两个端点,你可以计算出斜率或者角度吧?那么算出两个线段的夹角也就是很简单的加减法。 其实主要就是算出弧线的起点、弧线的终点。
早起晚睡 2016-01-16
  • 打赏
  • 举报
回复
你这路线就有问题 谁家的路是突然就掉头了 再说路也比汽车宽吧然后再走直线
lappidoth 2016-01-16
  • 打赏
  • 举报
回复
引用 1 楼 sp1234 的回复:
一个简单的办法,就是用一个“固定半径的圆”来内接两个线段内侧。 首先算出两个线段的夹角,取它的一半夹角(中分线上)为a。根据内接圆半径r,以及这个角度a,你就能算出汽车应该距离拐点还有多远的地方就应该走圆弧线了。
涉及到好多角度的计算,有点乱
lappidoth 2016-01-16
  • 打赏
  • 举报
回复
引用 3 楼 xuzuning 的回复:
DrawBeziers DrawCurve
可是路线一直是直的,只有到了拐弯的时候才有了弧度
xuzuning 2016-01-16
  • 打赏
  • 举报
回复
  • 打赏
  • 举报
回复
嗯,这并不需要去搞什么样条插值。完全没有必要那么精确且进行大量运算。
  • 打赏
  • 举报
回复
你会发现,就是一个很小的圆弧角,可不是要插值啊。如果样条插值,那么汽车整个都“喝醉了”,不走直线了。
xuzuning 2016-01-15
  • 打赏
  • 举报
回复
DrawBeziers DrawCurve
  • 打赏
  • 举报
回复
根据夹角a和圆半径r,结合第一条线段的方向你就能知道开始走弧线的起点坐标,结合第二条线的方向你就能知道离开元弧线重回第二条线的坐标。
  • 打赏
  • 举报
回复
一个简单的办法,就是用一个“固定半径的圆”来内接两个线段内侧。 首先算出两个线段的夹角,取它的一半夹角(中分线上)为a。根据内接圆半径r,以及这个角度a,你就能算出汽车应该距离拐点还有多远的地方就应该走圆弧线了。

111,128

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧