Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: Tim CochranОтветов: 3

У меня есть следующие массивы 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. Две дуги очень различимы:

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

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

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

Любые идеи?

beziergdi+graphicspath

Ответы

Ответ 1 · рейтинг 1 · Julio Themen

Используйте класс 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)

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

Ответ 2 · TEN Ware

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

Ответ 3 · SiliconMind

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

В этом случае вы ожидаете, что кривая начинается с [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.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы