Типичная задача — визуализация данных. Например томографы или сканеры отдают физически результат в виде облака точек, а визуализировать их нужно как твердый объект.
Обычно, правда, для подобных вещей (где точки в сетке с определенным разрешением) используют Marching Cubes
Хороший случай именно для такого алгоритма — построение выпуклой оболочки 3д объекта для использования в физическом движке (для игр и симуляций). Часто в физ движках выпуклые многогранники проще проверяются, кроме того, он будет состоять из значительно меньшего количества треугольников, чем исходная модель.
Спасибо, довольно интересная статья. Для понимания потребовалось некоторое мысленное усилие, но в целом алгоритм кажется даже простым.
Есть несколько вопросов и замечаний.
«Алгоритм работает только если на вход подается множество точек, в котором никакие 4 не лежат в одной плоскости. То есть каждые 3 точки задают свою плоскость.»
А почему в этом случае алгоритм не будет работать? Кажется, что будет небольшая неопределенность в том, какая точка будет добавлена (как именно будет триангулирован конкретный четырехугольник/полигон), зависящая от ошибок в округлении. Но в целом задача будет решена. Или есть какие то критические случаи?
Алгоритм использует стек. Это обязательно? Можно ли использовать очередь?
Я представляю его работу, как некий «жадный» алгоритм в глубину — получается ребра будут нарастать с одной стороны, наматываясь в сторону первого ребра по часовой стрелке, получится нечто похожее на кожуру апельсина, который рвали одной стороной. При этом когда до первых ребер дойдет очередь, они уже будут закрыты. Кажется, что использование очереди просто сделает заворачивание похожим на апельсин, заворачиваемый дольками — больше похоже на оборачивание подарка)) Единственный плюс стека — отсутствие фрагментации.
По поводу замечаний — после нахождения первых трех точек нигде не вводится определение «ребра». Стоило бы уточнить, что речь о ребрах, уже входящих в оболочку (прежде всего — идущих по ее краю — остальные ребра закрыты), и первые три точки образуют начальную грань, добавляющую первые 3 ребра.
Второе — фраза «Мы храним ребра в стеке, поочередно достаем их и рассматриваем: нужно ли добавить это ребро в нашу оболочку.» Эта фраза кажется построенной не правильно — мы храним список ребер, входящих в нашу оболочку (являющиеся краями уже найденных граней). Мы поочередно достаем их и проверяем — можем ли мы добавить к ним грань? (Не является ли ребро уже закрытым гранями с обеих сторон?)
Возможно, Я неправильно понял алгоритм, и тогда оба замечания не верные)
Нет, судя по всему это 2 разные проблемы.
Легли сервера валидации сертификатов разработчиков, которые проверяют подписи приложений. Из-за этого даже корректные приложения с действительными сертификатами не запускались.
Отдельная проблема — изменение API для работы с сетью, из-за которых работа брандмауэров и VPN стала некорректной.
Последнее предложение — из за тех же изменений в API брандмауэры не могут блокировать и перехватывать запросы к OCSP
Короче эппл как всегда закрутила гайки всем (ради нашей безопасности), но открутила себе (ради нашей безопасности, конечно же), но неудачно вышло с упавшим сервисом.
Кажется, что вы недооцениваете физичность некоторых ситуаций.
Например, 3 машины двигаются парралельно (разгоняются после светофора на многополосной дороге).
Сама по себе ситуация штатная.
Между машинами 2 м, скорость 60 км/ч
Если крайняя машина в один прекрасный момент решит протаранить бок центральной — ей потребуется 0,25 сек на весь маневр. Нет никакой возможности это предотвратить. Маневр в другую сторону невозможен — там другая машина, и при попытке совершить более резкий маневр ты достигнешь ее еще быстрее. Торможение происходит со скоростью до 10 м/с^2 — за 0,25 секунды разница составит пол корпуса — даже при идеальной реакции все равно попадут.
Это безотносительно машин с автопилотом.
Я попробую ответить.
Если кратко — со связностью нужно работать аккуратно и внимательно следить за ней.
Тут есть 2 аспекта — проблемы с EventBus и связность компонентов с EventBus компонентов с компонентами.
Зависимости:
— Сам по себе EventBus без сомнений станет зависимостью для всех, но это само по себе не большая проблема. Проблемой станет паразитные зависимости — если event bus будет связан с настройками/интерфейсами или конкретными сущностями (например, если его встраивают в главный контроллер игры). Он должен быть стабилен — синглтон с ленивой инициализацией, не ссылающйся ни на какие другие файлы.
— Если вы пишите переносимые компоненты — виджеты, компоненты рендера — не используйте EventBus. Используйте его в игровой логике.
— Не используйте EventBus с абстрактными или строковыми параметрами, используйте на интерфейсах или типах данных. Это защитит при переносах и переиспользовании компонент через зависимость на типы передаваемых сообщений/интерфейсы. Если вы завели тип/интерфейс в неймспейсе поставщика, все подписчики все равно получат явную зависимость на абстракцию от поставщика (его тип данных).
Но на самом деле это меньшие из проблем, самая важная проблема — это когда основной flow приложения неявным образом опирается на порядок вызовов в EventBus (который, по идее, обычно никак не гарантируется контрактом). Есть еще смежная проблема — когда в игре нельзя найти концов того, как игра пришла к такому состоянию (потому что ею управляла цепочка подписок).
Чтобы бороться с этими проблемами нужно ограничить использование EventBus:
— Пассивные реакции — компоненты, реагирующие на ивенты должны менять только свое состояние, но не состояние других компонентов.
— Низкоуровневые реакции — компоненты, реагирующие на ивенты, должны быть ниже по уровню абстракции. Условно, листья не должны шевелить деревом, дерево не должно управлять стартом игры (но наоборот — можно). Если у вас есть такое место, к примеру, рестарт игры завязан на упавшее здоровье игрока — возможно вы что-то делаете не так. Об этом же говорят проблемы с изменением списка подписчиков — скорее всего один из подписчиков слишком важная шишка и не должен быть просто подписчиком. Решайте это выделением специальных механизмов — к примеру, игрок должен иметь специальный колбек, который должен быть задан при его создании — тогда контроллер сущностей получает явную ручку для организации flow. А вот все остальные — интерфейсы здоровья, эффекты и т.д. — они подписываются на ивент изменения здоровья игрока.
— Изоляция. Если вы вынуждены написать логику, нарушающую первые 2 правила — выделите ее в отдельное место, которое об этом явно говорит. Например, ваши ГД хотят сами управлять условиями того, как завершается уровень, и хотят использовать для этого любой ивент, доступный им. Или стартующее новые миссии.
В этом случае это место станет точкой отказа, по логами и стактрейсу можно будет определить его как источник в случае ошибок, и в нем же можно будет разобраться с проблемами очередности и одновременности (к примеру, в этом компоненте можно будет организовать очередь сообщений, если могут быть выполнены сразу несколько условий с конфликтующими управляющими воздействиями)
Скорее всего потому, что фантастика не идет по пути «добавить, например, теоретически вполне реальные термоядерные двигатели» и прикинуть, как это изменит возможность реалистичных боев в космосе.
Фантастика идет по пути «пиу пиу, дог файт как в фильмах про первую мировую»
Безусловно, добавление каждого нового фантастического элемента (гиперпрыжки/суперэффективные лазеры и т.д.) серьезно может изменить стратегию и тактику такого сражения, но оно все еще больше будет похоже на многодневное маневрирование, прицеливание и войну точности, машин и скоростей, а не лихой кавалерийский наскок.
И открытые кокпиты, космические истребители с пилотами внутри и прочие атрибуты Звездных войн никак не станут актуальнее даже со сравнениями.
Чтобы это работало, нужно еще и непредсказуемо и постоянно маневрировать.
Иначе можно определить расстояние до тебя и жахнуть с математически корректным упреждением, которое целиком совпадет с реальностью.
Экономия и рациональное использование — это очень хороший путь, но у него быстро наступает предельная эффективность.
Нужно отвечать на оба вопроса — и генерации и потребление.
Все в описанном посте хорошо и правильно, кроме того, что он не обошелся БЕЗ интерфейса.
Интерфейс был, просто очень простой и понятный.
Впрочем книга то как раз про это, претензия скорее к статье.
По проектированию пользовательского взаимодействия для начинающих могу еще порекомендовать «психбольница в руках пациентов»
У меня Vectorman зависал на ровно одном уровне. Гидропонная ферма вроде.
Что характерно, пройти игру Я все же смог — был встроенный чит, позволяющий открыть 5/10/15/последний уровень, соответственно открывал уровень после и проходил.
Годы спустя прошел этот уровень на эмуляторе, и, как оказалось, непроходимым был реально только он — следующий за ним как раз был тем, который открывался читом.
А знает ли кто-нибудь ответ на смежный вопрос — а как игры с модификациями железа эмулируются на эмуляторах?
Никак, только стандартный ROM?
Или есть эмуляторы для соответствующих доп механизмов?
Кажется, что многие не понимают принципа «пишите скучно».
Экзотические варианты есть, но каждый такой вариант должен быть в осознаным и вызывать вопрос — а нужно ли так делать, если это вызывает такие проблемы?
А главное — иногда ты пишешь скучно, а хак получается из-за ошибки. И вот тогда супер полезно обратить на него пристальное внимание.
Большой взрыв не раз назывался неудачно распиаренным термином. Но по поводу «до большого взрыва» не обязательно «непознаваемое», просто кардинально другое состояние.
И тут, как и с технологической сингулярностью, математический термин вполне корректный.
У вас есть функция, которую можно отследить (рост пространства в первом и количество технологических открытий во втором случае)
Если бы это была простая и понятная функция — можно было бы взять условную линейку и дорисовать прогноз (что зачастую и делается на простых участках). Но есть такая точка, которая делает кучу измерений до нее практически бесполезными — настолько сильно в ней меняются свойства функции.
Экспонента простой пример — рисуешь себе спокойненько, до какого то момента кажется, что ничего не меняется а тут бац — и линию некуда рисовать. И вроде бы график не закончился еще, понятно, что дальше что-то есть, но вот отобразить на листочке уже не получается.
На эту тему было сломано множество копий в предыдущем треде, и они упираются в понимание того, что такое сознание и как оно работает.
Во первых, не все равно будет для личности оцифрованного человека в системе — у нее то как раз будет все зашибись, она будет видеть, что вот — тушка с оригиналом умирает, а вот он Я — живой, здоровый, бессмертный, красивый. И субъективно это все еще я. Для друзей и родственников это тоже все еще я. Профит. Копия просто воспринимается, как нечто типа подделки, мы не готовы признавать ее равноценность. И для картин это действительно так. А вот для файлов — не так.
Если так рассуждать, если ты воспринимаешь себя информацией, для тебя такой вариант доступен.
Можно построить это заключение еще и так. Ты сегодня — немного измененная копия себя вчера и совершенно не тот человек, который был три года назад (хотя и похож). И то, что ты по прежнему считаешь себя собой — только иллюзия, некоторое субъективное ощущение, основанное на непрерывности переносов и трансформаций.
Сознание в принципе иллюзия разума, субъективное ощущение, живущее в иллюзорном мире, к которому приводит мозг окружающую нас действительность.
Если для тебя и твоих друзей философски все нормально — у тебя нет проблем.
Во вторых, для слабых духом, которые не верят в такую философию, возможно будут доступны другие варианты. Тебе нейрон за нейроном заменяют мозг, ты в это время даже не теряешь сознание — ты продолжаешь думать, считать себя собой.
Результат аналогичный — ты думаешь целиком искусственным мозгом, теперь его, в отличие от мозга настоящего, можно выключить/включить, частично или полностью обсчитывать в симуляции, скопировать и вставить.
Наверное выключено все же сознание. Мозг вполне активен, личность — его проявление.
Воспоминания из фазы сна — это вроде просто интерпретация, она не связана с тем, что у личности новые свойства, она связана с тем, что ты так интерпретируешь местный бред.
Я, впрочем, тоже не уверен, что фраза «личность непрерывна» корректна
Ну вот потихоньку эта разница и складывается — из того, что знаешь и не знаешь, решал/не решал, решал на другом языке, видел мельком, читал и т.д.
Ты можешь не помнить не строчки синтаксиса, но само ощущение «Я очень похожее уже решал, есть стандартное решение и какой то хитрый хак» позволит тебе быстрее нарыть эту штуку, чем просто «надо погуглить»
Обычно, правда, для подобных вещей (где точки в сетке с определенным разрешением) используют Marching Cubes
Хороший случай именно для такого алгоритма — построение выпуклой оболочки 3д объекта для использования в физическом движке (для игр и симуляций). Часто в физ движках выпуклые многогранники проще проверяются, кроме того, он будет состоять из значительно меньшего количества треугольников, чем исходная модель.
Есть несколько вопросов и замечаний.
«Алгоритм работает только если на вход подается множество точек, в котором никакие 4 не лежат в одной плоскости. То есть каждые 3 точки задают свою плоскость.»
А почему в этом случае алгоритм не будет работать? Кажется, что будет небольшая неопределенность в том, какая точка будет добавлена (как именно будет триангулирован конкретный четырехугольник/полигон), зависящая от ошибок в округлении. Но в целом задача будет решена. Или есть какие то критические случаи?
Алгоритм использует стек. Это обязательно? Можно ли использовать очередь?
Я представляю его работу, как некий «жадный» алгоритм в глубину — получается ребра будут нарастать с одной стороны, наматываясь в сторону первого ребра по часовой стрелке, получится нечто похожее на кожуру апельсина, который рвали одной стороной. При этом когда до первых ребер дойдет очередь, они уже будут закрыты. Кажется, что использование очереди просто сделает заворачивание похожим на апельсин, заворачиваемый дольками — больше похоже на оборачивание подарка)) Единственный плюс стека — отсутствие фрагментации.
По поводу замечаний — после нахождения первых трех точек нигде не вводится определение «ребра». Стоило бы уточнить, что речь о ребрах, уже входящих в оболочку (прежде всего — идущих по ее краю — остальные ребра закрыты), и первые три точки образуют начальную грань, добавляющую первые 3 ребра.
Второе — фраза «Мы храним ребра в стеке, поочередно достаем их и рассматриваем: нужно ли добавить это ребро в нашу оболочку.» Эта фраза кажется построенной не правильно — мы храним список ребер, входящих в нашу оболочку (являющиеся краями уже найденных граней). Мы поочередно достаем их и проверяем — можем ли мы добавить к ним грань? (Не является ли ребро уже закрытым гранями с обеих сторон?)
Возможно, Я неправильно понял алгоритм, и тогда оба замечания не верные)
Легли сервера валидации сертификатов разработчиков, которые проверяют подписи приложений. Из-за этого даже корректные приложения с действительными сертификатами не запускались.
Отдельная проблема — изменение API для работы с сетью, из-за которых работа брандмауэров и VPN стала некорректной.
Последнее предложение — из за тех же изменений в API брандмауэры не могут блокировать и перехватывать запросы к OCSP
Короче эппл как всегда закрутила гайки всем (ради нашей безопасности), но открутила себе (ради нашей безопасности, конечно же), но неудачно вышло с упавшим сервисом.
Структурное программирование?
Функциональное?
Например, 3 машины двигаются парралельно (разгоняются после светофора на многополосной дороге).
Сама по себе ситуация штатная.
Между машинами 2 м, скорость 60 км/ч
Если крайняя машина в один прекрасный момент решит протаранить бок центральной — ей потребуется 0,25 сек на весь маневр. Нет никакой возможности это предотвратить. Маневр в другую сторону невозможен — там другая машина, и при попытке совершить более резкий маневр ты достигнешь ее еще быстрее. Торможение происходит со скоростью до 10 м/с^2 — за 0,25 секунды разница составит пол корпуса — даже при идеальной реакции все равно попадут.
Это безотносительно машин с автопилотом.
Если кратко — со связностью нужно работать аккуратно и внимательно следить за ней.
Тут есть 2 аспекта — проблемы с EventBus и связность компонентов с EventBus компонентов с компонентами.
Зависимости:
— Сам по себе EventBus без сомнений станет зависимостью для всех, но это само по себе не большая проблема. Проблемой станет паразитные зависимости — если event bus будет связан с настройками/интерфейсами или конкретными сущностями (например, если его встраивают в главный контроллер игры). Он должен быть стабилен — синглтон с ленивой инициализацией, не ссылающйся ни на какие другие файлы.
— Если вы пишите переносимые компоненты — виджеты, компоненты рендера — не используйте EventBus. Используйте его в игровой логике.
— Не используйте EventBus с абстрактными или строковыми параметрами, используйте на интерфейсах или типах данных. Это защитит при переносах и переиспользовании компонент через зависимость на типы передаваемых сообщений/интерфейсы. Если вы завели тип/интерфейс в неймспейсе поставщика, все подписчики все равно получат явную зависимость на абстракцию от поставщика (его тип данных).
Но на самом деле это меньшие из проблем, самая важная проблема — это когда основной flow приложения неявным образом опирается на порядок вызовов в EventBus (который, по идее, обычно никак не гарантируется контрактом). Есть еще смежная проблема — когда в игре нельзя найти концов того, как игра пришла к такому состоянию (потому что ею управляла цепочка подписок).
Чтобы бороться с этими проблемами нужно ограничить использование EventBus:
— Пассивные реакции — компоненты, реагирующие на ивенты должны менять только свое состояние, но не состояние других компонентов.
— Низкоуровневые реакции — компоненты, реагирующие на ивенты, должны быть ниже по уровню абстракции. Условно, листья не должны шевелить деревом, дерево не должно управлять стартом игры (но наоборот — можно). Если у вас есть такое место, к примеру, рестарт игры завязан на упавшее здоровье игрока — возможно вы что-то делаете не так. Об этом же говорят проблемы с изменением списка подписчиков — скорее всего один из подписчиков слишком важная шишка и не должен быть просто подписчиком. Решайте это выделением специальных механизмов — к примеру, игрок должен иметь специальный колбек, который должен быть задан при его создании — тогда контроллер сущностей получает явную ручку для организации flow. А вот все остальные — интерфейсы здоровья, эффекты и т.д. — они подписываются на ивент изменения здоровья игрока.
— Изоляция. Если вы вынуждены написать логику, нарушающую первые 2 правила — выделите ее в отдельное место, которое об этом явно говорит. Например, ваши ГД хотят сами управлять условиями того, как завершается уровень, и хотят использовать для этого любой ивент, доступный им. Или стартующее новые миссии.
В этом случае это место станет точкой отказа, по логами и стактрейсу можно будет определить его как источник в случае ошибок, и в нем же можно будет разобраться с проблемами очередности и одновременности (к примеру, в этом компоненте можно будет организовать очередь сообщений, если могут быть выполнены сразу несколько условий с конфликтующими управляющими воздействиями)
Фантастика идет по пути «пиу пиу, дог файт как в фильмах про первую мировую»
Безусловно, добавление каждого нового фантастического элемента (гиперпрыжки/суперэффективные лазеры и т.д.) серьезно может изменить стратегию и тактику такого сражения, но оно все еще больше будет похоже на многодневное маневрирование, прицеливание и войну точности, машин и скоростей, а не лихой кавалерийский наскок.
И открытые кокпиты, космические истребители с пилотами внутри и прочие атрибуты Звездных войн никак не станут актуальнее даже со сравнениями.
Иначе можно определить расстояние до тебя и жахнуть с математически корректным упреждением, которое целиком совпадет с реальностью.
Нужно смотреть на вещи комплексно.
Ядерная энергия спасет мир.
Нужно отвечать на оба вопроса — и генерации и потребление.
Интерфейс был, просто очень простой и понятный.
Впрочем книга то как раз про это, претензия скорее к статье.
По проектированию пользовательского взаимодействия для начинающих могу еще порекомендовать «психбольница в руках пациентов»
В целом так и предполагал, но раньше как-то не задумывался.
Что характерно, пройти игру Я все же смог — был встроенный чит, позволяющий открыть 5/10/15/последний уровень, соответственно открывал уровень после и проходил.
Годы спустя прошел этот уровень на эмуляторе, и, как оказалось, непроходимым был реально только он — следующий за ним как раз был тем, который открывался читом.
Никак, только стандартный ROM?
Или есть эмуляторы для соответствующих доп механизмов?
Экзотические варианты есть, но каждый такой вариант должен быть в осознаным и вызывать вопрос — а нужно ли так делать, если это вызывает такие проблемы?
А главное — иногда ты пишешь скучно, а хак получается из-за ошибки. И вот тогда супер полезно обратить на него пристальное внимание.
И тут, как и с технологической сингулярностью, математический термин вполне корректный.
У вас есть функция, которую можно отследить (рост пространства в первом и количество технологических открытий во втором случае)
Если бы это была простая и понятная функция — можно было бы взять условную линейку и дорисовать прогноз (что зачастую и делается на простых участках). Но есть такая точка, которая делает кучу измерений до нее практически бесполезными — настолько сильно в ней меняются свойства функции.
Экспонента простой пример — рисуешь себе спокойненько, до какого то момента кажется, что ничего не меняется а тут бац — и линию некуда рисовать. И вроде бы график не закончился еще, понятно, что дальше что-то есть, но вот отобразить на листочке уже не получается.
Во первых, не все равно будет для личности оцифрованного человека в системе — у нее то как раз будет все зашибись, она будет видеть, что вот — тушка с оригиналом умирает, а вот он Я — живой, здоровый, бессмертный, красивый. И субъективно это все еще я. Для друзей и родственников это тоже все еще я. Профит. Копия просто воспринимается, как нечто типа подделки, мы не готовы признавать ее равноценность. И для картин это действительно так. А вот для файлов — не так.
Если так рассуждать, если ты воспринимаешь себя информацией, для тебя такой вариант доступен.
Можно построить это заключение еще и так. Ты сегодня — немного измененная копия себя вчера и совершенно не тот человек, который был три года назад (хотя и похож). И то, что ты по прежнему считаешь себя собой — только иллюзия, некоторое субъективное ощущение, основанное на непрерывности переносов и трансформаций.
Сознание в принципе иллюзия разума, субъективное ощущение, живущее в иллюзорном мире, к которому приводит мозг окружающую нас действительность.
Если для тебя и твоих друзей философски все нормально — у тебя нет проблем.
Во вторых, для слабых духом, которые не верят в такую философию, возможно будут доступны другие варианты. Тебе нейрон за нейроном заменяют мозг, ты в это время даже не теряешь сознание — ты продолжаешь думать, считать себя собой.
Результат аналогичный — ты думаешь целиком искусственным мозгом, теперь его, в отличие от мозга настоящего, можно выключить/включить, частично или полностью обсчитывать в симуляции, скопировать и вставить.
Воспоминания из фазы сна — это вроде просто интерпретация, она не связана с тем, что у личности новые свойства, она связана с тем, что ты так интерпретируешь местный бред.
Я, впрочем, тоже не уверен, что фраза «личность непрерывна» корректна
Ты можешь не помнить не строчки синтаксиса, но само ощущение «Я очень похожее уже решал, есть стандартное решение и какой то хитрый хак» позволит тебе быстрее нарыть эту штуку, чем просто «надо погуглить»