Рисование путей между элементами управления, которые не пересекаются и не перекрываются.C#

Место общения программистов C#
Ответить
Anonymous
 Рисование путей между элементами управления, которые не пересекаются и не перекрываются.

Сообщение Anonymous »

Некоторое время я пытался найти решение для рисования путей между элементами управления, которые не пересекаются и не перекрывают друг друга, но, похоже, у меня закончились идеи. Я пробовал использовать MSAGL 1.1.6, а также пытался реализовать его с нуля.
Изображение

Зеленые пути на изображении представляют пути, которые я хочу нарисовать. Однако я продолжаю получать пути, подобные красным, которые пересекаются друг с другом или с другими элементами управления или частично перекрываются.

Код: Выделить всё

private class Conn {
public IIndicatorUser Src = null;
public IIndicatorUser Dst = null;
public Rectangle Rs;
public Rectangle Rd;
public GPoint SrcCenter;
public GPoint DstCenter;
public Side SrcSide;
public Side DstSide;
public int SrcIndex;
public int SrcCount;
public int DstIndex;
public int DstCount;
}
private enum Side { Left, Right, Top, Bottom }

private static Side ChooseSideTowards(Rectangle rect,GPoint toward) {
var center = new GPoint(rect.Left + (rect.Width / 2.0), rect.Top + (rect.Height / 2.0));
var dx = Math.Abs(toward.X - center.X);
var dy = Math.Abs(toward.Y - center.Y);
const double horizontalBias = 2.7;
if(dx>dy*horizontalBias)
return toward.X=center.Y ? Side.Bottom : Side.Top;
}

private static GPoint AnchorOnSide(Rectangle r,Side side,int index,int count) {
const int margin = 6;
count=Math.Max(1,count);
index=Math.Max(0,Math.Min(index,count-1));
if(side==Side.Left||side==Side.Right) {
var x = side == Side.Left ? r.Left : r.Right;
var span = Math.Max(0, r.Height - (2 * margin));
var y = r.Top + margin + (span * ((index + 1.0) / (count + 1.0)));
return new GPoint(x,y);
}
else {
var y = side == Side.Top ? r.Top : r.Bottom;
var span = Math.Max(0, r.Width - (2 * margin));
var x = r.Left + margin + (span * ((index + 1.0) / (count + 1.0)));
return new GPoint(x,y);
}
}

protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
using(var outPen = new Pen(Color.Black,3.5f))
using(var penGreen = new Pen(Color.LimeGreen,3.0f))
using(var penRed = new Pen(Color.Red,3.0f)) {
if(_connections.Count==0)
return;

var obstacles = new List();
var inflatedBounds = new Dictionary();
foreach(IIndicatorUser btn in Controls.OfType()) {
if(btn.IsDisposed) continue;
var r = new Rectangle(btn.Location, new Size(btn.Width, btn.Height));
r.Inflate(1,1);
inflatedBounds[btn]=r;

var center = new GPoint(r.Left + (r.Width / 2.0), r.Top + (r.Height / 2.0));
ICurve boundary = CurveFactory.CreateRectangle(r.Width, r.Height, center);
var shape = new Microsoft.Msagl.Routing.Shape(boundary);
obstacles.Add(shape);
}

var conns = new List();
foreach((IIndicatorUser Src, IIndicatorUser Dst) in _connections) {
IIndicatorUser src = Src;
IIndicatorUser dst = Dst;
if(src.IsDisposed||dst.IsDisposed) continue;
if(!Controls.Contains((Control)src)||!Controls.Contains((Control)dst)) continue;

Rectangle rs = inflatedBounds[src];
Rectangle rd = inflatedBounds[dst];
var srcCenter = new GPoint(rs.Left + (rs.Width / 2.0), rs.Top + (rs.Height / 2.0));
var dstCenter = new GPoint(rd.Left + (rd.Width / 2.0), rd.Top + (rd.Height / 2.0));
Side ss = ChooseSideTowards(rs, dstCenter);
Side ds = ChooseSideTowards(rd, srcCenter);

conns.Add(new Conn {
Src=src,
Dst=dst,
Rs=rs,
Rd=rd,
SrcCenter=srcCenter,
DstCenter=dstCenter,
SrcSide=ss,
DstSide=ds,
});
}

var srcGroups = new Dictionary();
var dstGroups = new Dictionary();
foreach(Conn c in conns) {
(IIndicatorUser Src, Side SrcSide) gs = (c.Src, c.SrcSide);
(IIndicatorUser Dst, Side DstSide) gd = (c.Dst, c.DstSide);
if(!srcGroups.TryGetValue(gs,out List l1)) { l1=new List(); srcGroups[gs]=l1; }
if(!dstGroups.TryGetValue(gd,out List l2)) { l2=new List(); dstGroups[gd]=l2; }
l1.Add(c);
l2.Add(c);
}

foreach(KeyValuePair  kv in srcGroups) {
Side side = kv.Key.Item2;
List list = kv.Value;
if(side==Side.Left||side==Side.Right)
list.Sort((a,b) => a.DstCenter.Y.CompareTo(b.DstCenter.Y));
else
list.Sort((a,b) => a.DstCenter.X.CompareTo(b.DstCenter.X));

for(var i = 0; i a.SrcCenter.Y.CompareTo(b.SrcCenter.Y));
else
list.Sort((a,b) => a.SrcCenter.X.CompareTo(b.SrcCenter.X));

for(var i = 0; i

Подробнее здесь: [url]https://stackoverflow.com/questions/79837994/drawing-paths-between-controls-that-do-not-intersect-each-other-and-dont-overla[/url]
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»