C++ 2D библиотека составления мозаики?

Вы можете использовать мой CommandParameterBehavior, что я отправил на форумы Призмы вчера. Это добавляет недостающее поведение, где изменение в эти CommandParameter заставляет Command быть повторно запрошенным.

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

необходимо будет, вероятно, удалить эти IDelegateCommand материал, если Вы не будете использовать Призму (и хотят внести те же изменения как я к библиотеке Prism). Также обратите внимание, что мы обычно не используем RoutedCommand с здесь (мы используем Призму DelegateCommand для в значительной степени всего), поэтому не держите меня ответственный, если мой вызов к CommandManager.InvalidateRequerySuggested выделяет своего рода квант wavefuntion каскад коллапса, который уничтожает известную вселенную или что-либо.

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;

namespace Microsoft.Practices.Composite.Wpf.Commands
{
    /// 
    /// This class provides an attached property that, when set to true, will cause changes to the element's CommandParameter to 
    /// trigger the CanExecute handler to be called on the Command.
    /// 
    public static class CommandParameterBehavior
    {
        /// 
        /// Identifies the IsCommandRequeriedOnChange attached property
        /// 
        /// 
        /// When a control has the 
        /// attached property set to true, then any change to it's 
        ///  property will cause the state of
        /// the command attached to it's  property to 
        /// be reevaluated.
        /// 
        public static readonly DependencyProperty IsCommandRequeriedOnChangeProperty =
            DependencyProperty.RegisterAttached("IsCommandRequeriedOnChange",
                                                typeof(bool),
                                                typeof(CommandParameterBehavior),
                                                new UIPropertyMetadata(false, new PropertyChangedCallback(OnIsCommandRequeriedOnChangeChanged)));

        /// 
        /// Gets the value for the  attached property.
        /// 
        /// The object to adapt.
        /// Whether the update on change behavior is enabled.
        public static bool GetIsCommandRequeriedOnChange(DependencyObject target)
        {
            return (bool)target.GetValue(IsCommandRequeriedOnChangeProperty);
        }

        /// 
        /// Sets the  attached property.
        /// 
        /// The object to adapt. This is typically a , 
        ///  or 
        /// Whether the update behaviour should be enabled.
        public static void SetIsCommandRequeriedOnChange(DependencyObject target, bool value)
        {
            target.SetValue(IsCommandRequeriedOnChangeProperty, value);
        }

        private static void OnIsCommandRequeriedOnChangeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (!(d is ICommandSource))
                return;

            if (!(d is FrameworkElement || d is FrameworkContentElement))
                return;

            if ((bool)e.NewValue)
            {
                HookCommandParameterChanged(d);
            }
            else
            {
                UnhookCommandParameterChanged(d);
            }

            UpdateCommandState(d);
        }

        private static PropertyDescriptor GetCommandParameterPropertyDescriptor(object source)
        {
            return TypeDescriptor.GetProperties(source.GetType())["CommandParameter"];
        }

        private static void HookCommandParameterChanged(object source)
        {
            var propertyDescriptor = GetCommandParameterPropertyDescriptor(source);
            propertyDescriptor.AddValueChanged(source, OnCommandParameterChanged);

            // N.B. Using PropertyDescriptor.AddValueChanged will cause "source" to never be garbage collected,
            // so we need to hook the Unloaded event and call RemoveValueChanged there.
            HookUnloaded(source);
        }

        private static void UnhookCommandParameterChanged(object source)
        {
            var propertyDescriptor = GetCommandParameterPropertyDescriptor(source);
            propertyDescriptor.RemoveValueChanged(source, OnCommandParameterChanged);

            UnhookUnloaded(source);
        }

        private static void HookUnloaded(object source)
        {
            var fe = source as FrameworkElement;
            if (fe != null)
            {
                fe.Unloaded += OnUnloaded;
            }

            var fce = source as FrameworkContentElement;
            if (fce != null)
            {
                fce.Unloaded += OnUnloaded;
            }
        }

        private static void UnhookUnloaded(object source)
        {
            var fe = source as FrameworkElement;
            if (fe != null)
            {
                fe.Unloaded -= OnUnloaded;
            }

            var fce = source as FrameworkContentElement;
            if (fce != null)
            {
                fce.Unloaded -= OnUnloaded;
            }
        }

        static void OnUnloaded(object sender, RoutedEventArgs e)
        {
            UnhookCommandParameterChanged(sender);
        }

        static void OnCommandParameterChanged(object sender, EventArgs ea)
        {
            UpdateCommandState(sender);
        }

        private static void UpdateCommandState(object target)
        {
            var commandSource = target as ICommandSource;

            if (commandSource == null)
                return;

            var rc = commandSource.Command as RoutedCommand;
            if (rc != null)
            {
                CommandManager.InvalidateRequerySuggested();
            }

            var dc = commandSource.Command as IDelegateCommand;
            if (dc != null)
            {
                dc.RaiseCanExecuteChanged();
            }

        }
    }
}

9
задан mpen 3 January 2011 в 18:40
поделиться

5 ответов

CGAL имеет пакеты для решения этой проблемы. Лучше всего, вероятно, будет использовать пакет 2D Polygon Partitioning . Например, вы можете сгенерировать y-монотонное разбиение многоугольника (работает и для невыпуклых многоугольников), и вы получите что-то вроде этого:

y-monoyone-partitioning y-monoyone-partitioning

Время выполнения - O (n log n).

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

typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Partition_traits_2<K>                         Traits;
typedef Traits::Point_2                                     Point_2;
typedef Traits::Polygon_2                                   Polygon_2;
typedef std::list<Polygon_2>                                Polygon_list;
typedef CGAL::Creator_uniform_2<int, Point_2>               Creator;
typedef CGAL::Random_points_in_square_2<Point_2, Creator>   Point_generator;   


int main( )
{
   Polygon_2    polygon;
   Polygon_list partition_polys;

   CGAL::random_polygon_2(50, std::back_inserter(polygon),
                      Point_generator(100));

   CGAL::y_monotone_partition_2(polygon.vertices_begin(),
                                polygon.vertices_end(),
                                std::back_inserter(partition_polys));

   // at this point partition_polys contains the partition of the input polygons
   return 0;
}

Чтобы установить cgal, если вы работаете в Windows, вы можете использовать установщик, чтобы получить предварительно скомпилированную библиотеку, и на этой странице есть руководства по установке для каждой платформы. Это может быть не так просто установить, но вы получите наиболее используемую и надежную библиотеку вычислительной геометрии, которая только есть,

17
ответ дан 4 December 2019 в 06:35
поделиться

Если вы не хотите встраивать весь GCAL в свое приложение - это, вероятно, проще реализовать.

http://www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml

2
ответ дан 4 December 2019 в 06:35
поделиться

Может быть полезно немного подробнее о желаемых входных и выходных данных.

Например, если вы просто пытаетесь превратить многоугольники в треугольники, веер из треугольников, вероятно, подойдет. Если вы пытаетесь разрезать многоугольник на маленькие части, вы можете реализовать какие-то маршевые квадраты.


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

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

Алгоритм, о котором я думал, в основном разбивал полигоны линиями, где линии представляют собой сетку, так что вы в основном получаете квадраты. Если у вас есть пересечение линии многоугольника, реализация будет простой. Другой способ поставить эту проблему - рассматривать двумерный многоугольник как функцию и накладывать сетку точек. Затем вы просто делаете что-то похожее на маршевые кубы ... если все 4 точки находятся в многоугольнике, создайте четырехугольник, если 3 образуют треугольник, 2 образуют прямоугольник и т. Д. Вероятно, перебор. Если вам нужны несколько неправильные полигоны, вы можете случайным образом расположить точки сетки.

С другой стороны, вы можете сделать подразделение в стиле catmull-clark, но опустите сглаживание. Алгоритм заключается в том, что вы добавляете точку в центре тяжести и в середине каждого края. Затем для каждого угла исходного многоугольника вы создаете новый многоугольник меньшего размера, который соединяет среднюю точку края, предшествующую углу, углу, средней точке следующего края и центроиду. Это плитки пространства, и будет иметь углы, аналогичные углам вашего входного многоугольника.

Итак, много вариантов, и мне нравятся решения для мозгового штурма, но я до сих пор понятия не имею, для чего вы планируете это использовать. Это для создания разрушаемых сеток? Вы делаете какую-то обработку сетки, которая требует меньших элементов? Пытаетесь избежать артефактов затенения по Гуро? Это что-то, что работает как предварительный процесс или в реальном времени? Насколько важна точность? Чем больше информации, тем лучше будут предложения.

Это для создания разрушаемых сеток? Вы делаете какую-то обработку сетки, которая требует меньших элементов? Пытаетесь избежать артефактов затенения по Гуро? Это что-то, что работает как предварительный процесс или в реальном времени? Насколько важна точность? Чем больше информации, тем лучше будут предложения.

Это для создания разрушаемых сеток? Вы делаете какую-то обработку сетки, которая требует меньших элементов? Пытаетесь избежать артефактов затенения по Гуро? Это что-то, что работает как предварительный процесс или в реальном времени? Насколько важна точность? Чем больше информации, тем лучше будут предложения.

1
ответ дан 4 December 2019 в 06:35
поделиться

Как упоминал balint.miklos в комментарии выше, пакет Шевчука треугольник неплох. Я сам им пользовался много раз; он прекрасно интегрируется в проекты, и есть интерфейс треугольник ++ C ++. Если вы хотите избежать осколков,

4
ответ дан 4 December 2019 в 06:35
поделиться

Если у вас выпуклые многоугольники, а вы не слишком повесили на качество, то это действительно просто - просто делайте отсечения уха . Не волнуйтесь, это не O (n ^ 2) для выпуклых многоугольников. Если вы делаете это наивно (то есть, вы обретете уши, как вы их найдете), то вы получите вентилятор треугольника, который немного сопротивляется, если вы пытаетесь избежать полет. Две тривиальные эвристики, которые могут улучшить триангуляцию, относятся к

  1. сортировать уши, или если это слишком медленно
  2. , выбирайте ухо на случайном порядке.

Если вы хотите более прочный триангулятор на основе отсечения ушей, проверьте кулак .

1
ответ дан 4 December 2019 в 06:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: