Диссертация (1149786), страница 15
Текст из файла (страница 15)
В первом случае нашкласс по необходимости генерирует очередную порцию вершин или ребер, а вовтором случае логически разбивает множество еще не обработанных элементовна конечное подмножество, обрабатываемое в первую очередь и бесконечносчетный остаток. При необходимости параллельной обработки этих двух подмножеств из второго снова будет выделено конечное подмножество.package org.ivg;importimportimportimportimportjava.util.Arrays;java.util.HashMap;java.util.List;java.util.Map;java.util.stream.Stream;public class InfiniteAreaDivisionimplements ISimplicialDivision {static final int RANGE = 28;static final Map<ISimplex, List<ISimplex>> pregenAdjList;static {pregenAdjList = new HashMap<>();for (int x = -RANGE; x <= RANGE; x += 2) {for (int y = -RANGE; y <= RANGE; y += 2) {Point2D p0 = new Point2D(x - 1, y + 1);Point2D p1 = new Point2D(x, y);Point2D p2 = new Point2D(x + 1, y - 1);Point2D p3 = new Point2D(x, y + 2);Point2D p4 = new Point2D(x + 1, y + 1);Point2D p5 = new Point2D(x + 2, y);Point2D p6 = new Point2D(x + 1, y + 3);Point2D p7 = new Point2D(x + 2, y + 2);Point2D p8 = new Point2D(x + 3, y + 1);Simplex2D t0 = new Simplex2D(p0, p1, p3);Simplex2D t1 = new Simplex2D(p1, p4, p3);Simplex2D t2 = new Simplex2D(p1, p5, p4);Simplex2D t3 = new Simplex2D(p1, p2, p5);96Simplex2D t4 = new Simplex2D(p3, p7,Simplex2D t5 = new Simplex2D(p3, p4,Simplex2D t6 = new Simplex2D(p4, p5,Simplex2D t7 = new Simplex2D(p5, p8,pregenAdjList.put(t1,Arrays.asList(t0, t2, t5));pregenAdjList.put(t2,Arrays.asList(t1, t3, t6));pregenAdjList.put(t6,Arrays.asList(t2, t7, t5));pregenAdjList.put(t5,Arrays.asList(t1, t6, t4));p6);p7);p7);p7);}}}@Overridepublic Stream<IPoint> vertices() {return pregenAdjList.keySet().stream().flatMap(t -> t.vertices()).distinct();}@Overridepublic Stream<IEdge> edges() {return pregenAdjList.keySet().stream().flatMap(t -> t.edges()).distinct();}@Overridepublic Stream<ISimplex> simplices() {return pregenAdjList.keySet().stream();}@Overridepublic Stream<ISimplex> adjacent(ISimplex simplex) {List<ISimplex> adj = pregenAdjList.get(simplex);return (adj == null)? Stream.<ISimplex>empty()97: adj.stream();}}Приведенный класс InfiniteAreaDivision может быть реализован так,чтобы создавать данные «на лету».
В модельном приложении, для простоты,и ввиду отсутствия простого способа ограничить генерацию данных, создаетсяпредрасчитанная порция, которая выдается по запросу через соответствующиеметоды.4.4Ограничение потока данныхКласс InfiniteAreaDivision спроектирован так, чтобы являться универсальным источником виртуально-бесконечного потока данных для задания симплициального подразделения специального вида. Среда исполнения может черпатьиз него данные до тех пор, пока не сработает условие, по которому запросык источнику-генератору прекратятся. Простейшим вариантом такого ограничения является задание конечного параллелепипеда, ограничивающего симплициально-подразделенную область.
Следующий класс, BoxedAreaDivision, реализует ограничение такого рода.package org.ivg;import java.util.Arrays;import java.util.Objects;import java.util.stream.Stream;public class BoxedAreaDivisionimplements ISimplicialDivision {ISimplicialDivision source;int[] minCoords;int[] maxCoords;public BoxedAreaDivision(ISimplicialDivision source,int[] minCoords,int[] maxCoords) {Objects.requireNonNull(source);98Objects.requireNonNull(minCoords);Objects.requireNonNull(maxCoords);if (minCoords.length < 1 ||minCoords.length != maxCoords.length) {throw new IllegalArgumentException();}this.source = source;this.minCoords = minCoords.clone();this.maxCoords = maxCoords.clone();}private static int[] populateArray(int size, int val) {int[] result = new int[size];Arrays.fill(result, val);return result;}public BoxedAreaDivision(ISimplicialDivision source,int dim, int absRange) {this(source, populateArray(dim, -Math.abs(absRange)),populateArray(dim, Math.abs(absRange)));}private boolean inBox(IPoint point) {final int dim = point.dimensions();if (dim != maxCoords.length) {throw new IndexOutOfBoundsException("Wrong " +"number of dimensions " + dim);}for (int i = 0; i < dim; ++i) {int crd = point.coordinate(i);if (crd < minCoords[i] || crd > maxCoords[i]) {return false;}}return true;}@Overridepublic Stream<IPoint> vertices() {return source.vertices().filter(this::inBox);}99@Overridepublic Stream<IEdge> edges() {return source.edges().filter(edge ->edge.allPointsCond(this::inBox));}@Overridepublic Stream<ISimplex> simplices() {return source.simplices().filter(simplex ->simplex.allPointsCond(this::inBox));}@Overridepublic Stream<ISimplex> adjacent(ISimplex simplex) {return source.adjacent(simplex);}}Класс BoxedAreaDivision предоставляет конструкторы, позволяющие задать либо произвольный параллелепипед, либо параллелепипед имеющий одинаковые размеры по всем осям с центром около начала координат.
В обоихслучаях конструктору требуется указать источник, из которого будут получены данные, подвергающиеся фильтрации. В качестве источника допустимо использовать либо виртуально-бесконечный входной поток, который предоставляет, например, класс InfiniteAreaDivision, либо любой другой реализующийбазовый интерфейс ISimplicialDivision.Приводимая реализация класса поддерживает только работу с симплициальными подразделениями дву- и трехмерных областей, но легко может бытьрасширена на случай большего числа измерений.4.5Укрупнение подразделенияДля более точного указания областей, в которых требуется произвести укрупнение симплициального подразделения необходимо иметь возможность гибкогомеханизма отсева вершин и ребер симплициального подразделения.
Указанную100функциональность можно обеспечить, предоставив интерфейс, в который передается произвольный, определяемый пользователем предикат, значения которого зависят от точки, как от аргумента.Ниже приводится класс ConditionedSubAreaDivision, обладающий необходимым свойством.
Для конструирования объекта этого класса необходимоуказать входной источник данных. Также как и другие классы, ограничивающие симплициально-подразделенную область, его можно использовать либос виртуально-бесконечным либо с ограниченным источником, а также, возможно, с источником уже подвергнутым процедуре укрупнения симплициальногоподразделения.package org.ivg;import java.util.Objects;import java.util.function.Predicate;import java.util.stream.Stream;public class ConditionedSubAreaDivisionimplements ISimplicialDivision {private ISimplicialDivision source;private Predicate<? super IPoint> condition;public ConditionedSubAreaDivision(ISimplicialDivisionsource, Predicate<? super IPoint> condition) {Objects.requireNonNull(source);Objects.requireNonNull(condition);this.source = source;this.condition = condition;}private Stream<ISimplex> coarse(ISimplex simplex) {if (simplex instanceof Simplex2D) {Predicate<ISimplex> sCond =s -> s.allPointsCondition(condition);if (!sCond.test(simplex)) {return Stream.of(simplex);}Predicate<ISimplex> sCondAndType2 = sCond101.and(Simplex2D::ofType2);Predicate<ISimplex> sCondAndType4 = sCond.and(Simplex2D::ofType4);Predicate<ISimplex> sCondAndType6 = sCond.and(Simplex2D::ofType6);Predicate<ISimplex> sCondAndType8 = sCond.and(Simplex2D::ofType8);Predicate<ISimplex> sCondOrNotType2 = sCond.negate().and(Simplex2D::ofType2).negate();Predicate<ISimplex> sCondOrNotType4 = sCond.negate().and(Simplex2D::ofType4).negate();Predicate<ISimplex> sCondOrNotType6 = sCond.negate().and(Simplex2D::ofType6).negate();Predicate<ISimplex> sCondOrNotType8 = sCond.negate().and(Simplex2D::ofType8).negate();Simplex2D simplex2D = (Simplex2D)simplex;if (Simplex2D.ofType1(simplex2D) &&source.adjacent(simplex2D).anyMatch(sCondAndType2) &&source.adjacent(simplex).allMatch(sCondOrNotType4)) {simplex2D = simplex2D.toType1_2();} else if (Simplex2D.ofType2(simplex2D)) {return Stream.<ISimplex>empty();} else if (Simplex2D.ofType3(simplex2D) &&source.adjacent(simplex2D).anyMatch(sCondAndType4) &&source.adjacent(simplex).allMatch(sCondOrNotType2)) {simplex2D = simplex2D.toType3_4();} else if (Simplex2D.ofType4(simplex2D)) {return Stream.<ISimplex>empty();} else if (Simplex2D.ofType5(simplex2D) &&source.adjacent(simplex2D).anyMatch(sCondAndType6) &&source.adjacent(simplex).allMatch(sCondOrNotType8)) {simplex2D = simplex2D.toType5_6();} else if (Simplex2D.ofType6(simplex2D)) {return Stream.<ISimplex>empty();} else if (Simplex2D.ofType7(simplex2D) &&source.adjacent(simplex2D)102.anyMatch(sCondAndType8) &&source.adjacent(simplex).allMatch(sCondOrNotType6)) {simplex2D = simplex2D.toType7_8();} else if (Simplex2D.ofType8(simplex2D)) {return Stream.<ISimplex>empty();}return Stream.<ISimplex>of(simplex2D);}return Stream.<ISimplex>empty();}@Overridepublic Stream<IPoint> vertices() {return source.simplices().flatMap(this::coarse).flatMap(ISimplex::vertices).distinct();}@Overridepublic Stream<IEdge> edges() {return source.simplices().flatMap(this::coarse).flatMap(ISimplex::edges).distinct();}@Overridepublic Stream<ISimplex> simplices() {return source.simplices().flatMap(this::coarse);}@Overridepublic Stream<ISimplex> adjacent(ISimplex simplex) {return source.adjacent(simplex);}}1034.6Приложение с графическим пользовательскиминтерфейсомДля возможности демонстрации работы с реализованной компьютерной моделью, представляется приложение, использующее графический пользовательский интерфейс.
Главная форма приложения содержит три области: областьграфического отображения симплициального подразделения, область для инструментов настройки параметров разбиения, укрупнения и графического отображения, и область вывода отладочной информации, сообщений об использовании недопустимых значений параметров и статистики.Рис. 17: Внешний вид компьютерного приложенияОбласть графического отображения симплициального подразделения служит для наглядного просмотра результата исходного подразделения, а такжерезультатов укрупнения. При моделировании симплициального подразделениятрехмерной области отображается проекция результата на плоскость X–Y .В области настроек, пользователю позволяется произвести следующие варианты выбора.
Двухмерная триангуляция или трехмерное симплициальноеподразделение. Для симплициального подразделения можно выбрать используемый метод определения разбиения призм на симплексы: (O1 ) или (O2 ) (см.104раздел 2.2). Если выбран метод (O1 ), пользователю позволяется указать используемые оси l1 и l2 . Если выбран метод (O2 ), предоставляется возможностьуказать ось lx . Для возможности задания произвольного условия определенияобласти, в которой следует произвести укрупнение симплициального подразделения, на панели настроек располагается поле для ввода, в которое можноввести код произвольного предиката, сформулированного в виде Java-кода, зависящего, как от аргумента, от тестируемой точки.Область вывода отладочной информации используется для предоставления пользователю сообщений о неверно заданных параметрах, (например,линейно-зависимых осях l1 и l2 ), и других возможных ошибках, таких как ошибки времени компиляции или исполнения предиката задаваемого пользователем.105ЗаключениеВопросы, рассмотренные в данной работе лежат в русле все увеличивающегося потока задач, связанных с вейвлетным анализом функций, заданных надвух- и трехмерных областях.
Особенно важным представляется применениерассматриваемых методов к большим и насыщенным потокам данных, для которых потребность сжатия за счет выделения важных составляющих труднопереоценить.Многие важные в теоретической и прикладной математике задачи приводят к необходимости рассмотрения подразделения некоторой области в эвклидовом пространстве на непересекающиеся элементы. В число таких задачвходит аппроксимация функций, заданных на конечных областях в Rn . Типичным вариантом подразделения конечной области в эвклидовом пространстве является задание правильного симплициального подразделения, т.
е. такого, что никакая вершина ни одного образующего подразделение симплекса, неможет оказаться во внутренней точке одномерного ребра другого симплекса.Симплициальное подразделение областей пространства R2 представляет собойтриангуляцию. При компьютерной обработке информационных потоков насущной потребностью является возможное уменьшение объема пересылаемых и обрабатываемых данных. Применительно к методам, использующим симплициальное подразделение, эта необходимость приводит к задаче локального укрупнения подразделения. В одномерном случае, локальное укрупнение подразделения осуществляется тривиальным образом, простым выбрасыванием лишнихузлов.