2011-12-13 4 views
9

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

У меня есть следующий пример геометрии:

<Path Fill="White" Stretch="Fill" Stroke="Black" StrokeThickness="2"> 
     <Path.Data> 
      <PathGeometry 
       Figures="M112,296C112,296 136,296 136,320 M112,344C112,344 136,344 136,320 M112,296L112,296 96,296 96,344 112,344"/> 
     </Path.Data> 
    </Path> 

Который производит следующий результат:

Undesired Fill Result

Это результат я хотел бы видеть:

Desired Fill Result

Любые Идеи? Я знаю, что могу сделать одну дугу, и это разрешит этот конкретный случай, но в моем приложении пользователь может нарисовать любую геометрию, чтобы результат мог состоять из любого количества «примитивов» (PolyLineSegments, EllipseGeometries, ArcSegments и т. Д.), и в случае, если результирующая геометрия содержит некоторый тип замкнутой области, я хотел бы точно заполнить эту область.

EDIT:

Вот пример того, что CombinedGeometry выглядит, как если бы я гарантировать, что все три смежных геометрий перекрывают друг друга и создать unioned CombinedGeometry со следующим кодом:

 <Path Grid.Row="2" Fill="White" Stretch="Fill" Stroke="Black" StrokeThickness="2"> 
     <Path.Data> 
      <CombinedGeometry GeometryCombineMode="Union"> 
       <CombinedGeometry.Geometry1> 
        <CombinedGeometry GeometryCombineMode="Union"> 
         <CombinedGeometry.Geometry1> 
          <PathGeometry 
           Figures="M111,293C111,296 136,293 136,325"/> 
         </CombinedGeometry.Geometry1> 
         <CombinedGeometry.Geometry2> 
          <PathGeometry 
           Figures="M111,346C111,344 136,344 136,320"/> 
         </CombinedGeometry.Geometry2> 
        </CombinedGeometry> 
       </CombinedGeometry.Geometry1> 
       <CombinedGeometry.Geometry2> 
        <PathGeometry 
         Figures="M125,296L115,296 96,296 96,344 120,344"/> 
       </CombinedGeometry.Geometry2> 
      </CombinedGeometry> 
     </Path.Data> 
    </Path> 

И вот результат:

Combined Geometry

Я был хопи ng он объединил бы просто штрихи и автоматически определял правильное заполнение для нового смежного полигона ... bummer.

EDIT 2:

Хм, так что я думаю, что я придумал пару возможных решений, ни один из которых так же просто, как я надеялся, что они будут. Первый вариант состоял бы в том, чтобы объединить все геометрии, как указано выше, с помощью структуры CombineGeometry, затем я назвал «GetFlattenedPathGeometry» на итоговой «CombineGeometry», чтобы получить PathGeometry. Затем я перебираю каждую фигуру в PathGeometry и просто удаляю те, которые являются отверстиями (которые, я думаю, вы должны сделать, избавляясь от всех фигур, которые полностью содержатся другим, или отверстия могут следовать за соглашением о том, что либо по часовой стрелке или против часовой стрелки, не уверен.), если все идет хорошо, вам следует оставить одну полностью заполненную геометрию.

Второй вариант заключается в том, чтобы снова вызвать «GetFlattenedPathGeometry» на любом результирующем пути, чтобы получить многоугольную аппроксимацию пути на основе вершин (без обозначения всей кривой, дуги, эллипса и т. Д., Мы хотим, чтобы путь, содержащий только точки и линии). После этого вы просто объедините все результирующие фигуры/сегменты в одну фигуру, сегменты которой упорядочены либо по часовой стрелке, либо против часовой стрелки.

Я тестировал оба подхода, и они, похоже, работают, по крайней мере, с простым тестовым примером, описанным выше, хотя они не будут работать с более сложными формами (самопересекающимися, вогнутыми и т. Д.) .. поддержкой, которые мне требуются. поэтому вопрос остается, как мне это сделать?

РЕДАКТИРОВАТЬ 3:

Вот более сложную геометрию, в которой упорядочение/объединения становится более трудным:

 <Path Fill="White" Stretch="Fill" Stroke="Black" StrokeThickness="2"> 
     <Path.Data> 
      <PathGeometry 
      Figures="M104,160C104,160 72,160 72,136 
       M104,128C104,128 72,128 72,152 
       M152,232L152,232 152,216 120,216 120,160 128,160 
       M152,232L152,232 72,232 104,216 104,160 96,160 
       M104,128L104,128 168,128 
       M128,160L128,160 168,160 
       M165,160L168,160 200,128 
       M200,160L200,160 200,128 
       M200,160L200,160 168,128 152,128"/> 
     </Path.Data> 
    </Path> 

Который производит:

enter image description here

ответ

5

Ваш пример геометрии представляет собой комбинацию трех смежных форм, которые не перекрываются. Ход рисуется на внешних краях просто потому, что формы не закрыты, а внутренние линии хода не существуют. Хотя может показаться, что формы объединяются и штрих применяется к геометрии в целом, это не то, что происходит.

Закрытие отверстия становится более сложной задачей программного обнаружения отверстия и закрытия его соответствующей формой или путем создания новой комбинированной формы, которая не имеет отверстия (возможно, путем обнаружения и отслеживания внешних точек). Я не знаю о какой-либо функциональности в WPF, которая может помочь вам в решении этой задачи. Существует класс CombinedGeometry, который может создавать объединение двух перекрывающихся фигур. Формы в этом примере не перекрываются.

Без контекста трудно рекомендовать решение. Если это бесплатная программа для рисования, возможно, пользователю просто нужно нарисовать другую фигуру посередине, чтобы закрыть геометрию.

+0

Спасибо за ваш ответ. Под «закрытием отверстия» вы подразумеваете отверстие в заливе или небольшой зазор между соседними геометриями? Если вы имеете в виду пробел между геометриями, я вскоре опубликую короткое сообщение с грубым примером CombinedGeometry, который, похоже, имеет такую ​​же проблему, когда штрихи смежных геометрий перекрываются и объединяются с объединением. Еще раз спасибо! – Craig

+0

Счастливые помочь. Я имел в виду большую область, которую вы пытаетесь заполнить, а не небольшой промежуток между соседними геометриями. Как показывает ваш отредактированный эксперимент, объединенное объединение нескольких фигур не устраняет дыру. Я не мог найти никаких функций в WPF, которые бы идентифицировали и удаляли отверстия, заключенные в касание или перекрывающиеся геометрии. Ваш подход сочетания геометрии и удаления фигур, которые полностью закрыты, звучит как отличный старт. – Scott

2

Лечить его как "соединить точки" проблемы :)

У вас есть 5 очков:

  • 96.296 - верхняя левая точка (угол)
  • 112296 - верхнее - начало кривого Безье
  • 136320 - крайний справа - конец первой кривой Безье, начало второго одного
  • 112,344 - нижний - конец второго Безье
  • 96 344 - нижняя левая точка (угол)

И теперь мы их соединим.

<Path Fill="White" Stretch="Fill" Stroke="Black" StrokeThickness="2"> 
    <Path.Data> 
     <PathGeometry Figures="M112,296 C112,296 136,296 136,320 C136,320 136,344 112,344 M112,344 96,344 96,296 112,296"/> 
    </Path.Data> 
</Path> 

Вы также можете использовать < GeometryGroup FillRule = "" ... Отлично от нуля >, чтобы заполнить свой собственный путь от 1-го поста. По умолчанию используется FillRule = «EvenOdd», который производит заполнение, подобное вашему. *

Дополнительную информацию о путевом мини-языке см. В разделе Синтаксис разметки пути (http://msdn.microsoft.com/en-us/library/ms752293.aspx).

  • Изменено < Путь > к <GeometryGroup>

EDIT 1:

Я заказана ваш путь немного:

<Path Fill="White" Stretch="Fill" Stroke="Black" StrokeThickness="2"> 
    <Path.Data> 
     <PathGeometry Figures="M72,152 C72,152 72,128 104,128 L168,128 200,160 200,128 168,160 120,160 120,216 152,216 152,232 72,232 104,216 104,160 C104,160 72,160 72,136"/> 
    </Path.Data> 
</Path> 

Который дает нам:

New shape

рисования путь, как с помощью какой-то «нарисовать форму» инструмента в программное обеспечение для редактирования вектора, где вы должны выбрать следующие пункты, и если вы не имеете следующий - форма автоматически закрывается (последний точка связана с первой, но только с целью заполнения формы - мы можем видеть, как это делается, когда мы смотрим на «нос» новой формы). В вашем примере У вас есть 9 отдельных фигур (каждая в отдельной строке, где M задает начало новой фигуры), и все они заполнены указанным выше способом.

Конечно, вы можете использовать GeometryGroup (с FillRule) или CombinedGeometry (с CombinedGeometryMode) для соединения фигур.

+0

Спасибо за ответ. Заказ фигур по часовой стрелке - это то, что я пробовал и нашел для работы для простых фигур, но такой же подход не будет работать для более сложных форм (самопересекающихся, вогнутых и т. Д.). Кроме того, Path не имеет свойства «FillRule» (по крайней мере, не в .NET 3.5), но я попытался помещать геометрии в GeometryGroup, у которого FillRule был ненулевым, но я получил те же результаты. В ближайшее время я опубликую более сложную геометрию и надеюсь, что вы можете доказать мне, что не так :). – Craig

+0

Ницца. Итак, как бы вы предлагали, я заказываю геометрию программно? Мой инструмент позволяет пользователю создавать эти фигуры из любой комбинации геометрий, поэтому я получаю что-то вроде того, что я написал выше, где геометрия упорядочена любым способом, которым пользователь добавил их на холст. Мне нужно будет изменить порядок этих геометрий программно, чтобы они были правильно заполнены. Я пробовал использовать CombinedGeometry, но это объединяет не только штрих, но и заполнение, поэтому вы получаете нечто похожее на то, с чего вы начали. – Craig

+0

При создании геометрии вы можете попробовать добавить следующую фигуру («примитив») без запуска новой фигуры (Mxxx, xxx) - в случае ie. кривые безьевой контрольной точки должны автоматически устанавливаться (коорды такие же, как и последняя точка). Вы можете попробовать что-то вроде этого (x, y - пользовательские координаты): PathGeometry geom = new PathGeometry(); PathFigure path = new PathFigure(); path.StartPoint = новая точка (x, y); geom.Figures.Add (путь); LineSegment line = новый LineSegment(); line.Point = новая точка (x, y); path.Segments.Add (линия); и т. д. Вы также должны назначить geom _xamlPathObject_.Данные –

1

Обнаружил an interesting article о создании фигур с помощью wpf с помощью svg-файла, созданного с помощью графического инструмента, такого как inkscape. Это может дать вам некоторое представление.

Смежные вопросы