Позволяет ли ms excel строить трехмерные поверхности

Обновлено: 28.06.2024

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

Чем это статья будет отличаться от предыдущих? В ней будет мало кода. В основном теория и разбор алгоритмов. Я понимаю, что алгоритм не идеальный, но мне интересно услышать какое-нибудь мнение, а еще лучше — совет. Тем более, что у меня есть пара вопросов.

Еще в процессе написания предыдущей статьи у меня возникли идеи по совершенствованию графического движка а-ля Wolfenstein 3D. Ведь одинаковые квадратные стены — это скучно.

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

Да, это фото! На телефон. В 2020 году. Но другого выхода нет из-за строгой политики безопасности.

Но перейдем к новой версии рейкастера, который позволяет рисовать произвольные стены в пространстве.

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

В основе нового движка лежит стандартный рейкастер, который направляет многочисленные лучи в направлении взгляда игрока. Лучи встречают стены, расстояния до стен записываются в массив, и программа рисует эти стены на экране.

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

Для начала нужно нарисовать карту уровня. Со временем я планирую использовать для этого Blender, а координаты точек будут браться из. obj файла. Но сейчас я нарисую ее на бумаге. Мне кажется, так будет более наглядно.

Перенесем координаты отрезков на отдельный лист в порядке X1, Y1, X2, Y2

В первой версии движка каждую итерацию луч проверял столкновение со всеми имеющимися отрезками. Не трудно предположить, что это закончилось полным провалом. Процесс отрисовки изображения занимал несколько минут. Сейчас карта состоит из 35 отрезков. А если бы она состояла из тысячи? Согласитесь, это выглядит более правдоподобно в формате компьютерных игр. Катастрофа.

Тогда я решил разбить все имеющиеся отрезки на сегменты в зависимости от секторов, в которых лежит отрезок. К примеру, размер одного сектора будет равен 8Х8 пунктов.

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

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

Для прохода по координатам отрезка я использовал следующую формулу:

X(Y) = X1(Y1) * (1 — STEP) + X2(Y2) * STEP,

где STEP — коэффициент, который определяет длину одного шага между координатами отрезка.

Каждую итерацию программа проверяет каждую точку отрезка. Если две точки находятся в разных секторах, то первый сегмент отрезка отправляется в коллекцию, а программа продолжает поиск следующего сектора.

Код получился слишком длинным, поэтому выкладывать его в чистом виде не очень оправданно. В конце статьи я приложу Excel файл, в котором можно будет лицезреть все своими глазами (модуль Editor).

Второй этап — создание двумерного массива с булевыми значениями, которые символизируют собой пустые и заполненные сектора.

Я не могу сказать, что программа написана чисто. Пришлось прибегать к разным костылям, чтобы отрезки формировались как надо и программа не плодила лишние сегменты (принудительное изменения номера сектора или оптимизация положения координат перед началом работы программы).

Наконец, полученные значения направляются на отдельный лист в порядке: X1, Y1, X2, Y2, Сектор по оси X, Сектор по оси Y. Рядом выводятся данные из массива с наполнением секторов. Получается следующее:

Теперь карта состоит аж из 201 отрезка, но разбиение на секторы позволит программе работать быстрее.

На этом формирование данных уровня закончено. По крайней мере сейчас, когда нет ни дверей, ни активных стен, ни предметов, ни врагов etc.

Когда луч оказывается в заполненном секторе (сверяет свое местоположение с картой секторов), он начинает искать столкновения с отрезками.

Для того, чтобы решить эту задачу, пришлось вспомнить, что такое вектор и какие действия с ним можно производить. В этом мне помогла следующая серия статей: Часть 1, Часть 2.

В этих статьях все описано достаточно подробно, поэтому я не буду приводить краткий курс геометрии, а объясню все в двух словах.

Для начала нужно создать два вектора от точки луча к начальным и конечным точкам каждого отрезка в секторе. Далее, посчитать скалярное и псевдоскаларное произведения этих двух векторов. Если скалярное произведение <= 0 и псевдоскалярное произведение == 0, то это значит, что точка лежит на отрезке.

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

Для поиска столкновений создал два класса. Класс Vector, который содержит два поля X, Y, а также метод, который создаёт вектор.

Option Explicit Public X As Variant, Y As Variant Sub createVector(X1 As Variant, Y1 As Variant, X2 As Variant, Y2 As Variant) X = X2 - X1 Y = Y2 - Y1 End Sub

А также класс VectorActions, который считает произведения векторов:

Option Explicit Public Vector1 As New Vector, Vector2 As New Vector 'скалярное произведение векторов Public Function getScalarProd() As Variant getScalarProd = Vector1.X * Vector2.X + Vector1.Y * Vector2.Y End Function 'косое произведение векторов Public Function getCrossProd() As Variant getCrossProd = Vector1.X * Vector2.Y - Vector2.X * Vector1.Y End Function

Я слышал мнение, что классы в VBA работают медленно, и лучше использовать обычное процедурное программирование. Но код писать действительно удобнее.

Сперва необходимо инициализировать некоторые переменные, которые понадобятся для рендеринга. Для этого я создал два класса: Config и Game. В модуле Main надо прописать такой код:

Option Explicit Public Const ED = "EDITOR" Public Const M = "MAP" Public Const CONF = "CONFIG" Public Const REND = "RENDER" Public Config As New Game, Elf As New Player Sub initializeVariables() 'настройка конфигурации Config.MapNumber = Sheets(CONF).Range("B10") Config.rayLength = Sheets(CONF).Range("B9") Config.RayStep = Sheets(CONF).Range("B8") Config.ScreenHeight = Sheets(CONF).Range("B1") Config.ScreenWidth = Sheets(CONF).Range("B2") Config.SectorHeight = Sheets(CONF).Range("B7") 'Настройка игрового экрана Set Config.renderField = Sheets(REND).Range(Sheets(REND).Cells(2, 2), _ Sheets(REND).Cells(Config.ScreenHeight + 1, Config.ScreenWidth + 1)) 'настройка карты Set Config.Map = Usefull.getRangeFromSheet(M & Config.MapNumber, 1, 1) Set Config.Sectors = Usefull.getRangeFromSheet(M & Config.MapNumber, 1, 8) 'настройка игрока Elf.FOV = Sheets(CONF).Range("B6") Elf.POV = Sheets(CONF).Range("B5") Elf.X = Sheets(CONF).Range("B3") Elf.Y = Sheets(CONF).Range("B4") End Sub

Все данные берутся с отдельного листа:

Процедура, которая пускает лучи, практически идентична той, что была в прошлой статье, за тем исключением, что теперь луч проверяет сектора.

'ядро рейкастинга Public Sub getRenderArray() Dim countRays As Integer, rayPOV As Single, rayDist As Single, rayX As Single, rayY As Single, _ sectorX As Integer, sectorY As Integer, arrEmpty() As Variant, arrRender() As Variant, iSeg As Integer On Error Resume Next arrEmpty() = Config.Sectors.Value ReDim arrRender(1, Config.ScreenWidth) For countRays = 1 To Config.ScreenWidth - 1 rayPOV = (Elf.POV - Elf.FOV / 2) + (countRays * (Elf.FOV / Config.ScreenWidth)) For rayDist = Config.RayStep To Config.rayLength Step Config.RayStep rayX = Elf.X + rayDist * Cos(rayPOV) rayY = Elf.Y + rayDist * Sin(rayPOV) sectorX = Fix(rayX / Config.SectorHeight) + 1 sectorY = Fix(rayY / Config.SectorHeight) + 1 'проверка, в каком секторе находится луч If arrEmpty(sectorY, sectorX) = True Then 'проверка на столкновения iSeg = getIntersect(rayX, rayY, sectorX - 1, sectorY - 1) If iSeg > 0 Then arrRender(0, countRays - 1) = iSeg arrRender(1, countRays - 1) = Application.WorksheetFunction.RoundDown((Config.ScreenHeight * 24 / rayDist / Cos(Elf.POV - rayPOV)), 0) Exit For End If End If Next Next Render.createImage arrRender() End Sub

Следующая процедура проверяет столкновения точки с отрезками:

'проверка на столкновение с отрезками Private Function getIntersect(rayX As Single, rayY As Single, sectorX As Integer, sectorY As Integer) As Long Dim Vector1 As New Vector, Vector2 As New Vector, VectorAct As New VectorActions, arrSegs() As Variant, _ countSegs As Integer, X1 As Single, X2 As Single, Y1 As Single, Y2 As Single, scalarProd As Single, crossProd As Single arrSegs() = Config.Map.Value For countSegs = 1 To UBound(arrSegs(), 1) If arrSegs(countSegs, 5) = sectorX And arrSegs(countSegs, 6) = sectorY Then X1 = arrSegs(countSegs, 1) Y1 = arrSegs(countSegs, 2) X2 = arrSegs(countSegs, 3) Y2 = arrSegs(countSegs, 4) Vector1.createVector rayX, rayY, X1, Y1 Vector2.createVector rayX, rayY, X2, Y2 Set VectorAct.Vector1 = Vector1 Set VectorAct.Vector2 = Vector2 scalarProd = VectorAct.getScalarProd crossProd = VectorAct.getCrossProd If scalarProd <= 0 And (crossProd > -1 And crossProd < 1) Then getIntersect = countSegs Exit Function End If End If Next End Function

Функция возвращает целочисленное значение (номер отрезка в массиве), которое определяет цвет стены при рендеринге.

Пришлось перенести карту с бумаги в Doom Builder (очень странные манипуляции), чтобы показать итоги.

Ради интереса я установил разрешение 800Х600:

Да, этот движок генерирует какое-то псевдотрехмерное изображение. Но имеются и проблемы.

Во-первых, даже со всеми улучшениями, изображение в разрешении 96Х128 отрисовывается от одной до пяти секунд. Это непозволительного для алгоритма, который должен работать моментально.

Во-вторых, луч иногда вообще не видит отрезки на их стыках. Как будто проходит сквозь них. На изображении это прекрасно заметно по дыркам в стенах. Это не частое явление, но проблема все таки имеется. Поэтому если кто-нибудь сможет мне пояснить, с чем это связано, я буду очень рад. Себе я сломал уже всю голову.

В настоящее время, когда луч встречает пустой сектор, он не пропускает его, а просто движется дальше и каждую итерацию проверяет один и тот же сектор. Для того, чтобы этого избежать, я пишу алгоритм, который будет вообще пропускать пустые сектора. Это значительно сократит количество итераций. Для этого необходимо высчитывать тангенс или котангенс угла между лучом и проекцией на ось X или Y. Когда-нибудь я напишу и об этом. Опять же, если кто-нибудь посоветует еще какие-нибудь способы сделать работу алгоритма быстрее, пишите.

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


3D-график в Excel используется для построения графика для тех наборов данных, которые могут не обеспечивать особой видимости, возможности сравнения с другими наборами данных и для построения графика области, когда у нас есть большие наборы точек данных. 3D Plot в Excel - это творческий способ превратить простой 2D-график в 3D.

Как построить 3D-графики в Excel?

Построение 3D-графиков в Excel очень просто и полезно, когда мы хотим преобразовать данные, круговые диаграммы, графики в 3D-формат. Давайте разберемся, как строить 3D-графики в Excel на нескольких примерах.

Вы можете скачать этот 3D-шаблон Excel Plot здесь - 3D-шаблон Excel Plot

Доступ к 3D-графику можно получить из меню « Вставка» в разделе «Графики ».


3D-график в Excel - Пример № 1

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


Теперь создаем 3D-график для вышеуказанного набора данных, сначала выберите данные.

Затем перейдите на вкладку меню Вставка и под диаграммой выберите столбчатую диаграмму. Как только мы нажмем на него, мы получим раскрывающееся меню. Оттуда выберите 3D-столбец, как показано ниже.


После выбора опции 3D Column мы получим трехмерный график с колонкой, как показано ниже. Здесь мы можем добавить метки данных, заголовки осей, заголовок и даже изменить дизайн 3D-столбцов.


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

Давайте снова отобразим эти данные на другом трехмерном графике. Теперь мы будем строить 3D-график. Для этого сначала выберите данные, а затем перейдите на вкладку меню « Вставка », в разделе «Диаграммы» выберите « Водопад», «Фондовая», «Поверхность» или «Радар», как показано ниже. (И для других версий Excel выберите опцию Other Charts )


Как только мы это сделаем, мы получим выпадающее меню диаграммы Stok, Surface и Radar, как показано ниже. Оттуда выберите 3D Surface .


Как только мы это сделаем, мы получим 3D-график поверхности, как показано ниже.


Приведенные выше данные показывают расстояние, пройденное атлетами по гребню и впадине, а область разного цвета представляет диапазон расстояний. Таким образом, мы можем попробовать еще несколько 3D-графиков, доступных в Excel, в соответствии с нашим использованием.

3D-график в Excel - Пример № 2

Давайте рассмотрим, что данные высоты поверхности от некоторых определенных точек и высоты измеряются в каждом 10-метровом промежутке. Где-то есть огромный всплеск высоты поверхности, а в других - это огромное падение. Данные приведены ниже.


Теперь для построения трехмерного графика для приведенного выше примера сначала выберите полные данные. Затем перейдите в меню «Вставка» и в разделе «Графики» выберите столбчатую диаграмму, как показано ниже. Как только мы нажмем на него, мы получим раскрывающееся меню. Оттуда выберите 3D-столбец, как показано ниже.


После выбора опции 3D Column мы получим трехмерный график с колонкой, как показано ниже.


Как мы видим, здесь есть несколько огромных башен и несколько плоских блоков. Построение данных такого рода в трехмерных диаграммах дает возможность увидеть, где в процессе наблюдаются пики и спады. Мы можем добавить метки данных здесь.

Давайте построим еще один 3D-график на тех же данных. Для этого выберите данные и перейдите в меню «Вставка», в разделе «Диаграммы» выберите « Линия» или « Диаграмма площади», как показано ниже.


После этого мы получим выпадающий список линейных графиков, как показано ниже. Оттуда выберите 3D Line chart.


После нажатия на него мы получим график графика 3D Line, как показано ниже.


Это самый выполнимый, простой 3D-сюжет. И это очень легко понять. Поскольку данные в этом сюжете достаточно разделены друг с другом. И изменения в данных также хорошо видны. Использование графика 3D Line хорошо, когда у нас есть данные, где мы можем легко увидеть разделение.

Выше приведен пример некоторых из категории 3D-графики. Мы можем создать трехмерный график для круговой диаграммы, диаграммы площади, линейчатой ​​диаграммы и комбинированной диаграммы, если имеющиеся у нас данные позволяют нам по-разному представлять требуемые виды.

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

Плюсы 3D-сюжета в Excel

  • Даже данные являются презентабельными, но при использовании трехмерного графика видимость становится шире, когда данные имеют размеры.
  • Модификация, выполненная в бэкэнде, может быть легко обновлена ​​с помощью этих трехмерных графиков или простых графиков.
  • Когда у нас есть данные о высоте поверхности, мы также можем построить контурные графики.

То, что нужно запомнить

  • Не всегда необходимо строить трехмерный график в Excel, когда у нас простая структура данных.
  • При вставке графика в разные файлы всегда вставляйте изображение, чтобы избежать каких-либо изменений в конечном графике.
  • Данные должны быть в правильном формате, чтобы любые изменения, которые необходимо внести в график, можно было легко сделать.
  • Не добавляйте метки данных в 3D-графики, потому что график много раз перегружен. Используйте метки данных, когда они действительно видны.

Рекомендуемые статьи

Это было руководство по 3D Plot в Excel. Здесь мы обсудили, как построить 3D-графики в Excel вместе с практическими примерами и загружаемым шаблоном Excel. Вы также можете просмотреть наши другие предлагаемые статьи -

Как вам, очевидно, известно, одной из основных задач, решаемых с помощью программы Microsoft Excel, является построение диаграмм и графиков (наряду с решением расчетных задач, в которых информация представлена в виде таблицы). А можно ли построить в Microsoft Excel трехмерное изображение? Например, поверхность, называемую “параболоидом вращения” (ее вид показан на рис. 1)?

Нет ничего проще! Но прежде чем рассказывать о том, как это сделать, надо немного поговорить о так называемых функциях двух переменных. Такая функция имеет вид z = f(x, y), где x и y — координаты точки на плоскости 1 , а z — значение функции. Например, функция, изображенная на рис. 1, записывается так: f(x, y) = x 2 + y 2 .

Определим интервалы, в которых будут изменяться значения аргументов x и y. Пусть это будет симметричный интервал (–5, 5) для x и другой симметричный интервал (–9, 9) для y. Шаг, с которым будут изменяться значения x и y, установим равным 0,2. Вообще говоря, выбор величины шага определяется исходя из требуемой “подробности” построения графика. Теперь на рабочем листе Excel зададим значения этих координат в виде строки B1:AZ1 для x и столбца A2:A92 для y (см. рис. 2, на котором показано начало этой таблицы).

Теперь введем в ячейку B2 формулу. Необходимо предварительно продумать адресацию ячеек, ведь этой формулой мы потом заполним весь диапазон B2:AZ92. Кстати, если у вас компьютер не слишком мощный, то диапазон следовало бы уменьшить, так как в нем помещается ни много ни мало 4641 ячейка. При небольшой производительности и памяти машины этот объем данных может для нее составить значительную сложность.

Итак, формула. При заполнении интервала по горизонтали (оси x) формулы во всех ячейках должны ссылаться на соответствующую ячейку верхнего ряда, следовательно, она должна иметь абсолютную адресацию по номеру строки, а по номеру столбца — относительную адресацию. Напомню, что абсолютная адресация обозначается знаком “$” перед соответствующей координатой адреса ячейки. В нашем случае адресация выглядит так: B$1. Что касается y, то здесь наоборот: абсолютным должен быть номер столбца, а номер строки — относительным, т.е. адрес имеет вид: $A2. Теперь соберем всю формулу. Чтобы не использовать дополнительных функций, в квадрат будем возводить просто умножением: =B$1*B$1+$A2*$A2. Этой формулой можно теперь заполнить весь прямоугольник от B2 до AZ92. Исходный массив данных готов. На рис. 3 — начало получившейся таблицы.

Теперь можно строить диаграмму. Вызываем Мастер диаграмм. Для построения трехмерных картинок надо выбрать тип диаграммы — Поверхность, а вид — тот, который программа предлагает по умолчанию — . Если у вас Excel последних версий, то все уже готово (Мастер диаграмм сам выберет участок таблицы, из которого надо брать данные, и построит диаграмму), а если более старый — то надо указать интервал данных (весь интервал A1:AZ92). Остается только усовершенствовать оформление диаграммы, в частности, если хотите получить более тонкие полосы, то надо выбрать вертикальную ось (по терминологии Excel — ось значений) и задать цену основных делений. На рис. 1 она равна 20, а на рис. 4–5. Видно, что проработка улучшилась.

В качестве упражнения попробуйте построить “седло” (z = x 2 – y 2 ) или такую поверхность, как на рис. 5 (z = sin(x + y) / (x + y)).

Как вам, очевидно, известно, одной из основных задач, решаемых с помощью программы Microsoft Excel, является построение диаграмм и графиков (наряду с решением расчетных задач, в которых информация представлена в виде таблицы). А так же можно построить в Microsoft Excel трехмерное изображение. Например, поверхность, называемую “параболоидом вращения” (ее вид показан на рис. 28).

Рис. 28. Поверхность “параболоид вращения”

Но прежде чем рассказывать о том, как это сделать, надо немного поговорить о так называемых функциях двух переменных. Такая функция имеет вид z = f(x, y), где x и y — координаты точки на плоскости 1 , а z — значение функции.

Определим интервалы, в которых будут изменяться значения аргументов x и y. Пусть это будет симметричный интервал (–5, 5) для x и другой симметричный интервал (–9, 9) для y. Шаг, с которым будут изменяться значения x и y, установим равным 0,2. Теперь на рабочем листе Excel зададим значения этих координат в виде строки B1:AZ1 для x и столбца A2:A92 для y (рис. 29, на котором показано начало этой таблицы).

Рис. 29. Задаем интервал

Теперь введем в ячейку B2 формулу. Необходимо предварительно продумать адресацию ячеек, ведь этой формулой мы потом заполним весь диапазон B2:AZ92. При заполнении интервала по горизонтали (оси x) формулы во всех ячейках должны ссылаться на соответствующую ячейку верхнего ряда, следовательно, она должна иметь абсолютную адресацию по номеру строки, а по номеру столбца — относительную адресацию.

Абсолютная адресация обозначается знаком “$” перед соответствующей координатой адреса ячейки. В нашем случае адресация выглядит так: B$1. Что касается y, то здесь наоборот: абсолютным должен быть номер столбца, а номер строки — относительным, т.е. адрес имеет вид: $A2. Теперь соберем всю формулу. Чтобы не использовать дополнительных функций, в квадрат будем возводить просто умножением: =B$1*B$1+$A2*$A2. Этой формулой можно теперь заполнить весь прямоугольник от B2 до AZ92. Исходный массив данных готов.

Рис. 30. Интервалы

На рис. 30 — начало получившейся таблицы. Теперь можно строить диаграмму. Вызываем Мастер диаграмм. Для построения трехмерных картинок надо выбрать тип диаграммы — Поверхность, а вид — тот, который программа предлагает по умолчанию — .

Если у вас Excel последних версий, то все уже готово (Мастер диаграммсам выберет участок таблицы, из которого надо брать данные, и построит диаграмму), а если более старый — то надо указать интервал данных (весь интервал A1:AZ92). Остается только усовершенствовать оформление диаграммы, в частности, если хотите получить более тонкие полосы, то надо выбрать вертикальную ось (по терминологии Excel — ось значений) и задать цену основных делений. На рис. 28 она равна 20, а на рис. 31 видно, что проработка улучшилась.

Читайте также: