Продвинутое рисование в табличном документе (стрелок и не только)




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

26 Comments

  1. SlavaKron

    Неплохо. Следующий шаг нарисовать каркас 3д модели в центральной проекции.

    Reply
  2. 🅵🅾️🆇

    Идея для следующей публикации:

    gif файл это по сути пару маркеров в начале, а затем массив точек.

    Собрать белое полотно — пару строчкек кода из цикла и двоичных данных.

    Ну а дальше вы художник)

    Reply
  3. pm74

    Браво. Я всегда говорю, что здоровая конкуренция — двигатель прогресса. За безье отдельное спасибо

    Reply
  4. Dmitri_1C

    Выше всяких похвал.

    Однозначно +.

    Reply
  5. Неопределено

    Теперь можно написать код, рисующий мультик. И почему я не сомневался, что эта публикация появится в ближайшее время?

    Reply
  6. it@contlog.ru

    Замечательно, если пойти далее можно так выводить файлы SVG

    Reply
  7. Antonov.AV

    + Следующий шаг анимация

    Reply
  8. HAMMER_59

    Какие-то не типичные основы компьютерной графики. Насколько я помню из курса компьютерной графики, да и в документации по DirectX то же самое. Все начинается с рассмотрение поворота точки. Начальная точка А имеет координаты.

    x = l * cos(a)

    y = l * sin(а)

    После поворота на угол бэта (b), получаем новые координаты

    x = l * cos(a + b)

    y = l * sin(a + b)

    cos(a + b) = cos(a) * cos(b) — sin(a) * sin(b)

    sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b)

    А вот после этого уже подгоняется под умножение матриц.

    Далее из матриц берем A * B * C * D = A * (B * C * D)

    Для перемещения и масштабирования матрицу увеличивают до 3 х 3

    Reply
  9. Cерый

    Отлично!

    Полагаю, следующий шаг — рисование в трехмерии, диаграммы в 1С до уровня Crystal Reports …

    Reply
  10. WalterMort

    (8) В документации по DirectX для вращения также используются матрицы, постоянно вычислять косинус и синус это дорогое удовольствие.

    https://docs.microsoft.com/ru-ru/windows/uwp/gaming/working-with-2d-graphics-in-your-directx-game

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

    Reply
  11. HAMMER_59

    Как же сложно стало отыскать нормальную документацию по основам 3Д графики. Насчет DirectX, читать надо не галопом по европам, а DirectX SDK, когда еще был 7 DirectX теория по 3D графике занимала порядка тысячи страниц, сейчас думаю поболее будет.

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

    Учебное пособие по компьютерной графике

    А в статье, как рисование совы через геометрические фигуры:

    Шаг1: Рисуем круг;

    Шаг2: Рисуем овал;

    Шаг3: Дорисовываем все остальное

    Reply
  12. WalterMort

    (12) Ну что же. Тогда вам стоит последовать моему примеру и написать свою публикацию на эту тему.

    Reply
  13. WalterMort

    Кстати о 3D, почему бы и нет. Нужно же до конца разобраться в кватернионах. Жалко, что не скоро найдется пара свободных вечеров.

    Reply
  14. HAMMER_59

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

    Почему я не написал подобную статью:

    1. Вся теория уже есть в интернете, и её очень и очень много, зачем переписывать то, что уже отлично изложено. Уверен, что у меня получится хуже.

    2. 1С не предназначена для работы с графикой.

    Почему я прицепился к теории — мне нравится математика, а Вы её как-то пропустили, причем подход то очень интересный. Понятно что в итоге приходят к свойству матриц: A * B * C * D = A * (B * C * D), но к этому нужно прийти.

    Начинают с того самого первого вектора, и его координаты указывают от от вектора с 0 градусом

    Ax = x * cos(a)

    Ay = x * sin(a)

    При повороте на угол b получаем новую точку B с координатами

    Bx = x * cos(a + b)

    By = x * sin(a + b)

    раскладываем по тригонометрическим формулам

    Bx = x * cos(a) * cos(b) — x * sin(a) * sin(b)

    By = x * sin (a) * cos(b) + cos(a) * sin(b)

    подставляем

    Bx = Ax * cos(b) — Ay * sin(b)

    By = Ay * cos(b) + Ax * sin(b)

    выводят конечно через деление, напишу сразу результат

    {Ax, Ay} * {} = Ax * cos(b) — Ay * sin(b)

    ————-{}—-Ay * cos(b) + Ax * sin(b)

    т.е. не сложно подобрать нужную матрицу поворота

    {cos(b), sin(b)}

    {-sin(b), cos(b)}

    Как сделать перемещение? А делают следующим образом, к вектору добавляют третье значение, теперь вектор (x, y, 1), и матрица преобразования уже не 2 х 2, а 3 x 3, для перемещения выглядит следующим образом

    1 0 0

    0 1 0

    Tx Ty 1

    Далее переходят к масштабированию. Записываем вектор (x, y, z) а координаты точки на экране (x/z, y/z). Матрица масштабирования выглядит

    1 0 Wx

    0 1 Wy

    0 0 Wz

    А вы как-то сразу перешли к относительным координатам.

    3-х мерная графика практически ничем не отличается от двумерной, появляется ось Z, которая направлена вдаль, центр по x, y переносится в центр экрана. По нехитрой формуле вычисляется коэффициент для координат x, y при смещении по оси Z, т,е. при отдалении точки смещаются в центр.

    Reply
  15. HAMMER_59

    (13) Ну и разу уж вы упомянули быстродействие: «Каждый раз вычислять синус и косинус слишком долго». Так в принципе, вся эта реализация, крайне медленная. Даже если опустить насколько «быстро» исполняется код 1С, программное вычисление — это слишком долго.

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

    Так что изначально вся эта затея не про скорость.

    Reply
  16. WalterMort

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

    Reply
  17. WalterMort

    (15) Т.е. что я хочу акцентировать. Преобразования в пространстве в первую очередь векторные и матричные операции. А тригонометрия это плюшка сверху, добавленная потому что люди привыкли оперировать понятием «угол».

    Reply
  18. HAMMER_59

    (18) По-моему уже предельно ясно описал как тригонометрические преобразования привели к умножению матриц, но Вы все равно не видите тригонометрических преобразований. И ещё раз повторю, что это не моя точка зрения, это изложения материала по 3Д графики, ссылку я уже привел, тоже самое написано и в документации под Direct3D, и по OpenGL.

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

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

    Reply
  19. WalterMort

    (19) Понимаю, что перебороть «как учили» сложно. Катеты, гипотенузы. Ортогональное пространство (где оси координат находятся под углом 90 градусов) это сильно частный случай. В рамках этого частного случая вектор можно описать как вращение (1,0) на угол «а». Если же ось Y направлена, например под углом 45 к оси X, то такого сделать будет нельзя.

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

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

    Reply
  20. HAMMER_59

    (20)

    Понимаю, что перебороть «как учили» сложно. Катеты, гипотенузы. Ортогональное пространство (где оси координат находятся под углом 90 градусов) это сильно частный случай. В рамках этого частного случая вектор можно описать как вращение (1,0) на угол «а». Если же ось Y направлена, например под углом 45 к оси X, то такого сделать будет нельзя.

    Т.е. на ваших рисунках оси координат не под 90 градусов расположены друг к другу о_О.

    Ну давайте на примере, раз уж на то пошло.

    Задаём фигуру — квадрат с равноудаленными точками от центра:

    (-1, -1)

    (-1, 1)

    (1, 1)

    (1, -1)

    Приводим к виду

    (-1, -1, 1)

    (-1, 1, 1)

    (1, 1, 1)

    (1, -1, 1)

    Теперь используем 2 матрицы, первая — матрица преобразования объекта M1, вторая матрица положения объекта на экране M2.

    Вычислять результат будем следующим образом

    M * M1 * M2

    где M — матрица точек объекта.

    Рассчитываем М2, для начала смещаем на 5 вправо, затем поворачиваем на 45 градусов.

    (1, 0, 0)

    (0, 1, 0) x

    (0, 0, 1)

    (1, 0, 0)

    (0, 1, 0) x

    (5, 0, 1)

    (0.7, 0.7, 0)

    (-0.7, 0.7, 0) =

    (0 , 0 , 1)

    (0.7, 0.7, 0)

    (-0.7, 0.7, 0)

    (3.5, 3.5, 1)

    проверяем

    (-1, -1, 1)

    (-1, 1, 1) х

    (1, 1, 1)

    (1, -1, 1)

    (0.7, 0.7, 0)

    (-0.7, 0.7, 0) =

    (3.5, 3.5, 1)

    (3.5, 2.1, 1)

    (2.1, 3.5, 1)

    (3.5, 4.9, 1)

    (4.9, 3.5, 1)

    Повернуть не получится, сейчас проверим, как не получится

    Для простоты возьмем матрицу поворота на 45 градусов, мы её уже рассчитали, т.е. M1 равно:

    (0.7, 0.7, 0)

    (-0.7, 0.7, 0)

    (0 , 0 , 1)

    M1 * M2 =

    (0, 1, 0)

    (-1, 0, 0)

    (3.5, 3.5, 1)

    Умножаем M на матрицу преобразований и о чудо

    (4.5, 2.5, 1)

    (2.5, 2.5, 1)

    (2.5, 4.5, 1)

    (4.5, 4.5, 1)

    Всё получилось, вот ведь.

    А если теперь добавить еще ось Z которая, перпендикулярна к осям X, Y уже получится 3-х мерное пространство.

    Reply
  21. WalterMort

    (21)

    Т.е. на ваших рисунках оси координат не под 90 градусов расположены друг к другу о_О.

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

    (7, 6, 0) — 7,6 это вектор базиса «вправо»

    (1, 5, 0) — 1,5 вектор базиса «вверх»

    (5, 4, 1) — 5,4 смещение.

    Точка в локальном пространстве 0,5 0.5 соответственно в глобальном:

    (0.5, 0.5, 1) * М = (9, 9.5, 1)

    Можно ли решить эту задачу зная не векторы базиса, а их углы относительно оси (1, 0) ? Можно. Сначала найдем через синус и косинус векторы базиса и потом опять же векторным способом получим матрицу ровно как я описал. А если мы изначально знаем векторы базиса, тригонометрия не нужна, вот о чем я толкую.

    Всё получилось, вот ведь.

    А я и не утвеждаю, что тригонометрия не работает, я говорю что к этой задаче она вторична.

    Офф: Кстати векторный базис в вышеописанной матрице ((7,6),(1,5)) имеет ещё одно замечательное свойство. Его определитель |R| показывает во сколько раз изменится площадь фигуры при её переносе из локального пространства в глобальное.

    Reply
  22. HAMMER_59

    (22) Я на всякий случай проверил, какую изначально задачу Вы ставили:

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

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

    Перемещение, поворот, масштабирование я описал в сообщение 15.

    Reply
  23. HAMMER_59

    (22) Как я уже написал, я знаю, крайне мало примеров практического использования проецирования на плоскость. Насколько помню, тени таким образом отображают, а также отражения одних предметов в других. Для меня это никогда особого интереса не вызывало.

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

    Как Вы уже убедились я могу делать любые преобразования в 2-мерном пространстве, и систем координат могу использовать сколь угодно много, т.е. легко организую вращение колеса вокруг своей оси, а ось будет прикреплена к раме, и рама может при этом как угодно вращаться/перемещаться, при этом еще и камера (точка зрения) может как угодно меняться.

    Для 3-мерного пространства, мало что изменится, кроме появления оси Z, и проецирования на область экрана, а матрицы преобразования будут подобными.

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

    Я даже уже задумался сделать модель движения поршня в двигателе, ну чтобы точно развеять все сомнения насчет мощи новаторского подхода. Потом посмотрел как выводится линии в 1С. Потом оценил как это все реализовать без ООП. И сразу вспомнил выражение: «Пытаться натянуть сову на глобус».

    По-моему проще внешнюю компоненту сделать, для работы, например, с OpenGL.

    Reply
  24. HAMMER_59

    (22) Насчёт того, как всё быстро и просто.

    Как я уже писал, весь сыр бор с матрицами из-за одного свойства матриц A * B * C = A * (B * C). С помощью данного свойства легко осуществляется переход между системами координат, как правило: камера, мир, объект, но и объекты могут перемещаться относительно других объектов.

    Для операции переноса + поворот (причем поворот то как раз не в отдельной системе координат, а системе координат изображения). В вашем новаторском способе.

    1. Сначала вычисляете координаты проекции. Естественно при вычислении используются операции синуса / косинуса.

    2. Затем получаете матрицу 3 х 3

    3. Далее каждую точку умножаете на матрицу. 9 операций умножения + 6 сложения.

    Тоже самое можно было бы сделать.

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

    2. Получили матрицу 2 x 2 просто подстановкой значений (в некоторых случаях нужно поменять знак).

    3. Для каждой точки. Сначала выполняем операцию перемещения, это 2 операции сложения. Затем полученные координаты умножаем на матрицу 2 х 2. 4 операции умножения + 2 сложения.

    Может вы и в других средах умеете писать, я даже готов ради такого случая освежить свой знания по Си шарп, и на нем написать пример. Могу и 3-х мерном пространстве и в 2-х. Чтобы голословным не быть, что в вашем подходе потенциала нет, а все решается совсем по-другому.

    Reply
  25. Dzenn

    QUAKE в 1С сможешь реализовать?)

    Reply
  26. free-lancer-2018

    Было бы круто, если бы можно было начертить стрелку от конкретной ячейки табличного документа к другой конкретной ячейке…

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *