diff --git a/src/App.svelte b/src/App.svelte
index d0abac7..dede907 100644
--- a/src/App.svelte
+++ b/src/App.svelte
@@ -9,8 +9,8 @@
import file_lib from "./libs/file";
import Modal from "./components/Modal.svelte";
- import MapApp from './services/map'
- import SvgMapParser from './svgmap/SvgMapParser'
+
+ import SvgMapParser from './svgmap/SvgMap.js'
import get_bbox from './libs/bbox'
diff --git a/src/back_.js b/src/back_.js
index 6be1df5..6bfc6c1 100644
--- a/src/back_.js
+++ b/src/back_.js
@@ -1,26 +1,33 @@
import fs, { symlinkSync } from "fs";
import axios from "axios";
-import SvgMapParser from "./svgmap/SvgMapParser.js";
+import SvgMap from "./svgmap/SvgMap.js";
+import SvgMapBuilder from "./svgmap/SvgMapBuilder.js";
+import CoordSystem from "./libs/CoordSystem.js";
+import SvgNode from "./svgmap/SvgNode.js";
import SvgNodes from "./svgmap/SvgNodes.js";
+import Transfrom from "./libs/Transform.js";
+import BBox from "./libs/bbox.js";
-import math_lib from './libs/math.js'
+// import SvgNodes from "./svgmap/SvgNodes.js";
+
+// import math_lib from './libs/math.js'
const back_url = "http://localhost:4000";
-const path = "../../data/2022-03-16";
+const path = "../../data/prodmaps";
// let file = fs.readFileSync('../data/2022-03-16/49_Кар тек и сум отб 7 об_вост.svg')
// let file = fs.readFileSync('../data/2022-03-16/49_Кар тек и сум отб 7 об_вост-sm.svg')
// let file = fs.readFileSync('../data/2022-03-16/49_Кар тек и сум отб 7 об_вост-inch.svg')
// let file = fs.readFileSync(`${path}/49_Кар тек и сум отб 7 об_вост-mm.svg`)
-let file = fs.readFileSync(`D:/dev/git/kz/prodmaps/tmp/49_Кар тек и сум отб 7 об_вост.svg`);
+let file = fs.readFileSync(`${path}/49_Кар тек и сум отб 7 об_вост.svg`);
// let file = fs.readFileSync('../data/2022-03-16/49_Кар тек и сум отб 7 об_вост-px.svg')
let styles = JSON.parse(fs.readFileSync("./moc/styles.json").toString());
-let parser = new SvgMapParser();
+let parser = new SvgMap();
function build_scaler() {
// Получить функцию для перевода координат из геологических в локальные.
@@ -51,64 +58,59 @@ async function start() {
let ww1 = wells.filter((x) => x.well == anchor.w1.name)[0];
let ww2 = wells.filter((x) => x.well == anchor.w2.name)[0];
- console.log(ww1, ww2);
-
if (!ww1) return ui.modal.show(`Скважины ${anchor.w1.name} не найдено в базе.`, ["ok"]);
if (!ww2) return ui.modal.show(`Скважины ${anchor.w2.name} не найдено в базе.`, ["ok"]);
- anchor.w1.whx = ww1.whx;
- anchor.w1.why = ww1.why;
- anchor.w2.whx = ww2.whx;
- anchor.w2.why = ww2.why;
+ // function cs(x0, y0, x1, y1) {
+ // return { x0, y0, x1, y1 };
+ // }
- function dist(x1, y1, x2, y2) {
- let dx = x2 - x1,
- dy = y2 - y1;
- return Math.sqrt(dx * dx + dy * dy);
- }
+ // function build_tr(cs1, cs2) {
+ // let dx1 = cs1.x1 - cs1.x0
+ // let dy1 = cs1.y1 - cs1.y0
+ // let dx2 = cs2.x1 - cs2.x0
+ // let dy2 = cs2.y1 - cs2.y0
- function cs(x0, y0, x1, y1) {
- return { x0, y0, x1, y1 };
- }
+ // const kx12 = dx2 / dx1
+ // const ky12 = dy2 / dy1;
+ // const kx21 = dx1 / dx2
+ // const ky21 = dy1 / dy2;
- function build_tr(cs1, cs2) {
- let dx1 = cs1.x1 - cs1.x0
- let dy1 = cs1.y1 - cs1.y0
- let dx2 = cs2.x1 - cs2.x0
- let dy2 = cs2.y1 - cs2.y0
+ // let tr = {
+ // tr12: {
+ // trx(x) {
+ // return (x - cs1.x0) * kx12 + cs2.x0;
+ // },
+ // try(y) {
+ // return (y - cs1.y0) * ky12 + cs2.y0;
+ // },
+ // },
+ // tr21: {
+ // trx(x) {
+ // return (x - cs2.x0) * kx21 + cs1.x0;
+ // },
+ // try(y) {
+ // return (y - cs2.y0) * ky21 + cs1.y0;
+ // },
+ // },
+ // };
+
+ // return tr;
+ // }
- const kx12 = dx2 / dx1
- const ky12 = dy2 / dy1;
- const kx21 = dx1 / dx2
- const ky21 = dy1 / dy2;
- let tr = {
- tr12: {
- trx(x) {
- return (x - cs1.x0) * kx12 + cs2.x0;
- },
- try(y) {
- return (y - cs1.y0) * ky12 + cs2.y0;
- },
- },
- tr21: {
- trx(x) {
- return (x - cs2.x0) * kx21 + cs1.x0;
- },
- try(y) {
- return (y - cs2.y0) * ky21 + cs1.y0;
- },
- },
- };
- return tr;
- }
// Функция перевода координат из глобальных в локальные.
- const cs1 = cs(anchor.w1.x, anchor.w1.y, anchor.w2.x, anchor.w2.y);
- const cs2 = cs(anchor.w1.whx, anchor.w1.why, anchor.w2.whx, anchor.w2.why);
- let tr = build_tr(cs1, cs2);
- console.log(tr);
+ const cs1 = new CoordSystem(anchor.w1.x, anchor.w1.y, anchor.w2.x, anchor.w2.y);
+ const cs2 = new CoordSystem(ww1.whx, ww1.why, ww2.whx, ww2.why);
+ // let tr = Transfrom.fromCoordSyses(cs2, cs1);
+
+ // let tr = Transfrom.fromCoordSyses(cs2, cs1);
+
+ // console.log('tr is:', tr);
+
+
// console.log(wells)
@@ -134,47 +136,436 @@ async function start() {
`// WHERE well='${anchor.w1.name}'`;
- // const query_all = `SELECT well, whx, why FROM wells`// WHERE well='${anchor.w1.name}'`;
- // const query_all = `SELECT well, whx, why FROM wells WHERE well='${anchor.w1.name}' OR well='${anchor.w2.name}'`;
+ // Получим максимально удаленные скважины не лежащие вдоль оси.
let all_wells = await axios.post(`${back_url}/proxy/sqlite`, { query: query_all }).then((x) => x.data.data);
- console.log(all_wells.map(x => x.wlf)) //.slice(0, 1))
- let mapped_wells = all_wells.map((x) => ({ ...x, lx: tr.tr21.trx(x.whx), ly: tr.tr21.try(x.why) }));
+ let bbox = BBox.from_array(all_wells.map(w => ({x: w.whx, y: w.why})))
+ console.log('BBOX', bbox)
+ console.log('BBOX', bbox.toLTWH())
+ console.log('BBOX', bbox.toLTRB())
-
- // let svg = SvgNodes.svg().set_attrs({
- // width: sc.w + "mm",
- // height: sc.h + "mm",
- // viewBox: `0 0 ${sc.w * sc.k} ${sc.h * sc.k}`,
- // });
- let svg = SvgNodes.group(['']).set_attr("id", "WLPT")
+ tr = Transfrom.fromCoordSyses()
- const tons_in_cm2 = 10000
- function t2r(tons){
- // tonns/mm2 = tonns/cm2 / 100. S(mm)=Pi*r*r=tons/tons_in_cm2*100. r = sqrt(tons/tons_in_cm2*100 / PI)
- return Math.sqrt(tons / tons_in_cm2 * 100 / Math.PI)
- }
- console.log(mapped_wells.filter(x => x.well == '213').map(x => ({...x, ttt: t2r(x.wlpt)})))
+ let mapped_wells = all_wells.map((x) => ({ ...x, lx: tr.trx(x.whx), ly: tr.try(x.why) }));
+
+ // const tons_in_cm2 = 10000
+
+ // function t2r(tons){
+ // // tonns/mm2 = tonns/cm2 / 100. S(mm)=Pi*r*r=tons/tons_in_cm2*100. r = sqrt(tons/tons_in_cm2*100 / PI)
+ // return Math.sqrt(tons / tons_in_cm2 * 100 / Math.PI)
+ // }
+
+ // console.log(mapped_wells.filter(x => x.well == '213').map(x => ({...x, ttt: t2r(x.wlpt)})))
// console.log(math_lib.make_ranges(vals))
// svg.append(mapped_wells.map((x) => SvgNodes.ring_sector(1.5 * sc.k, 6 * sc.k, 0, 120).move(x.lx, x.ly).set_style(styles.gpt)));
- // Круги
- let g_wopts = SvgNodes.group()
- svg.append(g_wopts)
- g_wopts.append(mapped_wells.map((x) => SvgNodes.ring_sectors(1.5 * sc.k, t2r(x.wlpt) * sc.k, [{v: x.wopt, style: styles.opt}, {v: x.wwpt, style: styles.wpt}]).move(x.lx, x.ly)));
+
- svg.append(mapped_wells.map((x) => SvgNodes.circle(1.5 * sc.k).move(x.lx, x.ly).set_style(styles.wellhead)));
- svg.append(mapped_wells.map((x) => SvgNodes.text(x.well).move(x.lx + 1.7 * sc.k, x.ly).set_style(styles.wellhead)));
- svg.append(mapped_wells.map((x) => SvgNodes.text(`${Math.round(x.wlf * 1000)/10 || ''}%`).move(x.lx + 1.7 * sc.k, x.ly + 1 * sc.k).set_style(styles.wlf)));
+ const settings = {
+ tons_in_cm2: 10000,
+ styles
+ }
- let data = file.toString().replace('', svg.render() + '')
+ {
+ let ti_layer = parser.build_tp_layer(mapped_wells, settings)
+ let svg = SvgNodes.svg().set_attr("width", "1000px").set_attr("height", "1000px").set_attr("viewBox", "0 0 1000 1000")
+ // let defs = new SvgNode('defs')
+ // defs.append(ti_layer.defs)
+ // console.log(ti_layer.defs.tag)
+ svg.append(ti_layer.defs)
+ svg.append(ti_layer.svg)
+ fs.writeFileSync(`${path}/out.svg`, svg.render());
+ }
+
+
+ // let ti_layer = parser.build_tp_layer(mapped_wells, settings)
+ // let data = file.toString()
+ // .replace('', ti_layer.defs.render() + '')
+ // .replace('', ti_layer.svg.render() + '')
+ // fs.writeFileSync("../tmp/out_prod.svg", data) //svg.render());
+
+
+ // let ti_layer_inj = parser.build_ti_layer(mapped_wells, settings)
+ // let data2 = file.toString()
+ // .replace('', ti_layer_inj.defs.render() + '')
+ // .replace('', ti_layer_inj.svg.render() + '')
+ // fs.writeFileSync("../tmp/out_inj.svg", data2) //svg.render());
- fs.writeFileSync("../tmp/out.svg", data) //svg.render());
}
-start();
+
+async function build_map_pt(devobj) {
+ // const DATE = '2023-01-01'
+
+ const query_all = `SELECT
+ wells.well, wells.whx, wells.why,
+ MAX(production_injections.date) as date
+ ,SUM(production_injections.woptm) as wopt
+ ,SUM(production_injections.wwptm) as wwpt
+ ,SUM(production_injections.wsgptv) as wgpt
+ ,SUM(production_injections.wwitv) as wwit
+ ,SUM(production_injections.wwptm)+SUM(production_injections.woptm) as wlpt
+ ,SUM(production_injections.wwptm)/(SUM(production_injections.wwptm)+SUM(production_injections.woptm)) as wlf
+ FROM
+ wells, production_injections
+ WHERE
+ wells.well=production_injections.well
+
+ AND object='${devobj}'
+ GROUP BY
+ wells.well
+
+ `
+
+ let all_wells = await axios.post(`${back_url}/proxy/sqlite`, { query: query_all }).then((x) => x.data.data);
+ if (all_wells.length == 0){
+ // fs.writeFileSync(`${path}/out_devobj-${devobj}.svg`, "");
+ return
+ }
+
+ let bbox = BBox.from_array(all_wells.map(w => ({x: w.whx, y: w.why})))
+
+ {
+ const builder = new SvgMapBuilder()
+
+ const settings = {
+ tons_in_cm2: 10000,
+ ppu: 100, // 100
+ styles: builder.update_styles(styles, 100),
+ // Масштаб 1мм карты / 1мм реальный (1000мм в 1м)
+ map_scale: 1 / 10000 * 1000
+ }
+
+ // Функция перевода координат из глобальных в локальные.
+ const cs1 = new CoordSystem(bbox.l, bbox.t, bbox.r, bbox.b)
+ const cs_mm = cs1.clone().flipy().moveto(0, 0).scale(settings.map_scale)
+ const cs_ppu = cs_mm.clone().scale(settings.ppu)
+ let tr = Transfrom.fromCoordSyses(cs1, cs_ppu);
+
+ let mapped_wells = all_wells.map((x) => ({ ...x, lx: tr.trx(x.whx), ly: tr.try(x.why) }));
+
+ let ti_layer = builder.build_tp_layer(mapped_wells, settings)
+ const csw = Math.abs(cs_mm.x1 - cs_mm.x0)
+ const csh = Math.abs(cs_mm.y1 - cs_mm.y0)
+ const bbox_ppu = BBox.fromLTRB(cs_ppu.x0, cs_ppu.y0, cs_ppu.x1, cs_ppu.y1)
+
+ let svg = SvgNodes.svg()
+ .set_attr("width", csw + "mm").set_attr("height", csh + "mm")
+ .set_attr("viewBox", `${bbox_ppu.l} ${bbox_ppu.t} ${bbox_ppu.w()} ${bbox_ppu.h()}`)
+ svg.append(ti_layer.defs)
+ svg.append(ti_layer.svg)
+ fs.writeFileSync(`${path}/out_devobj-${devobj}-PT.svg`, svg.render());
+ }
+}
+
+async function build_map_it(devobj) {
+ // const DATE = '2023-01-01'
+
+ const query_all = `SELECT
+ wells.well, wells.whx, wells.why,
+ MAX(production_injections.date) as date
+ ,SUM(production_injections.woptm) as wopt
+ ,SUM(production_injections.wwptm) as wwpt
+ ,SUM(production_injections.wsgptv) as wgpt
+ ,SUM(production_injections.wwitv) as wwit
+ ,SUM(production_injections.wwptm)+SUM(production_injections.woptm) as wlpt
+ ,SUM(production_injections.wwptm)/(SUM(production_injections.wwptm)+SUM(production_injections.woptm)) as wlf
+ FROM
+ wells, production_injections
+ WHERE
+ wells.well=production_injections.well
+ AND object='${devobj}'
+ GROUP BY
+ wells.well
+ HAVING
+ wwit>0
+
+ `
+
+ let all_wells = await axios.post(`${back_url}/proxy/sqlite`, { query: query_all }).then((x) => x.data.data);
+ if (all_wells.length == 0){
+ // fs.writeFileSync(`${path}/out_devobj-${devobj}.svg`, "");
+ return
+ }
+
+ let bbox = BBox.from_array(all_wells.map(w => ({x: w.whx, y: w.why})))
+
+ {
+ const builder = new SvgMapBuilder()
+
+ const settings = {
+ tons_in_cm2: 10000,
+ ppu: 100, // 100
+ styles: builder.update_styles(styles, 100),
+ // Масштаб 1мм карты / 1мм реальный (1000мм в 1м)
+ map_scale: 1 / 10000 * 1000
+ }
+
+ // Функция перевода координат из глобальных в локальные.
+ const cs1 = new CoordSystem(bbox.l, bbox.t, bbox.r, bbox.b)
+ const cs_mm = cs1.clone().flipy().moveto(0, 0).scale(settings.map_scale)
+ const cs_ppu = cs_mm.clone().scale(settings.ppu)
+ let tr = Transfrom.fromCoordSyses(cs1, cs_ppu);
+
+ let mapped_wells = all_wells.map((x) => ({ ...x, lx: tr.trx(x.whx), ly: tr.try(x.why) }));
+
+ let ti_layer = builder.build_ti_layer(mapped_wells, settings)
+ const csw = Math.abs(cs_mm.x1 - cs_mm.x0)
+ const csh = Math.abs(cs_mm.y1 - cs_mm.y0)
+ const bbox_ppu = BBox.fromLTRB(cs_ppu.x0, cs_ppu.y0, cs_ppu.x1, cs_ppu.y1)
+
+ let svg = SvgNodes.svg()
+ .set_attr("width", csw + "mm").set_attr("height", csh + "mm")
+ .set_attr("viewBox", `${bbox_ppu.l} ${bbox_ppu.t} ${bbox_ppu.w()} ${bbox_ppu.h()}`)
+ svg.append(ti_layer.defs)
+ svg.append(ti_layer.svg)
+ fs.writeFileSync(`${path}/out_devobj-${devobj}-IT.svg`, svg.render());
+ }
+
+
+ // let ti_layer = parser.build_tp_layer(mapped_wells, settings)
+ // let data = file.toString()
+ // .replace('', ti_layer.defs.render() + '')
+ // .replace('', ti_layer.svg.render() + '')
+ // fs.writeFileSync("../tmp/out_prod.svg", data) //svg.render());
+
+
+ // let ti_layer_inj = parser.build_ti_layer(mapped_wells, settings)
+ // let data2 = file.toString()
+ // .replace('', ti_layer_inj.defs.render() + '')
+ // .replace('', ti_layer_inj.svg.render() + '')
+ // fs.writeFileSync("../tmp/out_inj.svg", data2) //svg.render());
+}
+
+async function build_map_pty(devobj) {
+ let sql_max_year = `SELECT strftime('%Y', max(date)) as max_year FROM production_injections`
+ const max_year = await axios.post(`${back_url}/proxy/sqlite`, { query: sql_max_year }).then((x) => x.data.data[0].max_year);
+
+ // const DATE = '2023-01-01'
+
+ const query_all = `SELECT
+ wells.well, wells.whx, wells.why,
+ MAX(production_injections.date) as date
+ ,SUM(production_injections.woptm) as wopt
+ ,SUM(production_injections.wwptm) as wwpt
+ ,SUM(production_injections.wsgptv) as wgpt
+ ,SUM(production_injections.wwitv) as wwit
+ ,SUM(production_injections.wwptm)+SUM(production_injections.woptm) as wlpt
+ ,SUM(production_injections.wwptm)/(SUM(production_injections.wwptm)+SUM(production_injections.woptm)) as wlf
+ FROM
+ wells, production_injections
+ WHERE
+ wells.well=production_injections.well
+ AND object='${devobj}'
+ AND strftime('%Y', date)='${max_year}'
+ GROUP BY
+ wells.well
+
+ `
+
+ let all_wells = await axios.post(`${back_url}/proxy/sqlite`, { query: query_all }).then((x) => x.data.data);
+ if (all_wells.length == 0){
+ // fs.writeFileSync(`${path}/out_devobj-${devobj}-CP.svg`, "");
+ return
+ }
+
+ let bbox = BBox.from_array(all_wells.map(w => ({x: w.whx, y: w.why})))
+
+ {
+ const builder = new SvgMapBuilder()
+
+ const settings = {
+ tons_in_cm2: 10000,
+ ppu: 100, // 100
+ styles: builder.update_styles(styles, 100),
+ // Масштаб 1мм карты / 1мм реальный (1000мм в 1м)
+ map_scale: 1 / 10000 * 1000
+ }
+
+ // Функция перевода координат из глобальных в локальные.
+ const cs1 = new CoordSystem(bbox.l, bbox.t, bbox.r, bbox.b)
+ const cs_mm = cs1.clone().flipy().moveto(0, 0).scale(settings.map_scale)
+ const cs_ppu = cs_mm.clone().scale(settings.ppu)
+ let tr = Transfrom.fromCoordSyses(cs1, cs_ppu);
+
+ let mapped_wells = all_wells.map((x) => ({ ...x, lx: tr.trx(x.whx), ly: tr.try(x.why) }));
+
+ let ti_layer = builder.build_tp_layer(mapped_wells, settings)
+ const csw = Math.abs(cs_mm.x1 - cs_mm.x0)
+ const csh = Math.abs(cs_mm.y1 - cs_mm.y0)
+ const bbox_ppu = BBox.fromLTRB(cs_ppu.x0, cs_ppu.y0, cs_ppu.x1, cs_ppu.y1)
+
+ let svg = SvgNodes.svg()
+ .set_attr("width", csw + "mm").set_attr("height", csh + "mm")
+ .set_attr("viewBox", `${bbox_ppu.l} ${bbox_ppu.t} ${bbox_ppu.w()} ${bbox_ppu.h()}`)
+ svg.append(ti_layer.defs)
+ svg.append(ti_layer.svg)
+ fs.writeFileSync(`${path}/out_devobj-${devobj}-PC.svg`, svg.render());
+ }
+}
+
+
+
+async function start2() {
+ const DATE = '2023-01-01'
+
+ const sql_objects = `SELECT distinct(object) as devobj FROM production_injections`
+
+ let objects = await axios.post(`${back_url}/proxy/sqlite`, { query: sql_objects }).then((x) => x.data.data.map(y => y.devobj));
+
+ objects.map(build_map_pt)
+ objects.map(build_map_it)
+ objects.map(build_map_pty)
+
+ return
+
+ const query_all = `SELECT
+ wells.well, wells.whx, wells.why,
+ MAX(production_injections.date) as date
+ ,SUM(production_injections.woptm) as wopt
+ ,SUM(production_injections.wwptm) as wwpt
+ ,SUM(production_injections.wsgptv) as wgpt
+ ,SUM(production_injections.wwitv) as wwit
+ ,SUM(production_injections.wwptm)+SUM(production_injections.woptm) as wlpt
+ ,SUM(production_injections.wwptm)/(SUM(production_injections.wwptm)+SUM(production_injections.woptm)) as wlf
+ FROM
+ wells, production_injections
+ WHERE
+ wells.well=production_injections.well
+ AND production_injections.date<='${DATE}'
+ AND object='8'
+ GROUP BY
+ wells.well
+
+ `// WHERE well='${anchor.w1.name}'`;
+
+ // const query_all2 = `SELECT distinct(object) FROM production_injections limit 10`
+
+ let all_wells = await axios.post(`${back_url}/proxy/sqlite`, { query: query_all }).then((x) => x.data.data);
+
+ // console.log(all_wells)
+ // return
+
+ let bbox = BBox.from_array(all_wells.map(w => ({x: w.whx, y: w.why})))
+
+ // let mapped_wells = all_wells.map((x) => ({ ...x, lx: tr.trx(x.whx), ly: tr.try(x.why) }));
+
+ // let mapped_wells = all_wells.map((x) => ({ ...x, lx: tr.trx(x.whx), ly: tr.try(x.why) }));
+
+ // const tons_in_cm2 = 10000
+
+ // function t2r(tons){
+ // // tonns/mm2 = tonns/cm2 / 100. S(mm)=Pi*r*r=tons/tons_in_cm2*100. r = sqrt(tons/tons_in_cm2*100 / PI)
+ // return Math.sqrt(tons / tons_in_cm2 * 100 / Math.PI)
+ // }
+
+ // console.log(mapped_wells.filter(x => x.well == '213').map(x => ({...x, ttt: t2r(x.wlpt)})))
+
+ // console.log(math_lib.make_ranges(vals))
+
+ // svg.append(mapped_wells.map((x) => SvgNodes.ring_sector(1.5 * sc.k, 6 * sc.k, 0, 120).move(x.lx, x.ly).set_style(styles.gpt)));
+
+
+
+
+ {
+ const builder = new SvgMapBuilder()
+
+ const settings = {
+ tons_in_cm2: 10000,
+ ppu: 100, // 100
+ styles: builder.update_styles(styles, 100),
+ // Масштаб 1мм карты / 1мм реальный (1000мм в 1м)
+ map_scale: 1 / 10000 * 1000
+ }
+
+
+console.log(settings)
+
+ function mm2ppu(v){
+ if (v.endsWith('mm')){
+ return parseFloat(v.slice(0, v.length - 2)) * settings.ppu * 100 / 69
+ }
+ }
+
+ function pt2ppu(v){
+ if (v.endsWith('pt')){
+ return parseFloat(v.slice(0, v.length - 2)) * settings.ppu * 100 / 283.46
+ }
+ }
+
+ function u2ppu(v){
+ if (v.endsWith('mm')){
+ return parseFloat(v.slice(0, v.length - 2)) * settings.ppu * 100 / 69
+ }
+ if (v.endsWith('pt')){
+ return parseFloat(v.slice(0, v.length - 2)) * settings.ppu * 100 / 283.46
+ }
+ }
+
+ // mm = 25.4 * (px / 96)
+
+ // settings.styles.wellhead["font-family"] = "Courier New",
+ // console.log(mm2ppu(settings.styles.wellhead['font-size']))
+ // settings.styles.wellhead['font-size'] = u2ppu('10pt') //settings.styles.wellhead['font-size'])
+
+ // const query = `SELECT well, whx, why FROM wells WHERE well='203'`;
+ const query = `SELECT well, whx, why FROM wells WHERE well='R-2'`;
+ let wells = await axios.post(`${back_url}/proxy/sqlite`, { query }).then((x) => x.data.data);
+ console.log(wells);
+ let c = [wells[0].whx - bbox.l, wells[0].why - bbox.t]
+ console.log(c)
+
+
+
+ // Функция перевода координат из глобальных в локальные.
+ const cs1 = new CoordSystem(bbox.l, bbox.t, bbox.r, bbox.b)
+ const cs_mm = cs1.clone().moveto(0, 0).scale(settings.map_scale)
+ const cs_ppu = cs_mm.clone().scale(settings.ppu)
+ let tr = Transfrom.fromCoordSyses(cs1, cs_ppu);
+
+ console.log('cs_mm', cs_mm, 'cs_ppu', cs_ppu)
+
+
+
+
+ let mapped_wells = all_wells.map((x) => ({ ...x, lx: tr.trx(x.whx), ly: tr.try(x.why) }));
+
+ let ti_layer = builder.build_tp_layer(mapped_wells, settings)
+ const csw = (cs_mm.x1 - cs_mm.x0)
+ const csh = (cs_mm.y1 - cs_mm.y0)
+
+ let svg = SvgNodes.svg().set_attr("width", csw + "mm").set_attr("height", csh + "mm")
+ // .set_attr("viewBox", "0 0 1000 1000")
+ .set_attr("viewBox", `${cs_ppu.x0} ${cs_ppu.y0} ${(cs_ppu.x1 - cs_ppu.x0)} ${(cs_ppu.y1 - cs_ppu.y0)}`)
+ // let defs = new SvgNode('defs')
+ // defs.append(ti_layer.defs)
+ // console.log(ti_layer.defs.tag)
+ svg.append(ti_layer.defs)
+ svg.append(ti_layer.svg)
+ fs.writeFileSync(`${path}/out.svg`, svg.render());
+ }
+
+
+ // let ti_layer = parser.build_tp_layer(mapped_wells, settings)
+ // let data = file.toString()
+ // .replace('', ti_layer.defs.render() + '')
+ // .replace('', ti_layer.svg.render() + '')
+ // fs.writeFileSync("../tmp/out_prod.svg", data) //svg.render());
+
+
+ // let ti_layer_inj = parser.build_ti_layer(mapped_wells, settings)
+ // let data2 = file.toString()
+ // .replace('', ti_layer_inj.defs.render() + '')
+ // .replace('', ti_layer_inj.svg.render() + '')
+ // fs.writeFileSync("../tmp/out_inj.svg", data2) //svg.render());
+
+}
+
+
+start2();
diff --git a/src/libs/CoordSystem.js b/src/libs/CoordSystem.js
new file mode 100644
index 0000000..909fa91
--- /dev/null
+++ b/src/libs/CoordSystem.js
@@ -0,0 +1,54 @@
+export default class CoordSystem{
+ /**
+ * Создает ненормированную систему координат с началом в x0,y0 и направлением x1,y1
+ * @param {*} x0
+ * @param {*} y0
+ * @param {*} x1
+ * @param {*} y1
+ * @returns
+ */
+ constructor(x0, y0, x1, y1) {
+ this.x0 = x0
+ this.y0 = y0
+ this.x1 = x1
+ this.y1 = y1
+ }
+
+ scale(k){
+ this.x1 *= k
+ this.y1 *= k
+ return this
+ }
+
+ move(dx, dy){
+ this.x0 += dx
+ this.y0 += dy
+ this.x1 += dx
+ this.y1 += dy
+ return this
+ }
+
+ moveto(x, y){
+ let dx = x - this.x0
+ let dy = y - this.y0
+ return this.move(dx, dy)
+ }
+
+ flipx(){
+ let x = this.x0
+ this.x0 = this.x1
+ this.x1 = x
+ // this.x0 += 500
+ // this.x1 = 2 * this.x0 - this.x1 + 500
+ return this
+ }
+
+ flipy(){
+ this.y1 = 2 * this.y0 - this.y1
+ return this
+ }
+
+ clone(){
+ return new CoordSystem(this.x0, this.y0, this.x1, this.y1)
+ }
+};
diff --git a/src/libs/Transform.js b/src/libs/Transform.js
new file mode 100644
index 0000000..d774bab
--- /dev/null
+++ b/src/libs/Transform.js
@@ -0,0 +1,30 @@
+export default class Transfrom {
+ static fromCoordSyses(cs1, cs2){
+ let tr = new Transfrom()
+
+ tr.cs1 = cs1
+ tr.cs2 = cs2
+
+ let dx1 = cs1.x1 - cs1.x0;
+ let dy1 = cs1.y1 - cs1.y0;
+ let dx2 = cs2.x1 - cs2.x0;
+ let dy2 = cs2.y1 - cs2.y0;
+
+ tr.kx12 = dx2 / dx1;
+ tr.ky12 = dy2 / dy1;
+
+ return tr
+ }
+
+ trx(x){
+ return (x - this.cs1.x0) * this.kx12 + this.cs2.x0;
+ }
+
+ try(y){
+ return (y - this.cs1.y0) * this.ky12 + this.cs2.y0;
+ }
+
+ trp(p){
+ return {x: this.trx(p.x), y: this.trx(p.y)}
+ }
+}
diff --git a/src/libs/bbox.js b/src/libs/bbox.js
index 67ebd04..3c2a9e6 100644
--- a/src/libs/bbox.js
+++ b/src/libs/bbox.js
@@ -1,11 +1,95 @@
-module.exports = function (data) {
- return data.reduce(
- (s, c) => ({
- l: Math.min(s.l, c.x),
- t: Math.min(s.t, c.y),
- r: Math.max(s.r, c.x),
- b: Math.max(s.b, c.y),
- }),
- { l: data[0].x, t: data[0].y, r: data[0].x, b: data[0].y }
- );
-};
+export default class BBox {
+ static fromLTWH(l, t, w, h){
+ return BBox.fromLTRB(l, t, l + w, t + h)
+ }
+
+ static fromLTRB(l, t, r, b){
+ return Object.assign(new BBox(), {l: Math.min(l, r), t: Math.min(t, b), r: Math.max(l, r), b: Math.max(t, b)})
+ }
+
+ static from_array(arr_xy){
+ const bbox = BBox.fromLTWH(arr_xy[0].x, arr_xy[0].y, 0, 0)
+ return bbox.append_many(arr_xy)
+ }
+
+ w(){
+ return this.r - this.l
+ }
+
+ h(){
+ return this.b - this.t
+ }
+
+ toLTWH(){
+ const {l, t, r, b} = this
+ return {l, t, w: r - l, h: b - t }
+ }
+
+ toLTRB(){
+ const {l, t, r, b} = this
+ return {l, t, r, b}
+ }
+
+ toLTRBarr(){
+ const {l, t, r, b} = this
+ return [l, t, r, b]
+ }
+
+ append(x, y){
+ this.l = Math.min(this.l, x)
+ this.t = Math.min(this.t, y)
+ this.r = Math.max(this.r, x)
+ this.b = Math.max(this.b, y)
+ return this
+ }
+
+ append_many(arr_xy){
+ arr_xy.forEach(e => this.append(e.x, e.y))
+ return this
+ }
+
+ scale(k){
+ this.r = this.l + (this.r - this.l) * k
+ this.b = this.t + (this.b - this.t) * k
+ return this
+ }
+
+ move(dx, dy){
+ this.l += dx
+ this.t += dy
+ this.r += dx
+ this.b += dy
+ return this
+ }
+
+ moveto(x, y){
+ let dx = x - this.l
+ let dy = y - this.t
+ return this.move(dx, dy)
+ }
+
+ clone(){
+ return BBox.fromLTRB(this.l, this.t, this.r, this.b)
+ }
+
+ // static from_data(data){
+ // return data.reduce(
+ // (s, c) => ({
+ // l: Math.min(s.l, c.x),
+ // t: Math.min(s.t, c.y),
+ // r: Math.max(s.r, c.x),
+ // b: Math.max(s.b, c.y),
+ // }),
+ // { l: data[0].x, t: data[0].y, r: data[0].x, b: data[0].y }
+ // );
+ // // return data.reduce(
+ // // (s, c) => ({
+ // // l: Math.min(s.l, c.x),
+ // // t: Math.min(s.t, c.y),
+ // // r: Math.max(s.r, c.x),
+ // // b: Math.max(s.b, c.y),
+ // // }),
+ // // { l: data[0].x, t: data[0].y, r: data[0].x, b: data[0].y }
+ // // );
+ // }
+}
\ No newline at end of file
diff --git a/src/libs/math.js b/src/libs/math.js
index 0ae8e10..bd7e725 100644
--- a/src/libs/math.js
+++ b/src/libs/math.js
@@ -1,4 +1,10 @@
export default {
+ /**
+ * Создает данные дл круговой диаграммы из набора значений v0,v1,v2,v3 -> [{a0: 0, a1: v0}, {a0: v0, a1: v0+v1}, {a0: v0+v1, a1: v0+v1+v2},]
+ * @param { [Number] } values Значения долей
+ * @param { boolean } norm Нормировать ли значения диапазонов в отрезок 0-1
+ * @returns Массив с диапазонами долей 1,2,3,4 -> [{0,0.1},{0.1,0.3},{0.3,0.6},{0.6,1}]
+ */
make_ranges(values, norm = true) {
let ranges = values.reduce((s, c, i) => [...s, {...c, a0: i && s[i - 1].a1, a1: c + (i && s[i - 1].a1)}], [])
let max = ranges[ranges.length - 1].a1
diff --git a/src/moc/styles.json b/src/moc/styles.json
index df127ad..45adfca 100644
--- a/src/moc/styles.json
+++ b/src/moc/styles.json
@@ -1,21 +1,25 @@
{
"wellhead": {
"font-family": "Times New Roman",
- "font-weight": "bold",
- "stroke-width": "2.5mm",
- "font-size": 500,
+ "font-weight": "bold",
+ "font-size": "10pt",
+ "stroke-width": "0.1pt",
"stroke": "#fff",
- "fill": "#000"
+ "fill": "#000",
+ "dx":1.7,
+ "dy":"0"
},
+
"wlf": {
"font-family": "Times New Roman",
"font-weight": "bold",
"stroke-width": "0",
- "alignment-baseline": "hanging",
- "font-size": 300,
+ "font-size": "8pt",
"font-style": "italic",
"stroke": "#fff",
- "fill": "#00f"
+ "fill": "#00f",
+ "dx": 1.7,
+ "dy": 3
},
"gpt": {
@@ -26,11 +30,16 @@
"opt": {
"stroke-width": 10,
"stroke": "#000",
- "fill": "#B86B41"
+ "fill": "url(#rg_opt)"
},
"wpt": {
"stroke-width": 10,
"stroke": "#000",
- "fill": "#67c2e5"
- }
+ "fill": "url(#rg_wpt)"
+ },
+ "wit": {
+ "stroke-width": 10,
+ "stroke": "#000",
+ "fill": "url(#rg1)"
+ }
}
\ No newline at end of file
diff --git a/src/svgmap/SvgMap.js b/src/svgmap/SvgMap.js
new file mode 100644
index 0000000..2401e04
--- /dev/null
+++ b/src/svgmap/SvgMap.js
@@ -0,0 +1,140 @@
+import { parse } from "svg-parser";
+
+import SvgNode from './SvgNode.js'
+import SvgNodes from './SvgNodes.js'
+
+export default class {
+ async parse(xml) {
+ let result1 = parse(xml);
+
+ this.svg = result1.children.filter((x) => x.tagName == "svg")[0];
+ }
+
+ /**
+ * Получить слои документа. Имя слоя можно получить через поле id.
+ * @returns
+ */
+ get_layers() {
+ return this.svg.children.filter((x) => x.tagName == "g");
+ }
+
+ /**
+ * Получить данные масштаба карты.
+ * @returns {w, h, k, u} Ширина в мм, высота в мм, k * v[px] = v[мм], юниты (mm, cm, inch)
+ */
+ get_map_scale() {
+ // console.log(this.svg)
+ let vb = this.svg.properties.viewBox.split(" ").map((x) => parseFloat(x));
+ let w = this.svg.properties.width;
+ let h = this.svg.properties.height;
+
+ let units = {
+ in: 25.4,
+ mm: 1,
+ cm: 10,
+ px: 0.0846646,
+ // '%': 1
+ };
+
+ const u = Object.keys(units).filter((x) => w.endsWith(x))[0];
+ if (!u) throw "Unsupported units";
+
+ w = Math.round(parseFloat(w.substring(0, w.length - u.length)) * units[u] * 100) / 100;
+ h = Math.round(parseFloat(h.substring(0, h.length - u.length)) * units[u] * 100) / 100;
+ let k = vb[2] / w;
+
+ return { w, h, k, u };
+ }
+
+ /**
+ * Достать из слоя опордные скважины
+ * @param {*} layer Слой в котором 2 последние группы содержат опорные скважины.
+ * @returns { w1, w2 } Опрорные скважины
+ */
+ extract_anchor(layer) {
+ let w1 = this.extract_well(layer.children[layer.children.length - 1]);
+ let w2 = this.extract_well(layer.children[layer.children.length - 2]);
+
+ return { w1, w2 };
+ }
+
+ _flat(node) {
+ if (!node.children) return [node];
+ return node.children.reduce((s, c) => s.concat(this._flat(c)), [node]);
+ }
+
+ /**
+ * Получить из группы данные скважины (имя, координаты)
+ * @param {*} pivot_group Svg группа
+ * @returns { {x, y, name} }
+ */
+ extract_well(pivot_group) {
+ let flat = this._flat(pivot_group);
+ let ellipse = flat.filter((x) => x.tagName == "circle" || x.tagName == "ellipse")[0];
+ let tr = ellipse.properties.transform
+ .replace("matrix(", "")
+ .replace(")", "")
+ .split(" ")
+ .map((x) => parseFloat(x));
+
+ let text = flat.filter((x) => x.type == "text")[0];
+ let name = text.value;
+ return { x: tr[4], y: tr[5], name };
+ }
+
+ build_tp_layer(wells, settings){
+ const sc = this.get_map_scale()
+
+ function t2r(tons){
+ // tonns/mm2 = tonns/cm2 / 100. S(mm)=Pi*r*r=tons/tons_in_cm2*100. r = sqrt(tons/tons_in_cm2*100 / PI)
+ return Math.sqrt(tons / settings.tons_in_cm2 * 100 / Math.PI)
+ }
+
+ let {styles} = settings
+
+ let defs = new SvgNode("defs")
+ defs.append(SvgNodes.defs.simple.radialGradient("rg_opt", "#fff", "#B86B41"))
+ defs.append(SvgNodes.defs.simple.radialGradient("rg_wpt", "#fff", "#67c2e5"))
+
+ let svg = SvgNodes.group(['']).set_attr("id", "WWPT")
+ // Круги
+ svg.append(wells.map((x) => SvgNodes.ring_sectors(1.5 * sc.k, t2r(x.wlpt) * sc.k, [{v: x.wopt, style: styles.opt}, {v: x.wwpt, style: styles.wpt}]).move(x.lx, x.ly)));
+ // Знак скважины
+ svg.append(wells.map((x) => SvgNodes.circle(1.5 * sc.k).move(x.lx, x.ly).set_style(styles.wellhead)));
+ // Имя скважины
+ svg.append(wells.map((x) => SvgNodes.text(x.well).move(x.lx + styles.wellhead.dx * sc.k, x.ly + styles.wellhead.dy * sc.k).set_style(styles.wellhead)));
+ // Обводненность
+ svg.append(wells.map((x) => SvgNodes.text(`${Math.round(x.wlf * 1000)/10 || ''}%`).move(x.lx + styles.wlf.dx * sc.k, x.ly + styles.wlf.dy * sc.k).set_style(styles.wlf)));
+
+ return {defs, svg}
+ }
+
+ build_ti_layer(wells, settings){
+ const sc = this.get_map_scale()
+
+ function t2r(tons){
+ // tonns/mm2 = tonns/cm2 / 100. S(mm)=Pi*r*r=tons/tons_in_cm2*100. r = sqrt(tons/tons_in_cm2*100 / PI)
+ return Math.sqrt(tons / settings.tons_in_cm2 * 100 / Math.PI)
+ }
+
+ let {styles} = settings
+
+ let defs = SvgNodes.container()
+ defs.append(SvgNodes.defs.simple.radialGradient("rg1", "#fff", "#c1ff5e"))
+
+ let svg = SvgNodes.group(['']).set_attr("id", "WWIT")
+ // Круги
+ // let g_rings = SvgNodes.group(['']).set_attr("id", "Круги")
+ // svg.append(g_rings)
+ svg.append(wells.map((x) => SvgNodes.circle(t2r(x.wwit) * sc.k).set_style(styles.wit).move(x.lx, x.ly)));
+ // Знак скважины
+ svg.append(wells.map((x) => SvgNodes.circle(1.5 * sc.k).move(x.lx, x.ly).set_style(styles.wellhead)));
+ // Имя скважины
+ svg.append(wells.map((x) => SvgNodes.text(x.well).move(x.lx + styles.wellhead.dx * sc.k, x.ly + styles.wellhead.dy * sc.k).set_style(styles.wellhead)));
+ // Обводненность
+ svg.append(wells.map((x) => SvgNodes.text(`${Math.round(x.wlf * 1000)/10 || ''}%`).move(x.lx + styles.wlf.dx * sc.k, x.ly + styles.wlf.dy * sc.k).set_style(styles.wlf)));
+
+ return {defs, svg}
+ }
+
+}
diff --git a/src/svgmap/SvgMapBuilder.js b/src/svgmap/SvgMapBuilder.js
index 9928544..4cdec17 100644
--- a/src/svgmap/SvgMapBuilder.js
+++ b/src/svgmap/SvgMapBuilder.js
@@ -1,24 +1,144 @@
-export default class SvgMapBulder{
- let WellsRenderer = {
- // [{x,y}]
- heads(wells, r, style) {
- return wells.map((w) => SvgNodes.circle(r).set_style(style).move(w.x, w.y));
- },
+import SvgNode from "./SvgNode.js";
+import SvgNodes from "./SvgNodes.js";
- // [{x,y,name}]
- names(wells, style, shift) {
- return wells.map((w) =>
- SvgNodes.text(w.name)
- .set_style(style)
- .move(w.x + shift.x, w.y + shift.y)
- );
- },
+export default class {
+ /**
+ * Преобразовать размер шрифта в единицы карты
+ * @param { string | Number } v Значение для перевода "10mm", "22pt"
+ * @param {*} ppu Pixel per unit
+ * @returns
+ */
+ fontsize2ppu(v, ppu) {
+ if (typeof v !== "string") return v;
- // {x,y,ring[1,2,3,4,5]}
- ring(x, y, r0, r1, a0, a1, style) {
- return SvgNodes.ring_sector(r0, r1, a0, a1).move(x, y).set_style(style);
- },
- };
+ if (v.endsWith("mm")) {
+ return parseFloat(v.substring(0, v.length - 2) * ppu * 100) / 69;
+ }
+ if (v.endsWith("pt")) {
+ return (parseFloat(v.slice(0, v.length - 2)) * ppu * 100) / 283.46;
+ }
+ }
+ /**
+ * Перегоняет стиль в единицы карты (возвращает новый объект)
+ * @param {*} style Объект стиля для преобразования
+ * @param {*} ppu Pixel per unit
+ */
+ update_style(style, ppu) {
+ let s = Object.assign({}, style);
+ const convertable = ["font-size", "stroke-width"];
+ Object.keys(s).forEach((k) => {
+ if (convertable.includes(k)) s[k] = this.fontsize2ppu(s[k], ppu);
+ });
+ return s;
+ }
-}
\ No newline at end of file
+ /**
+ * Перегоняет все стили в единицы карты (возвращает новый объект)
+ * @param {*} style Объект стиля для преобразования
+ * @param {*} ppu Pixel per unit
+ */
+ update_styles(styles, ppu) {
+ return Object.keys(styles).reduce((s, c) => ({ ...s, [c]: this.update_style(styles[c], ppu) }), {});
+ }
+
+ build_tp_layer(wells, settings) {
+ function t2r(tons) {
+ // tonns/mm2 = tonns/cm2 / 100. S(mm)=Pi*r*r=tons/tons_in_cm2*100. r = sqrt(tons/tons_in_cm2*100 / PI)
+ return Math.sqrt(((tons / settings.tons_in_cm2) * 100) / Math.PI);
+ }
+
+ let { ppu, styles } = settings;
+
+ let defs = new SvgNode("defs");
+ defs.append(SvgNodes.defs.simple.radialGradient("rg_opt", "#fff", "#B86B41"));
+ defs.append(SvgNodes.defs.simple.radialGradient("rg_wpt", "#fff", "#67c2e5"));
+
+ let svg = SvgNodes.group(['']).set_attr("id", "WWPT");
+ // Круги
+ svg.append(
+ wells.map((x) =>
+ SvgNodes.ring_sectors(1.5 * ppu, t2r(x.wlpt) * ppu, [
+ { v: x.wopt, style: styles.opt },
+ { v: x.wwpt, style: styles.wpt },
+ ]).move(x.lx, x.ly)
+ )
+ );
+ // Знак скважины
+ svg.append(
+ wells.map((x) =>
+ SvgNodes.circle(1.5 * ppu)
+ .move(x.lx, x.ly)
+ .set_style(styles.wellhead)
+ )
+ );
+ // Имя скважины
+ svg.append(
+ wells.map((x) =>
+ SvgNodes.text(x.well)
+ .move(x.lx + styles.wellhead.dx * ppu, x.ly + styles.wellhead.dy * ppu)
+ .set_style(styles.wellhead)
+ )
+ );
+ // Обводненность
+ svg.append(
+ wells.map((x) =>
+ SvgNodes.text(`${Math.round(x.wlf * 1000) / 10 || ""}%`)
+ .move(x.lx + styles.wlf.dx * ppu, x.ly + styles.wlf.dy * ppu)
+ .set_style(styles.wlf)
+ )
+ );
+
+ return { defs, svg };
+ }
+
+ build_ti_layer(wells, settings) {
+ function t2r(tons) {
+ // tonns/mm2 = tonns/cm2 / 100. S(mm)=Pi*r*r=tons/tons_in_cm2*100. r = sqrt(tons/tons_in_cm2*100 / PI)
+ return Math.sqrt(((tons / settings.tons_in_cm2) * 100) / Math.PI);
+ }
+
+ let { ppu, styles } = settings;
+
+ let defs = new SvgNode("defs");
+ defs.append(SvgNodes.defs.simple.radialGradient("rg1", "#fff", "#c1ff5e"));
+
+ let svg = SvgNodes.group(['']).set_attr("id", "WWIT");
+ // Круги
+ // let g_rings = SvgNodes.group(['']).set_attr("id", "Круги")
+ // svg.append(g_rings)
+ svg.append(
+ wells.map((x) =>
+ SvgNodes.circle(t2r(x.wwit) * ppu)
+ .set_style(styles.wit)
+ .move(x.lx, x.ly)
+ )
+ );
+ // Знак скважины
+ svg.append(
+ wells.map((x) =>
+ SvgNodes.circle(1.5 * ppu)
+ .move(x.lx, x.ly)
+ .set_style(styles.wellhead)
+ )
+ );
+ // Имя скважины
+ svg.append(
+ wells.map((x) =>
+ SvgNodes.text(x.well)
+ .move(x.lx + styles.wellhead.dx * ppu, x.ly + styles.wellhead.dy * ppu)
+ .set_style(styles.wellhead)
+ )
+ );
+ // Обводненность
+ svg.append(
+ wells.map((x) =>
+ SvgNodes.text(`${Math.round(x.wlf * 1000) / 10 || ""}%`)
+ .move(x.lx + styles.wlf.dx * ppu, x.ly + styles.wlf.dy * ppu)
+ .set_style(styles.wlf)
+ )
+ );
+
+ return { defs, svg };
+ }
+}
diff --git a/src/svgmap/SvgMapParser.js b/src/svgmap/SvgMapParser.js
deleted file mode 100644
index 006fe31..0000000
--- a/src/svgmap/SvgMapParser.js
+++ /dev/null
@@ -1,74 +0,0 @@
-// import convert from 'xml-js/index.js'
-// import { XMLParser, XMLBuilder, XMLValidator} from 'fast-xml-parser'
-import { parse } from 'svg-parser'
-
-// var convert = require('xml-js');
-
-export default class {
- async parse(xml){
- let result1 = parse(xml);
-
- this.svg = result1.children.filter(x => x.tagName =='svg')[0]
- }
-
- get_layers(){
- return this.svg.children.filter(x => x.tagName == 'g')
- }
-
- get_map_scale(){
- // console.log(this.svg)
- let vb = this.svg.properties.viewBox.split(' ').map(x => parseFloat(x))
- let w = this.svg.properties.width
- let h = this.svg.properties.height
-
- let units = {
- 'in': 25.4,
- 'mm': 1,
- 'cm': 10,
- 'px': 0.0846646,
- // '%': 1
- }
-
- const u = Object.keys(units).filter(x => w.endsWith(x))[0]
- if (!u) throw "Unsupported units"
-
- w = Math.round(parseFloat(w.substring(0, w.length - u.length)) * units[u] * 100) / 100
- h = Math.round(parseFloat(h.substring(0, h.length - u.length)) * units[u] * 100) / 100
- let k = vb[2] / w
-
- return {w, h, k, u}
- }
-
- extract_anchor(layer){
- let w1 = this.extract_well(layer.children[layer.children.length - 1])
- let w2 = this.extract_well(layer.children[layer.children.length - 2])
-
- return{w1, w2}
- }
-
- _flat(node){
- if (!node.children) return [node];
- return node.children.reduce((s, c) => s.concat(this._flat(c)), [node])
- }
-
- extract_well(pivot_group){
- let scale = this.get_map_scale()
-
- let flat = this._flat(pivot_group)
- ///// console.log('pivot_group', pivot_group.children)
- // console.log('FLAT---', flat)
- let ellipse = flat.filter(x => x.tagName =='circle' || x.tagName =='ellipse')[0]
- // console.log('ellipse', ellipse)
- let tr = ellipse.properties.transform.replace('matrix(', '').replace(')', '').split(' ').map(x => parseFloat(x))
- // console.log('tr', tr)
- // let x = ellipse.properties.transform
- // let y = ellipse.cy.baseVal.value
-
- let text = flat.filter(x => x.type =='text')[0]
- // console.log('text', text)
- let name = text.value
- return {x: tr[4], y: tr[5], name}
- }
-
-
-}
\ No newline at end of file
diff --git a/src/svgmap/SvgNode.js b/src/svgmap/SvgNode.js
index de9ef46..be12bbf 100644
--- a/src/svgmap/SvgNode.js
+++ b/src/svgmap/SvgNode.js
@@ -5,8 +5,8 @@ export default class SvgNode {
this.items = items || []
}
- append(items){
- this.items.push(items)
+ append(...items){
+ this.items.push(...items)
return this
}
@@ -49,13 +49,16 @@ export default class SvgNode {
}
render() {
- let attrs = Object.keys(this.attrs).map(x => ` ${x}="${this.attrs[x]}"`).join('')
+ let attrs = Object.keys(this.attrs).filter(x => this.attrs[x]).map(x => ` ${x}="${this.attrs[x]}"`).join('')
// console.log(this.style ? Object.keys(this.style).map(x => `${x}:${this.style[x]}`) : '')
let style = this.style ? ' style="' + Object.keys(this.style).map(x => `${x}:${this.style[x]}`).join('; ') + '"' : ''
let transfrom = this.transform ? ` transform="translate(${this.transform.x},${this.transform.y})"` : ''
let items = this.items ? this.items.map(x => this._render_node(x)).join('') : ''
// console.log('this.items', this.items, items)
- return `<${this.tag}${attrs}${style}${transfrom}>${items}${this.tag}>`
+ if (this.tag)
+ return `<${this.tag}${attrs}${style}${transfrom}>${items}${this.tag}>`
+ else
+ return items
}
}
\ No newline at end of file
diff --git a/src/svgmap/SvgNodes.js b/src/svgmap/SvgNodes.js
index ded6616..b692b74 100644
--- a/src/svgmap/SvgNodes.js
+++ b/src/svgmap/SvgNodes.js
@@ -26,6 +26,10 @@ export default {
})
},
+ container(items){
+ return new SvgNode(null, null, items)
+ },
+
group(items){
return new SvgNode("g", null, items)
},
@@ -86,6 +90,26 @@ export default {
node.items = [text];
node.set_attrs({x: 0, y: 0})
return node;
+ },
+
+ defs: {
+ simple: {
+ radialGradient(id, color0, color1){
+ let s0 = new SvgNode("stop", {offset: "0%", "stop-color": color0})
+ let s1 = new SvgNode("stop", {offset: "100%", "stop-color": color1})
+ return new SvgNode("radialGradient", {id}).append(s0, s1)
+ }
+ },
+
+ radialGradient(id, cx, cy, r){
+ return new SvgNode("radialGradient", {id, cx, cy, r})
+ },
+
+ stop(offset, color){
+ return new SvgNode("stop", {offset, "stop-color": color})
+ },
+
+
}
};