Как определить конечные точки дуг в массивах GraphicsPath PathPoints и PathTypes?

У меня есть следующие массивы PathPoints и PathTypes (формат: X, Y, Type):

-177.477900,  11021.670000, 1
-614.447200,  11091.820000, 3
-1039.798000, 10842.280000, 3
-1191.761000, 10426.620000, 3
-1591.569000, 10493.590000, 3
-1969.963000, 10223.770000, 3
-2036.929000, 9823.960000,  3
-2055.820000, 9711.180000,  3
-2048.098000, 9595.546000,  3
-2014.380000, 9486.278000,  3

Вот как физически выглядит этот GraphicsPath. Две дуги очень различимы: alt text

Я знаю, что этот массив GraphicsPath.PathData был создан двумя командами AddArc. Пройдясь по коду в отладчике, я увидел, что первые 4 значения PathData были добавлены первой командой AddArc, а оставшиеся 6 точек добавлены второй командой AddArc.

Изучив необработанные массивы точек пути/типа пути (предварительно не зная, что это были 2 команды AddArc, чтобы я знал, что у меня есть 2 начальная и конечная точки), я хотел бы определить начальную и конечную точки каждой дуги.

Я пробовал несколько вычислений Безье, чтобы «воссоздать» точки в массиве, но не могу определить, как определить отдельные начальную и конечную точки. Похоже, что GDI+ объединяет начальную/конечную точку между дугами (это одна и та же точка, а дуги соединены), и я теряю тот факт, что одна дуга заканчивается, а другая начинается.

Любые идеи?


person Tim Cochran    schedule 24.11.2009    source источник


Ответы (3)


Используйте класс GraphicsPathIterator в сочетании с методом GraphicsPath.SetMarkers.

Например:

dim gp as new GraphicsPath
gp.AddArc(-50, 0, 100, 50, 270, 90) 'Arc1
gp.SetMarkers()
gp.AddArc(0, 25, 100, 50, 270, 90) 'Arc2
Dim iterator as New GraphicsPathIterator(gp)
Dim i as Integer = 0
Dim MyPts(3) As PointF
Dim temp as New GraphicsPath
Do until i > 2
   iterator.NextMarker(temp)
   MyPts(i) = temp.PathPoints(0)
   MyPts(i + 1) = temp.GetLastPoint()
  i += 2
Loop

'Free system resources...
iterator.Dispose()

temp.Dispose()

Arc1 -> start: MyPts(0); end: MyPts(1)
Arc2 -> start: MyPts(2); end: MyPts(3)

Надеюсь это поможет!

person Julio Themen    schedule 25.01.2011
comment
Это может помочь, если вы действительно можете добавлять маркеры при создании пути. Но это не всегда возможно. Посмотрите на этот ответ чтобы лучше понять внутреннюю структуру GraphicsPath. - person SiliconMind; 27.06.2013

Взгляните на перечисление PathPointType (System.Drawing.Drawing2D). Значение Значение 0 Начало (путь) 1 Линия 3 Безье/Безье3 7 Маска типа пути 16 Режим тире 32 Маркер пути 128 Закрыть вложенный путь

person TEN Ware    schedule 03.12.2009
comment
Это то, что 3-й номер в моем списке выше (PathPointType). У меня проблема в том, что в массиве выше есть 2 кривые Безье/Безье3 (PathPointType = 3). Мне нужно выяснить, как определить, где разделить массив. Я знаю, что добавил дугу программно, что значение «-1191.761000, 10426.620000, 3» является конечной точкой первой дуги и начальной точкой второй дуги. Однако мне нужно выяснить, как определить это программно. - person Tim Cochran; 04.12.2009

Меня этот тоже сильно напрягал! У меня был путь, созданный вне моего контроля без маркеров, и я не мог определить конечные точки кривой.

В этом случае вы ожидаете, что кривая начинается с [i + 1], но это не так! Оказывается, GDI объединяет точки пути, вероятно, для того, чтобы сделать массив точек короче. В этом случае точками кривой являются: [0], [1], [2], [3].

Кажется, что если за PathPointType.Start или PathPointType.Line следует PathPointType.Bezier, то вы должны рассматривать PathPontType.Start или Path.PointType.Line как первую точку вашей кривой Безье, поэтому в вашем примере это должно быть так:

 -177.47, 11021.67, 1  // Draw line to this point AND use it as a Bezier start!
 -614.44, 11091.82, 3  // Second Bezier point
-1039.79, 10842.28, 3  // Third Bezier point
-1191.76, 10426.62, 3  // Fourth Bezier point AND first point of the next Bezier!
-1591.56, 10493.59, 3  // Second Bezier point
-1969.96, 10223.77, 3  // Third Bezier point
-2036.92,  9823.96, 3  // Fourth Bezier point AND first point of the next Bezier!
-2055.82,  9711.18, 3  // Second Bezier point
-2048.09,  9595.54, 3  // Third Bezier point
-2014.38,  9486.27, 3  // Fourth Bezier point

Таким образом, при анализе массива PathPoints по точкам необходимо также проверять текущие и последующие индексы. Документы по PatPointType могут пригодиться. В большинстве случаев вы, вероятно, можете игнорировать дополнительные данные, хранящиеся в битах, отличных от первых трех (эти три определяют Start, Line и Bezier). Единственным исключением является CloseSubpath, но это не имеет значения, если вы прислушаетесь к следующему совету.

Также стоит отметить, что если у вас есть сложный путь, состоящий из огромного количества PathPoints, может быть удобно разбить путь на куски, используя GraphicsPathIterator. Это упрощает всю процедуру, так как PathPointType.CloseSubpath можно игнорировать - это всегда будет последняя точка вашего GraphicsPath чанка.

Краткий обзор Reflector или здесь может быть полезно, если вы хотите лучше понять массив PointTypes.

person SiliconMind    schedule 27.06.2013