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




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

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

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

<?php // Полная загрузка сервисных книжек, создан 2026-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 не будет опубликован. Обязательные поля помечены *