| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676 |
- //init
- WALLS = [];
- OBJDATA = [];
- ROOM = [];
- HISTORY = [];
- wallSize = 20;
- partitionSize = 8;
- let drag = 'off';
- let action = 0;
- let magnetic = 0;
- let construc = 0;
- let Rcirclebinder = 8;
- let mode = 'select_mode';
- let modeOption;
- let linElement = $('#lin');
- taille_w = linElement.width();
- taille_h = linElement.height();
- let offset = linElement.offset();
- // Debug: log initial floorplan image (background) width, height, and offset (x,y)
- try {
- const bgEl = (typeof document !== 'undefined') ? document.getElementById('backgroundImage') : null;
- if (bgEl) {
- const parseNum = (v, d=0) => { const n = parseFloat(v); return isFinite(n) ? n : d; };
- const fw = parseNum(bgEl.getAttribute('width'));
- const fh = parseNum(bgEl.getAttribute('height'));
- const fx = parseNum(bgEl.getAttribute('x'));
- const fy = parseNum(bgEl.getAttribute('y'));
- console.info('[init] floorplan image', { width: fw, height: fh, offset: { x: fx, y: fy } });
- }
- } catch (_) {}
- grid = 20;
- showRib = true;
- showArea = true;
- meter = 60;
- grid_snap = 'off';
- colorbackground = "#ffffff";
- colorline = "#fff";
- colorroom = "#f0daaf";
- colorWall = "#666";
- pox = 0;
- poy = 0;
- segment = 0;
- xpath = 0;
- ypath = 0;
- let width_viewbox = taille_w;
- let height_viewbox = taille_h;
- let ratio_viewbox = height_viewbox / width_viewbox;
- let originX_viewbox = 0;
- let originY_viewbox = 0;
- let zoom = 9;
- let factor = 1;
- // **************************************************************************
- // ***************** LOAD / SAVE LOCALSTORAGE ************************
- // **************************************************************************
- function initHistory(boot = false) {
- HISTORY.index = 0;
- // Preserve existing history across sessions to allow restoring background image metrics.
- // Do not clear here; new plan initializers below will explicitly clear when appropriate.
- // if (!boot && localStorage.getItem('history')) localStorage.removeItem('history');
- if (localStorage.getItem('history') && boot === "recovery") {
- let historyTemp = JSON.parse(localStorage.getItem('history'));
- load(historyTemp.length - 1, "boot");
- save("boot");
- }
- if (boot === "newSquare") {
- if (localStorage.getItem('history')) localStorage.removeItem('history');
- HISTORY.push({
- "objData": [],
- "wallData": [{
- "thick": 20,
- "start": { "x": 540, "y": 194 },
- "end": { "x": 540, "y": 734 },
- "type": "normal",
- "parent": 3,
- "child": 1,
- "angle": 1.5707963267948966,
- "equations": { "up": { "A": "v", "B": 550 }, "down": { "A": "v", "B": 530 }, "base": { "A": "v", "B": 540 } },
- "coords": [{ "x": 550, "y": 204 }, { "x": 530, "y": 184 }, { "x": 530, "y": 744 }, { "x": 550, "y": 724 }],
- "graph": { "0": {}, "context": {}, "length": 1 }
- }, {
- "thick": 20,
- "start": { "x": 540, "y": 734 },
- "end": { "x": 1080, "y": 734 },
- "type": "normal",
- "parent": 0,
- "child": 2,
- "angle": 0,
- "equations": { "up": { "A": "h", "B": 724 }, "down": { "A": "h", "B": 744 }, "base": { "A": "h", "B": 734 } },
- "coords": [{ "x": 550, "y": 724 }, { "x": 530, "y": 744 }, { "x": 1090, "y": 744 }, { "x": 1070, "y": 724 }],
- "graph": { "0": {}, "context": {}, "length": 1 }
- }, {
- "thick": 20,
- "start": { "x": 1080, "y": 734 },
- "end": { "x": 1080, "y": 194 },
- "type": "normal",
- "parent": 1,
- "child": 3,
- "angle": -1.5707963267948966,
- "equations": {
- "up": { "A": "v", "B": 1070 },
- "down": { "A": "v", "B": 1090 },
- "base": { "A": "v", "B": 1080 }
- },
- "coords": [{ "x": 1070, "y": 724 }, { "x": 1090, "y": 744 }, { "x": 1090, "y": 184 }, { "x": 1070, "y": 204 }],
- "graph": { "0": {}, "context": {}, "length": 1 }
- }, {
- "thick": 20,
- "start": { "x": 1080, "y": 194 },
- "end": { "x": 540, "y": 194 },
- "type": "normal",
- "parent": 2,
- "child": 0,
- "angle": 3.141592653589793,
- "equations": { "up": { "A": "h", "B": 204 }, "down": { "A": "h", "B": 184 }, "base": { "A": "h", "B": 194 } },
- "coords": [{ "x": 1070, "y": 204 }, { "x": 1090, "y": 184 }, { "x": 530, "y": 184 }, { "x": 550, "y": 204 }],
- "graph": { "0": {}, "context": {}, "length": 1 }
- }],
- "roomData": [{
- "coords": [{ "x": 540, "y": 734 }, { "x": 1080, "y": 734 }, { "x": 1080, "y": 194 }, {
- "x": 540,
- "y": 194
- }, { "x": 540, "y": 734 }],
- "coordsOutside": [{ "x": 1090, "y": 744 }, { "x": 1090, "y": 184 }, { "x": 530, "y": 184 }, {
- "x": 530,
- "y": 744
- }, { "x": 1090, "y": 744 }],
- "coordsInside": [{ "x": 1070, "y": 724 }, { "x": 1070, "y": 204 }, { "x": 550, "y": 204 }, {
- "x": 550,
- "y": 724
- }, { "x": 1070, "y": 724 }],
- "inside": [],
- "way": ["0", "2", "3", "1", "0"],
- "area": 270400,
- "surface": "",
- "name": "",
- "color": "gradientWhite",
- "showSurface": true,
- "action": "add"
- }]
- });
- HISTORY[0] = JSON.stringify(HISTORY[0]);
- localStorage.setItem('history', JSON.stringify(HISTORY));
- load(0);
- save();
- }
- if (boot === "newL") {
- if (localStorage.getItem('history')) localStorage.removeItem('history');
- HISTORY.push({
- "objData": [],
- "wallData": [{
- "thick": 20,
- "start": { "x": 447, "y": 458 },
- "end": { "x": 447, "y": 744 },
- "type": "normal",
- "parent": 5,
- "child": 1,
- "angle": 1.5707963267948966,
- "equations": { "up": { "A": "v", "B": 457 }, "down": { "A": "v", "B": 437 }, "base": { "A": "v", "B": 447 } },
- "coords": [{ "x": 457, "y": 468 }, { "x": 437, "y": 448 }, { "x": 437, "y": 754 }, { "x": 457, "y": 734 }],
- "graph": { "0": {}, "context": {}, "length": 1 }
- }, {
- "thick": 20,
- "start": { "x": 447, "y": 744 },
- "end": { "x": 1347, "y": 744 },
- "type": "normal",
- "parent": 0,
- "child": 2,
- "angle": 0,
- "equations": { "up": { "A": "h", "B": 734 }, "down": { "A": "h", "B": 754 }, "base": { "A": "h", "B": 744 } },
- "coords": [{ "x": 457, "y": 734 }, { "x": 437, "y": 754 }, { "x": 1357, "y": 754 }, { "x": 1337, "y": 734 }],
- "graph": { "0": {}, "context": {}, "length": 1 }
- }, {
- "thick": 20,
- "start": { "x": 1347, "y": 744 },
- "end": { "x": 1347, "y": 144 },
- "type": "normal",
- "parent": 1,
- "child": 3,
- "angle": -1.5707963267948966,
- "equations": {
- "up": { "A": "v", "B": 1337 },
- "down": { "A": "v", "B": 1357 },
- "base": { "A": "v", "B": 1347 }
- },
- "coords": [{ "x": 1337, "y": 734 }, { "x": 1357, "y": 754 }, { "x": 1357, "y": 134 }, { "x": 1337, "y": 154 }],
- "graph": { "0": {}, "context": {}, "length": 1 }
- }, {
- "thick": 20,
- "start": { "x": 1347, "y": 144 },
- "end": { "x": 1020, "y": 144 },
- "type": "normal",
- "parent": 2,
- "child": 4,
- "angle": 3.141592653589793,
- "equations": { "up": { "A": "h", "B": 154 }, "down": { "A": "h", "B": 134 }, "base": { "A": "h", "B": 144 } },
- "coords": [{ "x": 1337, "y": 154 }, { "x": 1357, "y": 134 }, { "x": 1010, "y": 134 }, { "x": 1030, "y": 154 }],
- "graph": { "0": {}, "context": {}, "length": 1 }
- }, {
- "thick": 20,
- "start": { "x": 1020, "y": 144 },
- "end": { "x": 1020, "y": 458 },
- "type": "normal",
- "parent": 3,
- "child": 5,
- "angle": 1.5707963267948966,
- "equations": {
- "up": { "A": "v", "B": 1030 },
- "down": { "A": "v", "B": 1010 },
- "base": { "A": "v", "B": 1020 }
- },
- "coords": [{ "x": 1030, "y": 154 }, { "x": 1010, "y": 134 }, { "x": 1010, "y": 448 }, { "x": 1030, "y": 468 }],
- "graph": { "0": {}, "context": {}, "length": 1 }
- }, {
- "thick": 20,
- "start": { "x": 1020, "y": 458 },
- "end": { "x": 447, "y": 458 },
- "type": "normal",
- "parent": 4,
- "child": 0,
- "angle": 3.141592653589793,
- "equations": { "up": { "A": "h", "B": 468 }, "down": { "A": "h", "B": 448 }, "base": { "A": "h", "B": 458 } },
- "coords": [{ "x": 1030, "y": 468 }, { "x": 1010, "y": 448 }, { "x": 437, "y": 448 }, { "x": 457, "y": 468 }],
- "graph": { "0": {}, "context": {}, "length": 1 }
- }],
- "roomData": [{
- "coords": [{ "x": 447, "y": 744 }, { "x": 1347, "y": 744 }, { "x": 1347, "y": 144 }, {
- "x": 1020,
- "y": 144
- }, { "x": 1020, "y": 458 }, { "x": 447, "y": 458 }, { "x": 447, "y": 744 }],
- "coordsOutside": [{ "x": 1357, "y": 754 }, { "x": 1357, "y": 134 }, { "x": 1010, "y": 134 }, {
- "x": 1010,
- "y": 448
- }, { "x": 437, "y": 448 }, { "x": 437, "y": 754 }, { "x": 1357, "y": 754 }],
- "coordsInside": [{ "x": 1337, "y": 734 }, { "x": 1337, "y": 154 }, { "x": 1030, "y": 154 }, {
- "x": 1030,
- "y": 468
- }, { "x": 457, "y": 468 }, { "x": 457, "y": 734 }, { "x": 1337, "y": 734 }],
- "inside": [],
- "way": ["0", "2", "3", "4", "5", "1", "0"],
- "area": 330478,
- "surface": "",
- "name": "",
- "color": "gradientWhite",
- "showSurface": true,
- "action": "add"
- }]
- });
- HISTORY[0] = JSON.stringify(HISTORY[0]);
- localStorage.setItem('history', JSON.stringify(HISTORY));
- load(0);
- save();
- }
- }
- document.getElementById('redo').addEventListener("click", function () {
- if (HISTORY.index < HISTORY.length) {
- load(HISTORY.index);
- HISTORY.index++;
- $('#undo').removeClass('disabled');
- if (HISTORY.index === HISTORY.length) {
- $('#redo').addClass('disabled');
- }
- }
- });
- document.getElementById('undo').addEventListener("click", function () {
- if (HISTORY.index > 0) {
- $('#undo').removeClass('disabled');
- if (HISTORY.index - 1 > 0) {
- HISTORY.index--;
- load(HISTORY.index - 1);
- $('#redo').removeClass('disabled');
- }
- }
- if (HISTORY.index === 1) $('#undo').addClass('disabled');
- });
- function save(boot = false) {
- // Only clear history on explicit boolean true; avoid clearing when called with strings like "boot"
- if (boot === true) localStorage.removeItem('history');
- // If background image sizing is in progress, defer save to avoid capturing default geometry
- try {
- if (typeof window !== 'undefined' && window.__bgSizing) {
- if (typeof console !== 'undefined' && console.debug) {
- console.debug('[save] deferred: background image sizing in progress');
- }
- setTimeout(function(){ try { save(boot); } catch(_){} }, 50);
- return false;
- }
- } catch(_) {}
- // FOR CYCLIC OBJ INTO LOCALSTORAGE !!!
- for (let k in WALLS) {
- if (WALLS[k].child != null) {
- WALLS[k].child = WALLS.indexOf(WALLS[k].child);
- }
- if (WALLS[k].parent != null) {
- WALLS[k].parent = WALLS.indexOf(WALLS[k].parent);
- }
- }
- // Gather background image state if present; if element is absent, carry over from previous snapshot to avoid reset
- const __bgImgEl = (typeof document !== 'undefined') ? document.getElementById('backgroundImage') : null;
- // Read previous snapshot (if any) to preserve background image when not present in DOM
- let __prevSnap = null;
- try { if (HISTORY && HISTORY.length > 0) { __prevSnap = JSON.parse(HISTORY[HISTORY.length - 1]); } } catch(_) {}
- // Fallback: read from localStorage history if in-memory HISTORY is empty or unparsable
- if (!__prevSnap) {
- try {
- const __ls = localStorage.getItem('history');
- if (__ls) {
- const __arr = JSON.parse(__ls);
- if (Array.isArray(__arr) && __arr.length > 0) {
- __prevSnap = JSON.parse(__arr[__arr.length - 1]);
- }
- }
- } catch(_) {}
- }
- const backgroundImage = (__bgImgEl) ? (function(el){
- const parseNum = (v, d=0) => { const n = parseFloat(v); return isFinite(n) ? n : d; };
- const x = parseNum(el.getAttribute('x'), 0);
- const y = parseNum(el.getAttribute('y'), 0);
- const width = parseNum(el.getAttribute('width'), 0);
- const height = parseNum(el.getAttribute('height'), 0);
- let opacity = parseNum(el.getAttribute('opacity'), 1);
- if (!isFinite(opacity) || opacity <= 0) opacity = 1;
- const href = el.getAttribute('href') || el.getAttribute('xlink:href') || '';
- // Try to attach fileName from currentBackgroundImage reference if available
- let fileName = null;
- try { if (window.currentBackgroundImage && window.currentBackgroundImage.fileName) fileName = window.currentBackgroundImage.fileName; } catch(_) {}
- const snapshot = { x, y, width, height, opacity, href, fileName };
- try { if (typeof console !== 'undefined' && console.debug) console.debug('[save] backgroundImage snapshot', snapshot); } catch(_) {}
- return snapshot;
- })(__bgImgEl) : (__prevSnap && __prevSnap.backgroundImage ? __prevSnap.backgroundImage : null);
- const snapshot = { objData: OBJDATA, wallData: WALLS, roomData: ROOM, furnitureData: getFurnitureData(), backgroundImage };
- // If caller requests suppression and we'd drop background image (DOM missing) while previous snapshot has one, skip pushing
- try {
- if (typeof window !== 'undefined' && window.__suppressSaveIfNoBg) {
- const hasDomBg = !!__bgImgEl;
- const hadPrevBg = !!(__prevSnap && __prevSnap.backgroundImage);
- if (!hasDomBg && hadPrevBg) {
- if (typeof console !== 'undefined' && console.debug) {
- console.debug('[save] suppressed: no DOM backgroundImage while previous snapshot had one');
- }
- // Clear the suppression flag for subsequent saves
- window.__suppressSaveIfNoBg = false;
- return false;
- }
- // Clear flag if we proceed
- window.__suppressSaveIfNoBg = false;
- }
- } catch(_) {}
- if (JSON.stringify(snapshot) === HISTORY[HISTORY.length - 1]) {
- for (let k in WALLS) {
- if (WALLS[k].child != null) {
- WALLS[k].child = WALLS[WALLS[k].child];
- }
- if (WALLS[k].parent != null) {
- WALLS[k].parent = WALLS[WALLS[k].parent];
- }
- }
- return false;
- }
- if (HISTORY.index < HISTORY.length) {
- HISTORY.splice(HISTORY.index, (HISTORY.length - HISTORY.index));
- $('#redo').addClass('disabled');
- }
- HISTORY.push(JSON.stringify(snapshot));
- localStorage.setItem('history', JSON.stringify(HISTORY));
- HISTORY.index++;
- // Log when state is saved to history along with current floorplan image metrics
- try {
- const bgEl = (typeof document !== 'undefined') ? document.getElementById('backgroundImage') : null;
- if (bgEl) {
- const parseNum = (v, d=0) => { const n = parseFloat(v); return isFinite(n) ? n : d; };
- const fw = parseNum(bgEl.getAttribute('width'));
- const fh = parseNum(bgEl.getAttribute('height'));
- const fx = parseNum(bgEl.getAttribute('x'));
- const fy = parseNum(bgEl.getAttribute('y'));
- console.info('[save] snapshot pushed', { historyIndex: HISTORY.index, width: fw, height: fh, offset: { x: fx, y: fy } });
- } else if (backgroundImage) {
- console.info('[save] snapshot pushed', { historyIndex: HISTORY.index, width: backgroundImage.width, height: backgroundImage.height, offset: { x: backgroundImage.x, y: backgroundImage.y }, note: 'carried over previous backgroundImage' });
- } else {
- console.info('[save] snapshot pushed', { historyIndex: HISTORY.index, note: 'no backgroundImage' });
- }
- } catch (_) {}
- if (HISTORY.index > 1) $('#undo').removeClass('disabled');
- for (let k in WALLS) {
- if (WALLS[k].child != null) {
- WALLS[k].child = WALLS[WALLS[k].child];
- }
- if (WALLS[k].parent != null) {
- WALLS[k].parent = WALLS[WALLS[k].parent];
- }
- }
- return true;
- }
- function load(index = HISTORY.index, boot = false) {
- if (HISTORY.length === 0 && !boot) return false;
- for (let k in OBJDATA) {
- OBJDATA[k].graph.remove();
- }
- OBJDATA = [];
- let historyTemp = [];
- historyTemp = JSON.parse(localStorage.getItem('history'));
- historyTemp = JSON.parse(historyTemp[index]);
- for (let k in historyTemp.objData) {
- let OO = historyTemp.objData[k];
- // if (OO.family === 'energy') OO.family = 'byObject';
- let obj = new editor.obj2D(OO.family, OO.class, OO.type, {
- x: OO.x,
- y: OO.y
- }, OO.angle, OO.angleSign, OO.size, OO.hinge = 'normal', OO.thick, OO.value);
- obj.limit = OO.limit;
- OBJDATA.push(obj);
- $('#boxcarpentry').append(OBJDATA[OBJDATA.length - 1].graph);
- obj.update();
- }
- WALLS = historyTemp.wallData;
- for (let k in WALLS) {
- if (WALLS[k].child != null) {
- WALLS[k].child = WALLS[WALLS[k].child];
- }
- if (WALLS[k].parent != null) {
- WALLS[k].parent = WALLS[WALLS[k].parent];
- }
- }
- ROOM = historyTemp.roomData;
- // Load furniture data if it exists
- if (historyTemp.furnitureData) {
- loadSavedFurnitureData(historyTemp.furnitureData);
- }
- // Restore background image properties if present and an image exists in DOM
- try {
- if (historyTemp.backgroundImage) {
- const bgEl = (typeof document !== 'undefined') ? document.getElementById('backgroundImage') : null;
- if (bgEl) {
- // Only restore if it's the same image as saved (match href)
- const currentHref = bgEl.getAttribute('href') || bgEl.getAttribute('xlink:href') || '';
- const savedHref = historyTemp.backgroundImage.href || '';
- try { if (console && console.debug) console.debug('[load] backgroundImage found', { currentHref, savedHref, props: historyTemp.backgroundImage }); } catch(_) {}
- if (savedHref && currentHref && currentHref === savedHref) {
- try { if (console && console.debug) console.debug('[load] applying saved backgroundImage props'); } catch(_) {}
- if (typeof adjustBackgroundImage === 'function') {
- adjustBackgroundImage(historyTemp.backgroundImage);
- } else {
- const props = historyTemp.backgroundImage;
- if (props.x !== undefined) bgEl.setAttribute('x', props.x);
- if (props.y !== undefined) bgEl.setAttribute('y', props.y);
- if (props.width !== undefined) bgEl.setAttribute('width', props.width);
- if (props.height !== undefined) bgEl.setAttribute('height', props.height);
- if (props.opacity !== undefined) bgEl.setAttribute('opacity', props.opacity);
- }
- } else {
- try { if (console && console.debug) console.debug('[load] skipping apply: href mismatch or missing'); } catch(_) {}
- }
- } else {
- try { if (console && console.debug) console.debug('[load] no #backgroundImage element to restore to'); } catch(_) {}
- }
- }
- } catch (e) {
- console.warn('Error restoring background image properties:', e);
- }
- // Update UI: filename display and Floorplan mode button based on background image presence
- try {
- const bgEl = (typeof document !== 'undefined') ? document.getElementById('backgroundImage') : null;
- const nameEl = (typeof document !== 'undefined') ? document.getElementById('floorplan_filename') : null;
- const btn = (typeof document !== 'undefined') ? document.getElementById('floorplan_mode_btn') : null;
- if (bgEl) {
- // Enable button and show saved filename if available
- if (btn) btn.disabled = false;
- if (nameEl) {
- const savedName = (historyTemp.backgroundImage && historyTemp.backgroundImage.fileName) ? historyTemp.backgroundImage.fileName : '';
- nameEl.textContent = savedName;
- }
- } else {
- // No background image element yet: show last used filename if available but keep button disabled
- if (nameEl) {
- const savedName = (historyTemp.backgroundImage && historyTemp.backgroundImage.fileName) ? historyTemp.backgroundImage.fileName : '';
- nameEl.textContent = savedName;
- }
- if (btn) {
- btn.disabled = true;
- btn.innerText = 'Floorplan mode';
- }
- if (window.__floorplanMode && typeof exitFloorplanMode === 'function') {
- exitFloorplanMode();
- }
- }
- } catch(_) {}
- editor.architect(WALLS);
- editor.showScaleBox();
- rib();
- // Ensure we default to select mode after loading a snapshot
- try {
- if (typeof $ !== 'undefined') {
- $('#boxinfo').html('Mode "select"');
- // Clear any lingering binders
- if (typeof binder !== 'undefined') {
- try { if (binder.graph) $(binder.graph).remove(); else if (binder.remove) binder.remove(); } catch (e) {}
- $('#boxbind').empty();
- binder = undefined;
- }
- // Update buttons UI without triggering a save (avoid fonc_button which calls save())
- if (typeof raz_button === 'function') raz_button();
- $('#select_mode').removeClass('btn-default').addClass('btn-success');
- }
- mode = 'select_mode';
- } catch(_) {}
- }
- $('svg').each(function () {
- $(this)[0].setAttribute('viewBox', originX_viewbox + ' ' + originY_viewbox + ' ' + width_viewbox + ' ' + height_viewbox)
- });
- // **************************************************************************
- // ***************** FUNCTIONS ON BUTTON click ************************
- // **************************************************************************
- document.getElementById('report_mode').addEventListener("click", function () {
- if (typeof (globalArea) === "undefined") return false;
- mode = "report_mode";
- $('#panel').hide();
- $('#reportTools').show(200)
- document.getElementById('reportTotalSurface').innerHTML = "Total surface : <b>" + (globalArea / 3600).toFixed(1) + "</b> m²";
- $('#reportTotalSurface').show(1000);
- document.getElementById('reportNumberSurface').innerHTML = "Number of rooms : <b>" + ROOM.length + "</b>";
- $('#reportNumberSurface').show(1000);
- let number = 1;
- let reportRoom = '<div class="row">\n';
- for (let k in ROOM) {
- let nameRoom = "Room n°" + number + " <small>(sans nom)</small>";
- if (ROOM[k].name != "") nameRoom = ROOM[k].name;
- reportRoom += '<div class="col-md-6"><p>' + nameRoom + '</p></div>\n';
- reportRoom += '<div class="col-md-6"><p>Surface : <b>' + ((ROOM[k].area) / 3600).toFixed(2) + '</b> m²</p></div>\n';
- number++;
- }
- reportRoom += '</div><hr/>\n';
- reportRoom += '<div>\n';
- let switchNumber = 0;
- let plugNumber = 0;
- let lampNumber = 0;
- for (let k in OBJDATA) {
- if (OBJDATA[k].class === 'energy') {
- if (OBJDATA[k].type === 'switch' || OBJDATA[k].type === 'doubleSwitch' || OBJDATA[k].type === 'dimmer') switchNumber++;
- if (OBJDATA[k].type === 'plug' || OBJDATA[k].type === 'plug20' || OBJDATA[k].type === 'plug32') plugNumber++;
- if (OBJDATA[k].type === 'wallLight' || OBJDATA[k].type === 'roofLight') lampNumber++;
- }
- }
- reportRoom += '<p>Switch number : ' + switchNumber + '</p>';
- reportRoom += '<p>Electric outlet number : ' + plugNumber + '</p>';
- reportRoom += '<p>Light point number : ' + lampNumber + '</p>';
- reportRoom += '</div>';
- reportRoom += '<div>\n';
- reportRoom += '<h2>Energy distribution per room</h2>\n';
- number = 1;
- reportRoom += '<div class="row">\n';
- reportRoom += '<div class="col-md-4"><p>Label</p></div>\n';
- reportRoom += '<div class="col-md-2"><small>Swi.</small></div>\n';
- reportRoom += '<div class="col-md-2"><small>Elec. out.</small></div>\n';
- reportRoom += '<div class="col-md-2"><small>Light.</small></div>\n';
- reportRoom += '<div class="col-md-2"><small>Watts Max</small></div>\n';
- reportRoom += '</div>';
- let roomEnergy = [];
- for (let k in ROOM) {
- reportRoom += '<div class="row">\n';
- let nameRoom = "Room n°" + number + " <small>(no name)</small>";
- if (ROOM[k].name != "") nameRoom = ROOM[k].name;
- reportRoom += '<div class="col-md-4"><p>' + nameRoom + '</p></div>\n';
- switchNumber = 0;
- plugNumber = 0;
- let plug20 = 0;
- let plug32 = 0;
- lampNumber = 0;
- let wattMax = 0;
- let plug = false;
- for (let i in OBJDATA) {
- if (OBJDATA[i].class === 'energy') {
- if (OBJDATA[i].type === 'switch' || OBJDATA[i].type === 'doubleSwitch' || OBJDATA[i].type === 'dimmer') {
- if (roomTarget = editor.rayCastingRoom(OBJDATA[i])) {
- if (isObjectsEquals(ROOM[k], roomTarget)) switchNumber++;
- }
- }
- if (OBJDATA[i].type === 'plug' || OBJDATA[i].type === 'plug20' || OBJDATA[i].type === 'plug32') {
- if (roomTarget = editor.rayCastingRoom(OBJDATA[i])) {
- if (isObjectsEquals(ROOM[k], roomTarget)) {
- plugNumber++;
- if (OBJDATA[i].type === 'plug' && !plug) {
- wattMax += 3520;
- plug = true;
- }
- if (OBJDATA[i].type === 'plug20') {
- wattMax += 4400;
- plug20++;
- }
- if (OBJDATA[i].type === 'plug32') {
- wattMax += 7040;
- plug32++;
- }
- }
- }
- }
- if (OBJDATA[i].type === 'wallLight' || OBJDATA[i].type === 'roofLight') {
- if (roomTarget = editor.rayCastingRoom(OBJDATA[i])) {
- if (isObjectsEquals(ROOM[k], roomTarget)) {
- lampNumber++;
- wattMax += 100;
- }
- }
- }
- }
- }
- roomEnergy.push({
- switch: switchNumber,
- plug: plugNumber,
- plug20: plug20,
- plug32: plug32,
- light: lampNumber
- });
- reportRoom += '<div class="col-md-2"><b>' + switchNumber + '</b></div>\n';
- reportRoom += '<div class="col-md-2"><b>' + plugNumber + '</b></div>\n';
- reportRoom += '<div class="col-md-2"><b>' + lampNumber + '</b></div>\n';
- reportRoom += '<div class="col-md-2"><b>' + wattMax + '</b></div>\n';
- number++;
- reportRoom += '</div>';
- }
- reportRoom += '<hr/><h2>Standard details NF C 15-100</h2>\n';
- number = 1;
- for (let k in ROOM) {
- reportRoom += '<div class="row">\n';
- let nfc = true;
- let nameRoom = "Room n°" + number + " <small>(no name)</small>";
- if (ROOM[k].name != "") nameRoom = ROOM[k].name;
- reportRoom += '<div class="col-md-4"><p>' + nameRoom + '</p></div>\n';
- if (ROOM[k].name === "") {
- reportRoom +=
- '<div class="col-md-8"><p><i class="fa fa-ban" aria-hidden="true" style="color:red"></i> The room has no label, Home Rough Editor cannot provide you with information.</p></div>\n';
- } else {
- if (ROOM[k].name === "Salon") {
- for (let g in ROOM) {
- if (ROOM[g].name === "Salle à manger") {
- roomEnergy[k].light += roomEnergy[g].light;
- roomEnergy[k].plug += roomEnergy[g].plug;
- roomEnergy[k].switch += roomEnergy[g].switch;
- }
- }
- reportRoom += '<div class="col-md-8">';
- if (roomEnergy[k].light === 0) {
- reportRoom +=
- '<p><i class="fa fa-exclamation-triangle" style="color:orange" aria-hidden="true"></i> This room must have at least <b>1 controlled light point</b> <small>(actually ' +
- roomEnergy[k].light + ')</small>.</p>\n';
- nfc = false;
- }
- if (roomEnergy[k].plug < 5) {
- reportRoom +=
- '<p><i class="fa fa-exclamation-triangle" style="color:orange" aria-hidden="true"></i> This room must have at least <b>5 power outlets</b> <small>(actually ' +
- roomEnergy[k].plug + ')</small>.</p>\n';
- nfc = false;
- }
- if (nfc) reportRoom += '<i class="fa fa-check" aria-hidden="true" style="color:green"></i>';
- reportRoom += '</div>';
- }
- if (ROOM[k].name === "Salle à manger") {
- reportRoom +=
- '<div class="col-md-8"><p><i class="fa fa-info" aria-hidden="true" style="color:blue"></i> This room is linked to the <b>living room / living room</b> according to the standard.</p></div>\n';
- }
- if (ROOM[k].name.substr(0, 7) === "Chambre") {
- reportRoom += '<div class="col-md-8">';
- if (roomEnergy[k].light === 0) {
- reportRoom +=
- '<p><i class="fa fa-exclamation-triangle" style="color:orange" aria-hidden="true"></i> This room must have at least <b>1 controlled light point</b> <small>(actually ' +
- roomEnergy[k].light + ')</small>.</p>\n';
- nfc = false;
- }
- if (roomEnergy[k].plug < 3) {
- reportRoom +=
- '<p><i class="fa fa-exclamation-triangle" style="color:orange" aria-hidden="true"></i> This room must have at least <b>3 power outlets</b> <small>(actually ' +
- roomEnergy[k].plug + ')</small>.</p>\n';
- nfc = false;
- }
- if (nfc) reportRoom += '<i class="fa fa-check" aria-hidden="true" style="color:green"></i>';
- reportRoom += '</div>';
- }
- if (ROOM[k].name === "SdB") {
- reportRoom += '<div class="col-md-8">';
- if (roomEnergy[k].light === 0) {
- reportRoom +=
- '<p><i class="fa fa-exclamation-triangle" style="color:orange" aria-hidden="true"></i> This room must have at least <b>1 light point</b> <small>(actually ' +
- roomEnergy[k].light + ')</small>.</p>\n';
- nfc = false;
- }
- if (roomEnergy[k].plug < 2) {
- reportRoom +=
- '<p><i class="fa fa-exclamation-triangle" style="color:orange" aria-hidden="true"></i> This room must have at least <b>2 power outlets</b> <small>(actually ' +
- roomEnergy[k].plug + ')</small>.</p>\n';
- nfc = false;
- }
- if (roomEnergy[k].switch === 0) {
- reportRoom +=
- '<p><i class="fa fa-exclamation-triangle" style="color:orange" aria-hidden="true"></i> This room must have at least <b>1 switch</b> <small>(actually ' +
- roomEnergy[k].switch + ')</small>.</p>\n';
- nfc = false;
- }
- if (nfc) reportRoom += '<i class="fa fa-check" aria-hidden="true" style="color:green"></i>';
- reportRoom += '</div>';
- }
- if (ROOM[k].name === "Couloir") {
- reportRoom += '<div class="col-md-8">';
- if (roomEnergy[k].light === 0) {
- reportRoom +=
- '<p><i class="fa fa-exclamation-triangle" style="color:orange" aria-hidden="true"></i> This room must have at least <b>1 controlled light point</b> <small>(actually ' +
- roomEnergy[k].light + ')</small>.</p>\n';
- nfc = false;
- }
- if (roomEnergy[k].plug < 1) {
- reportRoom +=
- '<p><i class="fa fa-exclamation-triangle" style="color:orange" aria-hidden="true"></i> This room must have at least <b>1 power outlet</b> <small>(actually ' +
- roomEnergy[k].plug + ')</small>.</p>\n';
- nfc = false;
- }
- if (nfc) reportRoom += '<i class="fa fa-check" aria-hidden="true" style="color:green"></i>';
- reportRoom += '</div>';
- }
- if (ROOM[k].name === "Toilette") {
- reportRoom += '<div class="col-md-8">';
- if (roomEnergy[k].light === 0) {
- reportRoom +=
- '<p><i class="fa fa-exclamation-triangle" style="color:orange" aria-hidden="true"></i> This room must have at least <b>1 light point</b>. <small>(actually ' +
- roomEnergy[k].light + ')</small>.</p>\n';
- nfc = false;
- }
- if (nfc) reportRoom += '<i class="fa fa-check" aria-hidden="true" style="color:green"></i>';
- reportRoom += '</div>';
- }
- if (ROOM[k].name === "Cuisine") {
- reportRoom += '<div class="col-md-8">';
- if (roomEnergy[k].light === 0) {
- reportRoom +=
- '<p><i class="fa fa-exclamation-triangle" style="color:orange" aria-hidden="true"></i> This room must have at least <b>1 controlled light point</b> <small>(actually ' +
- roomEnergy[k].light + ')</small>.</p>\n';
- nfc = false;
- }
- if (roomEnergy[k].plug < 6) {
- reportRoom +=
- '<p><i class="fa fa-exclamation-triangle" style="color:orange" aria-hidden="true"></i> This room must have at least <b>6 power outlets</b> <small>(actually ' +
- roomEnergy[k].plug + ')</small>.</p>\n';
- nfc = false;
- }
- if (roomEnergy[k].plug32 === 0) {
- reportRoom +=
- '<p><i class="fa fa-exclamation-triangle" style="color:orange" aria-hidden="true"></i> This room must have at least <b>1 32A power outlet</b> <small>(actually ' +
- roomEnergy[k].plug32 + ')</small>.</p>\n';
- nfc = false;
- }
- if (roomEnergy[k].plug20 < 2) {
- reportRoom +=
- '<p><i class="fa fa-exclamation-triangle" style="color:orange" aria-hidden="true"></i> This room must have at least <b>2 20A power outlets</b> <small>(actually ' +
- roomEnergy[k].plug20 + ')</small>.</p>\n';
- nfc = false;
- }
- if (nfc) reportRoom += '<i class="fa fa-check" aria-hidden="true" style="color:green"></i>';
- reportRoom += '</div>';
- }
- }
- number++;
- reportRoom += '</div>';
- }
- document.getElementById('reportRooms').innerHTML = reportRoom;
- $('#reportRooms').show(1000);
- });
- document.getElementById('wallWidth').addEventListener("input", function () {
- let sliderValue = this.value;
- binder.wall.thick = sliderValue;
- binder.wall.type = "normal";
- editor.architect(WALLS);
- let objWall = editor.objFromWall(binder.wall); // LIST OBJ ON EDGE
- for (let w = 0; w < objWall.length; w++) {
- objWall[w].thick = sliderValue;
- objWall[w].update();
- }
- rib();
- document.getElementById("wallWidthVal").textContent = sliderValue;
- });
- document.getElementById("bboxTrash").addEventListener("click", function () {
- binder.obj.graph.remove();
- binder.graph.remove();
- OBJDATA.splice(OBJDATA.indexOf(binder.obj), 1);
- $('#objBoundingBox').hide(100);
- $('#panel').show(200);
- fonc_button('select_mode');
- $('#boxinfo').html('Deleted object');
- delete binder;
- rib();
- });
- document.getElementById("bboxStepsAdd").addEventListener("click", function () {
- let newValue = document.getElementById("bboxStepsVal").textContent;
- if (newValue < 15) {
- newValue++;
- binder.obj.value = newValue;
- binder.obj.update();
- document.getElementById("bboxStepsVal").textContent = newValue;
- }
- });
- document.getElementById("bboxStepsMinus").addEventListener("click", function () {
- let newValue = document.getElementById("bboxStepsVal").textContent;
- if (newValue > 2) {
- newValue--;
- binder.obj.value = newValue;
- binder.obj.update();
- document.getElementById("bboxStepsVal").textContent = newValue;
- }
- });
- document.getElementById('bboxWidth').addEventListener("input", function () {
- let sliderValue = this.value;
- let objTarget = binder.obj;
- objTarget.size = (sliderValue / 100) * meter;
- objTarget.update();
- binder.size = (sliderValue / 100) * meter;
- binder.update();
- document.getElementById("bboxWidthVal").textContent = sliderValue;
- });
- document.getElementById('bboxHeight').addEventListener("input", function () {
- let sliderValue = this.value;
- let objTarget = binder.obj;
- objTarget.thick = (sliderValue / 100) * meter;
- objTarget.update();
- binder.thick = (sliderValue / 100) * meter;
- binder.update();
- document.getElementById("bboxHeightVal").textContent = sliderValue;
- });
- document.getElementById('bboxRotation').addEventListener("input", function () {
- let sliderValue = this.value;
- let objTarget = binder.obj;
- objTarget.angle = sliderValue;
- objTarget.update();
- binder.angle = sliderValue;
- binder.update();
- document.getElementById("bboxRotationVal").textContent = sliderValue;
- });
- document.getElementById('doorWindowWidth').addEventListener("input", function () {
- let sliderValue = this.value;
- let objTarget = binder.obj;
- let wallBind = editor.rayCastingWalls(objTarget, WALLS);
- if (wallBind.length > 1) {
- wallBind = wallBind[wallBind.length - 1];
- }
- let limits = limitObj(wallBind.equations.base, sliderValue, objTarget);
- if (qSVG.btwn(limits[1].x, wallBind.start.x, wallBind.end.x) && qSVG.btwn(limits[1].y, wallBind.start.y, wallBind.end.y) &&
- qSVG.btwn(limits[0].x, wallBind.start.x, wallBind.end.x) && qSVG.btwn(limits[0].y, wallBind.start.y, wallBind.end.y)) {
- objTarget.size = sliderValue;
- objTarget.limit = limits;
- objTarget.update();
- binder.size = sliderValue;
- binder.limit = limits;
- binder.update();
- document.getElementById("doorWindowWidthVal").textContent = sliderValue;
- }
- inWallRib(wallBind);
- });
- document.getElementById("objToolsHinge").addEventListener("click", function () {
- let objTarget = binder.obj;
- let hingeStatus = objTarget.hinge; // normal - reverse
- if (hingeStatus === 'normal') {
- objTarget.hinge = 'reverse';
- } else objTarget.hinge = 'normal';
- objTarget.update();
- });
- window.addEventListener("load", function () {
- document.getElementById('panel').style.transform = "translateX(200px)";
- document.getElementById('panel').addEventListener("transitionend", function () {
- document.getElementById('moveBox').style.transform = "translateX(-165px)";
- document.getElementById('zoomBox').style.transform = "translateX(-165px)";
- });
- if (!localStorage.getItem('history')) {
- $('#recover').html("<p>Select a plan type.");
- }
- const myModal = new bootstrap.Modal($('#myModal'))
- myModal.show();
- });
- document.getElementById('sizePolice').addEventListener("input", function () {
- document.getElementById('labelBox').style.fontSize = this.value + 'px';
- });
- $('#textToLayer').on('hidden.bs.modal', function (e) {
- fonc_button('select_mode');
- action = 0;
- let textToMake = document.getElementById('labelBox').textContent;
- if (textToMake != "" && textToMake != "Your text") {
- binder = new editor.obj2D("free", "text", document.getElementById('labelBox').style.color, snap, 0, 0, 0, "normal", 0, {
- text: textToMake,
- size: document.getElementById('sizePolice').value
- });
- binder.update();
- OBJDATA.push(binder);
- binder.graph.remove();
- $('#boxText').append(OBJDATA[OBJDATA.length - 1].graph);
- OBJDATA[OBJDATA.length - 1].update();
- delete binder;
- $('#boxinfo').html('Added text');
- save();
- } else {
- $('#boxinfo').html('Selection mode');
- }
- document.getElementById('labelBox').textContent = "Your text";
- document.getElementById('labelBox').style.color = "#333333";
- document.getElementById('labelBox').style.fontSize = "15px";
- document.getElementById('sizePolice').value = 15;
- });
- if (!Array.prototype.includes) {
- Object.defineProperty(Array.prototype, 'includes', {
- value: function (searchElement, fromIndex) {
- if (this === null) {
- throw new TypeError('"this" is null or not defined');
- }
- let o = Object(this);
- let len = o.length >>> 0;
- if (len === 0) {
- return false;
- }
- let n = fromIndex | 0;
- let k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
- while (k < len) {
- if (o[k] === searchElement) {
- return true;
- }
- k++;
- }
- return false;
- }
- });
- }
- function isObjectsEquals(a, b, message = false) {
- if (message) console.log(message)
- let isOK = true;
- for (let prop in a) {
- if (a[prop] !== b[prop]) {
- isOK = false;
- break;
- }
- }
- return isOK;
- };
- function throttle(callback, delay) {
- let last;
- let timer;
- return function () {
- let context = this;
- let now = +new Date();
- let args = arguments;
- if (last && now < last + delay) {
- // le délai n'est pas écoulé on reset le timer
- clearTimeout(timer);
- timer = setTimeout(function () {
- last = now;
- callback.apply(context, args);
- }, delay);
- } else {
- last = now;
- callback.apply(context, args);
- }
- };
- }
- linElement.mousewheel(throttle(function (event) {
- event.preventDefault();
- if (event.deltaY > 0) {
- zoom_maker('zoomin', 200);
- } else {
- zoom_maker('zoomout', 200);
- }
- }, 100));
- document.getElementById("showRib").addEventListener("click", function () {
- if (document.getElementById("showRib").checked) {
- $('#boxScale').show(200);
- $('#boxRib').show(200);
- showRib = true;
- } else {
- $('#boxScale').hide(100);
- $('#boxRib').hide(100);
- showRib = false;
- }
- });
- document.getElementById("showArea").addEventListener("click", function () {
- if (document.getElementById("showArea").checked) {
- $('#boxArea').show(200);
- } else {
- $('#boxArea').hide(100);
- }
- });
- document.getElementById("showLayerRoom").addEventListener("click", function () {
- if (document.getElementById("showLayerRoom").checked) {
- $('#boxRoom').show(200);
- } else {
- $('#boxRoom').hide(100);
- }
- });
- document.getElementById("showLayerEnergy").addEventListener("click", function () {
- if (document.getElementById("showLayerEnergy").checked) {
- $('#boxEnergy').show(200);
- } else {
- $('#boxEnergy').hide(100);
- }
- });
- document.getElementById("showLayerBackground").addEventListener("click", function () {
- const backgroundImage = document.getElementById('backgroundImage');
- if (backgroundImage) {
- if (document.getElementById("showLayerBackground").checked) {
- backgroundImage.style.display = 'block';
- } else {
- backgroundImage.style.display = 'none';
- }
- }
- });
- // document.getElementById("showLayerFurniture").addEventListener("click", function () {
- // if (document.getElementById("showLayerFurniture").checked) {
- // $('#boxFurniture').show(200);
- // }
- // else {
- // $('#boxFurniture').hide(100);
- // }
- // });
- document.getElementById("applySurface").addEventListener("click", function () {
- $('#roomTools').hide(100);
- $('#panel').show(200);
- binder.remove();
- delete binder;
- let id = $('#roomIndex').val();
- //COLOR
- let data = $('#roomBackground').val();
- ROOM[id].color = data;
- //ROOM NAME
- let roomName = $('#roomName').val();
- if (roomName === 'None') {
- roomName = '';
- }
- ROOM[id].name = roomName;
- //ROOM SURFACE
- let area = $('#roomSurface').val();
- ROOM[id].surface = area;
- //SHOW SURFACE
- let show = document.querySelector("#seeArea").checked;
- ROOM[id].showSurface = show;
- //ACTION PARAM
- let action = document.querySelector('input[type=radio]:checked').value;
- ROOM[id].action = action;
- if (action === 'sub') {
- ROOM[id].color = 'hatch';
- }
- if (action != 'sub' && data === 'hatch') {
- ROOM[id].color = 'gradientNeutral';
- }
- $('#boxRoom').empty();
- $('#boxSurface').empty();
- editor.roomMaker(Rooms);
- $('#boxinfo').html('Updated room');
- fonc_button('select_mode');
- });
- document.getElementById("resetRoomTools").addEventListener("click", function () {
- $('#roomTools').hide(100);
- $('#panel').show(200);
- binder.remove();
- delete binder;
- $('#boxinfo').html('Updated room');
- fonc_button('select_mode');
- });
- document.getElementById("wallTrash").addEventListener("click", function () {
- let wall = binder.wall;
- for (let k in WALLS) {
- if (isObjectsEquals(WALLS[k].child, wall)) WALLS[k].child = null;
- if (isObjectsEquals(WALLS[k].parent, wall)) {
- WALLS[k].parent = null;
- }
- }
- WALLS.splice(WALLS.indexOf(wall), 1);
- $('#wallTools').hide(100);
- wall.graph.remove();
- binder.graph.remove();
- editor.architect(WALLS);
- rib();
- mode = "select_mode";
- $('#panel').show(200);
- });
- let textEditorColorBtn = document.querySelectorAll('.textEditorColor');
- for (let k = 0; k < textEditorColorBtn.length; k++) {
- textEditorColorBtn[k].addEventListener('click', function () {
- document.getElementById('labelBox').style.color = this.style.color;
- });
- }
- let zoomBtn = document.querySelectorAll('.zoom');
- for (let k = 0; k < zoomBtn.length; k++) {
- zoomBtn[k].addEventListener("click", function () {
- let lens = this.getAttribute('data-zoom');
- zoom_maker(lens, 200, 50);
- })
- }
- let roomColorBtn = document.querySelectorAll(".roomColor");
- for (let k = 0; k < roomColorBtn.length; k++) {
- roomColorBtn[k].addEventListener("click", function () {
- let data = this.getAttribute('data-type');
- $('#roomBackground').val(data);
- binder.attr({ 'fill': 'url(#' + data + ')' });
- });
- }
- let objTrashBtn = document.querySelectorAll(".objTrash");
- for (let k = 0; k < objTrashBtn.length; k++) {
- objTrashBtn[k].addEventListener("click", function () {
- $('#objTools').hide('100');
- let obj = binder.obj;
- obj.graph.remove();
- OBJDATA.splice(OBJDATA.indexOf(obj), 1);
- fonc_button('select_mode');
- $('#boxinfo').html('Selection mode');
- $('#panel').show('200');
- binder.graph.remove();
- delete binder;
- rib();
- $('#panel').show('300');
- });
- }
- let dropdownMenu = document.querySelectorAll(".dropdown-menu li a");
- for (let k = 0; k < dropdownMenu.length; k++) {
- dropdownMenu[k].addEventListener("click", function () {
- let selText = this.textContent;
- $(this).parents('.btn-group').find('.dropdown-toggle').html(selText + ' <span class="caret"></span>');
- if (selText != 'None') $('#roomName').val(selText);
- else $('#roomName').val('');
- });
- }
- // TRY MATRIX CALC FOR BBOX REAL COORDS WITH TRAS + ROT.
- function matrixCalc(el, message = false) {
- if (message) console.log("matrixCalc called by -> " + message);
- let m = el.getCTM();
- let bb = el.getBBox();
- let tpts = [
- matrixXY(m, bb.x, bb.y),
- matrixXY(m, bb.x + bb.width, bb.y),
- matrixXY(m, bb.x + bb.width, bb.y + bb.height),
- matrixXY(m, bb.x, bb.y + bb.height)];
- return tpts;
- }
- function matrixXY(m, x, y) {
- return { x: x * m.a + y * m.c + m.e, y: x * m.b + y * m.d + m.f };
- }
- function realBboxShow(coords) {
- for (let k in coords) {
- debugPoint(coords[k]);
- }
- }
- function limitObj(equation, size, coords, message = false) {
- if (message) {
- console.log(message);
- }
- let Px = coords.x;
- let Py = coords.y;
- let Aq = equation.A;
- let Bq = equation.B;
- let pos1, pos2;
- if (Aq === 'v') {
- pos1 = { x: Px, y: Py - size / 2 };
- pos2 = { x: Px, y: Py + size / 2 };
- } else if (Aq === 'h') {
- pos1 = { x: Px - size / 2, y: Py };
- pos2 = { x: Px + size / 2, y: Py };
- } else {
- let A = 1 + Aq * Aq;
- let B = (-2 * Px) + (2 * Aq * Bq) + (-2 * Py * Aq);
- let C = (Px * Px) + (Bq * Bq) - (2 * Py * Bq) + (Py * Py) - (size * size) / 4; // -N
- let Delta = (B * B) - (4 * A * C);
- let posX1 = (-B - (Math.sqrt(Delta))) / (2 * A);
- let posX2 = (-B + (Math.sqrt(Delta))) / (2 * A);
- pos1 = { x: posX1, y: (Aq * posX1) + Bq };
- pos2 = { x: posX2, y: (Aq * posX2) + Bq };
- }
- return [pos1, pos2];
- }
- function zoom_maker(lens, xmove, xview) {
- if (lens === 'zoomout' && zoom > 1 && zoom < 17) {
- zoom--;
- width_viewbox += xmove;
- let ratioWidthZoom = taille_w / width_viewbox;
- height_viewbox = width_viewbox * ratio_viewbox;
- myDiv = document.getElementById("scaleVal");
- myDiv.style.width = 60 * ratioWidthZoom + 'px';
- originX_viewbox = originX_viewbox - (xmove / 2);
- originY_viewbox = originY_viewbox - (xmove / 2 * ratio_viewbox);
- }
- if (lens === 'zoomin' && zoom < 14 && zoom > 0) {
- zoom++;
- let oldWidth = width_viewbox;
- let ratioWidthZoom = taille_w / width_viewbox;
- let newWidth = width_viewbox - xmove;
- if (newWidth < 100) newWidth = 100;
- width_viewbox = newWidth;
- height_viewbox = width_viewbox * ratio_viewbox;
- originX_viewbox = originX_viewbox + ((oldWidth - width_viewbox) / 2);
- originY_viewbox = originY_viewbox + (((oldWidth - width_viewbox) / 2) * ratio_viewbox);
- myDiv = document.getElementById("scaleVal");
- myDiv.style.width = 60 * ratioWidthZoom + 'px';
- }
- if (lens === 'zoominit') {
- width_viewbox = taille_w;
- height_viewbox = width_viewbox * ratio_viewbox;
- originX_viewbox = 0;
- originY_viewbox = 0;
- zoom = 9;
- factor = 1;
- }
- if (lens === 'zoomright') {
- originX_viewbox += xview;
- }
- if (lens === 'zoomleft') {
- originX_viewbox -= xview;
- }
- if (lens === 'zoomtop') {
- originY_viewbox -= xview;
- }
- if (lens === 'zoombottom') {
- originY_viewbox += xview;
- }
- if (lens === 'zoomdrag') {
- originX_viewbox -= xmove;
- originY_viewbox -= xview;
- }
- // Update pixel-to-SVG factor after any viewBox change
- factor = width_viewbox / taille_w;
- $('svg').each(function () {
- $(this)[0].setAttribute('viewBox', originX_viewbox + ' ' + originY_viewbox + ' ' + width_viewbox + ' ' + height_viewbox)
- });
- }
- // Center the current floorplan in view by fitting the WALLS bounding box to the viewport
- function centerFloorplanView(padding = 40) {
- try {
- if (!Array.isArray(WALLS) || WALLS.length === 0) return false;
- // Compute bounding box from wall endpoints
- let minX, minY, maxX, maxY;
- for (let i = 0; i < WALLS.length; i++) {
- const s = WALLS[i].start;
- const e = WALLS[i].end;
- if (!i) {
- minX = Math.min(s.x, e.x);
- minY = Math.min(s.y, e.y);
- maxX = Math.max(s.x, e.x);
- maxY = Math.max(s.y, e.y);
- } else {
- minX = Math.min(minX, s.x, e.x);
- minY = Math.min(minY, s.y, e.y);
- maxX = Math.max(maxX, s.x, e.x);
- maxY = Math.max(maxY, s.y, e.y);
- }
- }
- // Handle degenerate cases
- if (minX === undefined || minY === undefined || maxX === undefined || maxY === undefined) return false;
- const bboxW = Math.max(1, maxX - minX);
- const bboxH = Math.max(1, maxY - minY);
- // Target size keeping aspect ratio
- const viewAspect = ratio_viewbox; // height/width
- const targetWidth = bboxW + 2 * padding;
- const targetHeight = bboxH + 2 * padding;
- const widthFromHeight = targetHeight / viewAspect;
- const fitWidth = Math.max(targetWidth, widthFromHeight);
- const fitHeight = fitWidth * viewAspect;
- width_viewbox = fitWidth;
- height_viewbox = fitHeight;
- const cx = (minX + maxX) / 2;
- const cy = (minY + maxY) / 2;
- originX_viewbox = cx - (width_viewbox / 2);
- originY_viewbox = cy - (height_viewbox / 2);
- // Update pixel-to-SVG factor based on new viewBox size
- factor = width_viewbox / taille_w;
- // Update scale indicator if present
- const scaleEl = document.getElementById('scaleVal');
- if (scaleEl) {
- const ratioWidthZoom = taille_w / width_viewbox;
- scaleEl.style.width = (60 * ratioWidthZoom) + 'px';
- }
- // Apply viewBox to all SVGs
- $('svg').each(function () {
- $(this)[0].setAttribute('viewBox', originX_viewbox + ' ' + originY_viewbox + ' ' + width_viewbox + ' ' + height_viewbox);
- });
- return true;
- } catch (e) {
- console.error('Error centering view:', e);
- return false;
- }
- }
- tactile = false;
- function calcul_snap(event, state) {
- if (event.touches) {
- let touches = event.changedTouches;
- console.log("toto")
- eX = touches[0].pageX;
- eY = touches[0].pageY;
- tactile = true;
- } else {
- eX = event.pageX;
- eY = event.pageY;
- }
- x_mouse = (eX * factor) - (offset.left * factor) + originX_viewbox;
- y_mouse = (eY * factor) - (offset.top * factor) + originY_viewbox;
- if (state === 'on') {
- x_grid = Math.round(x_mouse / grid) * grid;
- y_grid = Math.round(y_mouse / grid) * grid;
- }
- if (state === 'off') {
- x_grid = x_mouse;
- y_grid = y_mouse;
- }
- return {
- x: x_grid,
- y: y_grid,
- xMouse: x_mouse,
- yMouse: y_mouse
- };
- }
- minMoveGrid = function (mouse) {
- return Math.abs(Math.abs(pox - mouse.x) + Math.abs(poy - mouse.y));
- }
- function intersectionOff() {
- if (typeof (lineIntersectionP) != 'undefined') {
- lineIntersectionP.remove();
- delete lineIntersectionP;
- }
- }
- function intersection(snap, range = Infinity, except = ['']) {
- // ORANGE LINES 90° NEAR SEGMENT
- let bestEqPoint = {};
- let equation = {};
- bestEqPoint.distance = range;
- if (typeof (lineIntersectionP) != 'undefined') {
- lineIntersectionP.remove();
- delete lineIntersectionP;
- }
- lineIntersectionP = qSVG.create("boxbind", "path", { // ORANGE TEMP LINE FOR ANGLE 0 90 45 -+
- d: "",
- "stroke": "transparent",
- "stroke-width": 0.5,
- "stroke-opacity": "1",
- fill: "none"
- });
- for (index = 0; index < WALLS.length; index++) {
- if (except.indexOf(WALLS[index]) === -1) {
- let x1 = WALLS[index].start.x;
- let y1 = WALLS[index].start.y;
- let x2 = WALLS[index].end.x;
- let y2 = WALLS[index].end.y;
- // EQUATION 90° of segment nf/nf-1 at X2/Y2 Point
- if (Math.abs(y2 - y1) === 0) {
- equation.C = 'v'; // C/D equation 90° Coef = -1/E
- equation.D = x1;
- equation.E = 'h'; // E/F equation Segment
- equation.F = y1;
- equation.G = 'v'; // G/H equation 90° Coef = -1/E
- equation.H = x2;
- equation.I = 'h'; // I/J equation Segment
- equation.J = y2;
- } else if (Math.abs(x2 - x1) === 0) {
- equation.C = 'h'; // C/D equation 90° Coef = -1/E
- equation.D = y1;
- equation.E = 'v'; // E/F equation Segment
- equation.F = x1;
- equation.G = 'h'; // G/H equation 90° Coef = -1/E
- equation.H = y2;
- equation.I = 'v'; // I/J equation Segment
- equation.J = x2;
- } else {
- equation.C = (x1 - x2) / (y2 - y1);
- equation.D = y1 - (x1 * equation.C);
- equation.E = (y2 - y1) / (x2 - x1);
- equation.F = y1 - (x1 * equation.E);
- equation.G = (x1 - x2) / (y2 - y1);
- equation.H = y2 - (x2 * equation.C);
- equation.I = (y2 - y1) / (x2 - x1);
- equation.J = y2 - (x2 * equation.E);
- }
- equation.A = equation.C;
- equation.B = equation.D;
- eq = qSVG.nearPointOnEquation(equation, snap);
- if (eq.distance < bestEqPoint.distance) {
- setBestEqPoint(bestEqPoint, eq.distance, index, eq.x, eq.y, x1, y1, x2, y2, 1);
- }
- equation.A = equation.E;
- equation.B = equation.F;
- eq = qSVG.nearPointOnEquation(equation, snap);
- if (eq.distance < bestEqPoint.distance) {
- setBestEqPoint(bestEqPoint, eq.distance, index, eq.x, eq.y, x1, y1, x2, y2, 1);
- }
- equation.A = equation.G;
- equation.B = equation.H;
- eq = qSVG.nearPointOnEquation(equation, snap);
- if (eq.distance < bestEqPoint.distance) {
- setBestEqPoint(bestEqPoint, eq.distance, index, eq.x, eq.y, x1, y1, x2, y2, 2);
- }
- equation.A = equation.I;
- equation.B = equation.J;
- eq = qSVG.nearPointOnEquation(equation, snap);
- if (eq.distance < bestEqPoint.distance) {
- setBestEqPoint(bestEqPoint, eq.distance, index, eq.x, eq.y, x1, y1, x2, y2, 2);
- }
- } // END INDEXOF EXCEPT TEST
- } // END LOOP FOR
- if (bestEqPoint.distance < range) {
- if (bestEqPoint.way === 2) {
- lineIntersectionP.attr({ // ORANGE TEMP LINE FOR ANGLE 0 90 45 -+
- d: "M" + bestEqPoint.x1 + "," + bestEqPoint.y1 + " L" + bestEqPoint.x2 + "," + bestEqPoint.y2 + " L" + bestEqPoint.x + "," +
- bestEqPoint.y,
- "stroke": "#d7ac57"
- });
- } else {
- lineIntersectionP.attr({ // ORANGE TEMP LINE FOR ANGLE 0 90 45 -+
- d: "M" + bestEqPoint.x2 + "," + bestEqPoint.y2 + " L" + bestEqPoint.x1 + "," + bestEqPoint.y1 + " L" + bestEqPoint.x + "," +
- bestEqPoint.y,
- "stroke": "#d7ac57"
- });
- }
- return ({
- x: bestEqPoint.x,
- y: bestEqPoint.y,
- wall: WALLS[bestEqPoint.node],
- distance: bestEqPoint.distance
- });
- } else {
- return false;
- }
- }
- function debugPoint(point, name, color = "#00ff00") {
- qSVG.create('boxDebug', 'circle', {
- cx: point.x,
- cy: point.y,
- r: 7,
- fill: color,
- id: name,
- class: "visu"
- });
- }
- function showVertex() {
- for (let i = 0; i < vertex.length; i++) {
- debugPoint(vertex[i], i);
- }
- }
- function showJunction() {
- for (let i = 0; i < junction.length; i++) {
- debugPoint({ x: junction[i].values[0], y: junction[i].values[1] }, i);
- }
- }
- $('.visu').mouseover(function () {
- console.log(this.id)
- });
- let sizeText = [];
- let showAllSizeStatus = 0;
- function hideAllSize() {
- $('#boxbind').empty();
- sizeText = [];
- showAllSizeStatus = 0;
- }
- function allRib() {
- $('#boxRib').empty();
- for (let i in WALLS) {
- inWallRib(WALLS[i], 'all');
- }
- }
- function inWallRib(wall, option = false) {
- if (!option) $('#boxRib').empty();
- ribMaster = [];
- ribMaster.push([]);
- ribMaster.push([]);
- let inter;
- let distance;
- let cross;
- let angleTextValue = wall.angle * (180 / Math.PI);
- let objWall = editor.objFromWall(wall); // LIST OBJ ON EDGE
- if (objWall.length == 0) return
- ribMaster[0].push({ wall: wall, crossObj: false, side: 'up', coords: wall.coords[0], distance: 0 });
- ribMaster[1].push({ wall: wall, crossObj: false, side: 'down', coords: wall.coords[1], distance: 0 });
- let objTarget = null
- for (let ob in objWall) {
- objTarget = objWall[ob];
- objTarget.up = [
- qSVG.nearPointOnEquation(wall.equations.up, objTarget.limit[0]),
- qSVG.nearPointOnEquation(wall.equations.up, objTarget.limit[1])
- ];
- objTarget.down = [
- qSVG.nearPointOnEquation(wall.equations.down, objTarget.limit[0]),
- qSVG.nearPointOnEquation(wall.equations.down, objTarget.limit[1])
- ];
- distance = qSVG.measure(wall.coords[0], objTarget.up[0]) / meter;
- ribMaster[0].push({
- wall: objTarget,
- crossObj: ob,
- side: 'up',
- coords: objTarget.up[0],
- distance: distance.toFixed(2)
- });
- distance = qSVG.measure(wall.coords[0], objTarget.up[1]) / meter;
- ribMaster[0].push({
- wall: objTarget,
- crossObj: ob,
- side: 'up',
- coords: objTarget.up[1],
- distance: distance.toFixed(2)
- });
- distance = qSVG.measure(wall.coords[1], objTarget.down[0]) / meter;
- ribMaster[1].push({
- wall: objTarget,
- crossObj: ob,
- side: 'down',
- coords: objTarget.down[0],
- distance: distance.toFixed(2)
- });
- distance = qSVG.measure(wall.coords[1], objTarget.down[1]) / meter;
- ribMaster[1].push({
- wall: objTarget,
- crossObj: ob,
- side: 'down',
- coords: objTarget.down[1],
- distance: distance.toFixed(2)
- });
- }
- distance = qSVG.measure(wall.coords[0], wall.coords[3]) / meter;
- ribMaster[0].push({ wall: objTarget, crossObj: false, side: 'up', coords: wall.coords[3], distance: distance });
- distance = qSVG.measure(wall.coords[1], wall.coords[2]) / meter;
- ribMaster[1].push({ wall: objTarget, crossObj: false, side: 'down', coords: wall.coords[2], distance: distance });
- ribMaster[0].sort(function (a, b) {
- return (a.distance - b.distance).toFixed(2);
- });
- ribMaster[1].sort(function (a, b) {
- return (a.distance - b.distance).toFixed(2);
- });
- for (let t in ribMaster) {
- for (let n = 1; n < ribMaster[t].length; n++) {
- let found = true;
- let shift = -5;
- let valueText = Math.abs(ribMaster[t][n - 1].distance - ribMaster[t][n].distance);
- let angleText = angleTextValue;
- if (found) {
- if (ribMaster[t][n - 1].side === 'down') {
- shift = -shift + 10;
- }
- if (angleText > 89 || angleText < -89) {
- angleText -= 180;
- if (ribMaster[t][n - 1].side === 'down') {
- shift = -5;
- } else shift = -shift + 10;
- }
- sizeText[n] = document.createElementNS('http://www.w3.org/2000/svg', 'text');
- let startText = qSVG.middle(ribMaster[t][n - 1].coords.x, ribMaster[t][n - 1].coords.y, ribMaster[t][n].coords.x,
- ribMaster[t][n].coords.y);
-
- // Check for valid coordinates before setting attributes
- if (startText && !isNaN(startText.x) && !isNaN(startText.y)) {
- sizeText[n].setAttributeNS(null, 'x', startText.x);
- sizeText[n].setAttributeNS(null, 'y', (startText.y) + shift);
- sizeText[n].setAttributeNS(null, 'text-anchor', 'middle');
- sizeText[n].setAttributeNS(null, 'font-family', 'roboto');
- sizeText[n].setAttributeNS(null, 'stroke', '#ffffff');
- sizeText[n].textContent = valueText.toFixed(2);
- if (sizeText[n].textContent < 1) {
- sizeText[n].setAttributeNS(null, 'font-size', '0.8em');
- sizeText[n].textContent = sizeText[n].textContent.substring(1, sizeText[n].textContent.length);
- } else sizeText[n].setAttributeNS(null, 'font-size', '1em');
- sizeText[n].setAttributeNS(null, 'stroke-width', '0.27px');
- sizeText[n].setAttributeNS(null, 'fill', '#666666');
- sizeText[n].setAttribute("transform", "rotate(" + angleText + " " + startText.x + "," + (startText.y) + ")");
- } else {
- // Skip creating text element if coordinates are invalid
- console.warn('Invalid coordinates for size text element:', startText);
- }
- $('#boxRib').append(sizeText[n]);
- }
- }
- }
- }
- function rib(shift = 5) {
- // return false;
- let ribMaster = [];
- ribMaster.push([]);
- ribMaster.push([]);
- let inter;
- let distance;
- let cross;
- for (let i in WALLS) {
- if (WALLS[i].equations.base) {
- ribMaster[0].push([]);
- pushToRibMaster(ribMaster, 0, i, i, i, 'up', WALLS[i].coords[0], 0);
- ribMaster[1].push([]);
- pushToRibMaster(ribMaster, 1, i, i, i, 'down', WALLS[i].coords[1], 0);
- for (let p in WALLS) {
- if (i != p && WALLS[p].equations.base) {
- cross = qSVG.intersectionOfEquations(WALLS[i].equations.base, WALLS[p].equations.base, "object");
- if (qSVG.btwn(cross.x, WALLS[i].start.x, WALLS[i].end.x, 'round') &&
- qSVG.btwn(cross.y, WALLS[i].start.y, WALLS[i].end.y, 'round')) {
- inter = qSVG.intersectionOfEquations(WALLS[i].equations.up, WALLS[p].equations.up, "object");
- if (qSVG.btwn(inter.x, WALLS[i].coords[0].x, WALLS[i].coords[3].x, 'round') &&
- qSVG.btwn(inter.y, WALLS[i].coords[0].y, WALLS[i].coords[3].y, 'round') &&
- qSVG.btwn(inter.x, WALLS[p].coords[0].x, WALLS[p].coords[3].x, 'round') &&
- qSVG.btwn(inter.y, WALLS[p].coords[0].y, WALLS[p].coords[3].y, 'round')) {
- distance = qSVG.measure(WALLS[i].coords[0], inter) / meter;
- pushToRibMaster(ribMaster, 0, i, i, p, 'up', inter, distance.toFixed(2));
- }
- inter = qSVG.intersectionOfEquations(WALLS[i].equations.up, WALLS[p].equations.down, "object");
- if (qSVG.btwn(inter.x, WALLS[i].coords[0].x, WALLS[i].coords[3].x, 'round') &&
- qSVG.btwn(inter.y, WALLS[i].coords[0].y, WALLS[i].coords[3].y, 'round') &&
- qSVG.btwn(inter.x, WALLS[p].coords[1].x, WALLS[p].coords[2].x, 'round') &&
- qSVG.btwn(inter.y, WALLS[p].coords[1].y, WALLS[p].coords[2].y, 'round')) {
- distance = qSVG.measure(WALLS[i].coords[0], inter) / meter;
- pushToRibMaster(ribMaster, 0, i, i, p, 'up', inter, distance.toFixed(2));
- }
- inter = qSVG.intersectionOfEquations(WALLS[i].equations.down, WALLS[p].equations.up, "object");
- if (qSVG.btwn(inter.x, WALLS[i].coords[1].x, WALLS[i].coords[2].x, 'round') &&
- qSVG.btwn(inter.y, WALLS[i].coords[1].y, WALLS[i].coords[2].y, 'round') &&
- qSVG.btwn(inter.x, WALLS[p].coords[0].x, WALLS[p].coords[3].x, 'round') &&
- qSVG.btwn(inter.y, WALLS[p].coords[0].y, WALLS[p].coords[3].y, 'round')) {
- distance = qSVG.measure(WALLS[i].coords[1], inter) / meter;
- pushToRibMaster(ribMaster, 1, i, i, p, 'down', inter, distance.toFixed(2));
- }
- inter = qSVG.intersectionOfEquations(WALLS[i].equations.down, WALLS[p].equations.down, "object");
- if (qSVG.btwn(inter.x, WALLS[i].coords[1].x, WALLS[i].coords[2].x, 'round') &&
- qSVG.btwn(inter.y, WALLS[i].coords[1].y, WALLS[i].coords[2].y, 'round') &&
- qSVG.btwn(inter.x, WALLS[p].coords[1].x, WALLS[p].coords[2].x, 'round') &&
- qSVG.btwn(inter.y, WALLS[p].coords[1].y, WALLS[p].coords[2].y, 'round')) {
- distance = qSVG.measure(WALLS[i].coords[1], inter) / meter;
- pushToRibMaster(ribMaster, 1, i, i, p, 'down', inter, distance.toFixed(2));
- }
- }
- }
- }
- distance = qSVG.measure(WALLS[i].coords[0], WALLS[i].coords[3]) / meter;
- pushToRibMaster(ribMaster, 0, i, i, i, 'up', WALLS[i].coords[3], distance.toFixed(2));
- distance = qSVG.measure(WALLS[i].coords[1], WALLS[i].coords[2]) / meter;
- pushToRibMaster(ribMaster, 1, i, i, i, 'down', WALLS[i].coords[2], distance.toFixed(2));
- }
- }
- for (let a in ribMaster[0]) {
- ribMaster[0][a].sort(function (a, b) {
- return (a.distance - b.distance).toFixed(2);
- });
- }
- for (let a in ribMaster[1]) {
- ribMaster[1][a].sort(function (a, b) {
- return (a.distance - b.distance).toFixed(2);
- });
- }
- let sizeText = [];
- if (shift === 5) $('#boxRib').empty();
- for (let t in ribMaster) {
- for (let a in ribMaster[t]) {
- for (let n = 1; n < ribMaster[t][a].length; n++) {
- if (ribMaster[t][a][n - 1].wallIndex === ribMaster[t][a][n].wallIndex) {
- let edge = ribMaster[t][a][n].wallIndex;
- let found = true;
- let valueText = Math.abs(ribMaster[t][a][n - 1].distance - ribMaster[t][a][n].distance);
- // CLEAR TOO LITTLE VALUE
- if (valueText < 0.15) {
- found = false;
- }
- // CLEAR (thick) BETWEEN CROSS EDGE
- if (found && ribMaster[t][a][n - 1].crossEdge === ribMaster[t][a][n].crossEdge && ribMaster[t][a][n].crossEdge !=
- ribMaster[t][a][n].wallIndex) {
- found = false;
- }
- // CLEAR START INTO EDGE
- if (found && ribMaster[t][a].length > 2 && n === 1) {
- let polygon = [];
- for (let pp = 0; pp < 4; pp++) {
- polygon.push({
- x: WALLS[ribMaster[t][a][n].crossEdge].coords[pp].x,
- y: WALLS[ribMaster[t][a][n].crossEdge].coords[pp].y
- }); // FOR Z
- }
- if (qSVG.rayCasting(ribMaster[t][a][0].coords, polygon)) {
- found = false;
- }
- }
- // CLEAR END INTO EDGE
- if (found && ribMaster[t][a].length > 2 && n === ribMaster[t][a].length - 1) {
- let polygon = [];
- for (let pp = 0; pp < 4; pp++) {
- polygon.push({
- x: WALLS[ribMaster[t][a][n - 1].crossEdge].coords[pp].x,
- y: WALLS[ribMaster[t][a][n - 1].crossEdge].coords[pp].y
- }); // FOR Z
- }
- if (qSVG.rayCasting(ribMaster[t][a][ribMaster[t][a].length - 1].coords, polygon)) {
- found = false;
- }
- }
- if (found) {
- let angleText = WALLS[ribMaster[t][a][n].wallIndex].angle * (180 / Math.PI);
- let shiftValue = -shift;
- if (ribMaster[t][a][n - 1].side === 'down') {
- shiftValue = -shiftValue + 10;
- }
- if (angleText > 90 || angleText < -89) {
- angleText -= 180;
- if (ribMaster[t][a][n - 1].side === 'down') {
- shiftValue = -shift;
- } else shiftValue = -shiftValue + 10;
- }
- sizeText[n] = document.createElementNS('http://www.w3.org/2000/svg', 'text');
- let startText = qSVG.middle(ribMaster[t][a][n - 1].coords.x, ribMaster[t][a][n - 1].coords.y, ribMaster[t][a][n].coords.x,
- ribMaster[t][a][n].coords.y);
-
- // Check for valid coordinates before setting attributes
- if (startText && !isNaN(startText.x) && !isNaN(startText.y)) {
- sizeText[n].setAttributeNS(null, 'x', startText.x);
- sizeText[n].setAttributeNS(null, 'y', (startText.y) + (shiftValue));
- sizeText[n].setAttributeNS(null, 'text-anchor', 'middle');
- sizeText[n].setAttributeNS(null, 'font-family', 'roboto');
- sizeText[n].setAttributeNS(null, 'stroke', '#ffffff');
- sizeText[n].textContent = valueText.toFixed(2);
- if (sizeText[n].textContent < 1) {
- sizeText[n].setAttributeNS(null, 'font-size', '0.73em');
- sizeText[n].textContent = sizeText[n].textContent.substring(1, sizeText[n].textContent.length);
- } else sizeText[n].setAttributeNS(null, 'font-size', '0.9em');
- sizeText[n].setAttributeNS(null, 'stroke-width', '0.2px');
- sizeText[n].setAttributeNS(null, 'fill', '#555555');
- sizeText[n].setAttribute("transform", "rotate(" + angleText + " " + startText.x + "," + (startText.y) + ")");
- } else {
- // Skip creating text element if coordinates are invalid
- console.warn('Invalid coordinates for size text element:', startText);
- }
- $('#boxRib').append(sizeText[n]);
- }
- }
- }
- }
- }
- }
- function cursor(tool) {
- if (tool === 'grab') tool =
- "url('https://wiki.openmrs.org/s/en_GB/7502/b9217199c27dd617c8d51f6186067d7767c5001b/_/images/icons/emoticons/add.png') 8 8, auto";
- if (tool === 'scissor') tool = "url('https://maxcdn.icons8.com/windows10/PNG/64/Hands/hand_scissors-64.png'), auto";
- if (tool === 'trash') tool = "url('https://cdn4.iconfinder.com/data/icons/common-toolbar/36/Cancel-32.png'), auto";
- if (tool === 'validation') tool = "url('https://images.fatguymedia.com/wp-content/uploads/2015/09/check.png'), auto";
- linElement.css('cursor', tool);
- }
- function fullscreen() {
- // go full-screen
- let i = document.body;
- if (i.requestFullscreen) {
- i.requestFullscreen();
- } else if (i.webkitRequestFullscreen) {
- i.webkitRequestFullscreen();
- } else if (i.mozRequestFullScreen) {
- i.mozRequestFullScreen();
- } else if (i.msRequestFullscreen) {
- i.msRequestFullscreen();
- }
- }
- function outFullscreen() {
- if (document.exitFullscreen) {
- document.exitFullscreen();
- } else if (document.mozCancelFullScreen) {
- document.mozCancelFullScreen();
- } else if (document.webkitExitFullscreen) {
- document.webkitExitFullscreen();
- }
- }
- document.addEventListener("fullscreenchange", function () {
- if (
- !document.fullscreenElement &&
- !document.webkitFullscreenElement &&
- !document.mozFullScreenElement &&
- !document.msFullscreenElement) {
- $('#nofull_mode').display = 'none';
- $('#full_mode').show();
- }
- });
- function raz_button() {
- $('#rect_mode').removeClass('btn-success');
- $('#rect_mode').addClass('btn-default');
- $('#select_mode').removeClass('btn-success');
- $('#select_mode').addClass('btn-default');
- $('#line_mode').removeClass('btn-success');
- $('#line_mode').addClass('btn-default');
- $('#partition_mode').removeClass('btn-success');
- $('#partition_mode').addClass('btn-default');
- $('#door_mode').removeClass('btn-success');
- $('#door_mode').addClass('btn-default');
- $('#node_mode').removeClass('btn-success');
- $('#node_mode').addClass('btn-default');
- $('#text_mode').removeClass('btn-success');
- $('#text_mode').addClass('btn-default');
- $('#room_mode').removeClass('btn-success');
- $('#room_mode').addClass('btn-default');
- $('#distance_mode').removeClass('btn-success');
- $('#distance_mode').addClass('btn-default');
- $('#object_mode').removeClass('btn-success');
- $('#object_mode').addClass('btn-default');
- $('#stair_mode').removeClass('btn-success');
- $('#stair_mode').addClass('btn-default');
- }
- function fonc_button(modesetting, option) {
- save();
- $('.sub').hide();
- raz_button();
- if (option != 'simpleStair') {
- $('#' + modesetting).removeClass('btn-default');
- $('#' + modesetting).addClass('btn-success');
- }
- mode = modesetting;
- modeOption = option;
- if (typeof (lineIntersectionP) != 'undefined') {
- lineIntersectionP.remove();
- delete lineIntersectionP;
- }
- }
- $('#distance_mode').click(function () {
- linElement.css('cursor', 'crosshair');
- $('#boxinfo').html('Add a measurement');
- fonc_button('distance_mode');
- });
- $('#room_mode').click(function () {
- linElement.css('cursor', 'pointer');
- $('#boxinfo').html('Config. of rooms');
- fonc_button('room_mode');
- });
- $('#select_mode').click(function () {
- $('#boxinfo').html('Mode "select"');
- if (typeof (binder) != 'undefined') {
- try { if (binder.graph) $(binder.graph).remove(); } catch (e) {}
- $('#boxbind').empty();
- binder = undefined;
- }
- fonc_button('select_mode');
- });
- $('#line_mode').click(function () {
- linElement.css('cursor', 'crosshair');
- $('#boxinfo').html('Creation of wall(s)');
- multi = 0;
- action = 0;
- // snap = calcul_snap(event, grid_snap);
- //
- // pox = snap.x;
- // poy = snap.y;
- fonc_button('line_mode');
- });
- $('#partition_mode').click(function () {
- linElement.css('cursor', 'crosshair');
- $('#boxinfo').html('Creation of thin wall(s)');
- multi = 0;
- fonc_button('partition_mode');
- });
- $('#rect_mode').click(function () {
- linElement.css('cursor', 'crosshair');
- $('#boxinfo').html('Room(s) creation');
- fonc_button('rect_mode');
- });
- $('.door').click(function () {
- linElement.css('cursor', 'crosshair');
- $('#boxinfo').html('Add a door');
- $('#door_list').hide(200);
- fonc_button('door_mode', this.id);
- });
- $('.window').click(function () {
- linElement.css('cursor', 'crosshair');
- $('#boxinfo').html('Add a window');
- $('#door_list').hide(200);
- $('#window_list').hide(200);
- fonc_button('door_mode', this.id);
- });
- $('.object').click(function () {
- cursor('move');
- $('#boxinfo').html('Add an object');
- fonc_button('object_mode', this.id);
- });
- $('#stair_mode').click(function () {
- cursor('move');
- $('#boxinfo').html('Add stair');
- fonc_button('object_mode', 'simpleStair');
- });
- $('#node_mode').click(function () {
- $('#boxinfo')
- .html('Cut a wall<br/><span style=\"font-size:0.7em\">Warning : Cutting the wall of a room can cancel its ' +
- 'configuration</span>');
- fonc_button('node_mode');
- });
- $('#text_mode').click(function () {
- $('#boxinfo').html('Add text<br/><span style=\"font-size:0.7em\">Place the cursor to the desired location, then ' +
- 'type your text.</span>');
- fonc_button('text_mode');
- });
- $('#grid_mode').click(function () {
- if (grid_snap === 'on') {
- grid_snap = 'off';
- $('#boxinfo').html('Help grid off');
- $('#grid_mode').removeClass('btn-success');
- $('#grid_mode').addClass('btn-warning');
- $('#grid_mode').html('GRID OFF');
- $('#boxgrid').css('opacity', '0.5');
- } else {
- grid_snap = 'on';
- $('#boxinfo').html('Help grid on');
- $('#grid_mode').removeClass('btn-warning');
- $('#grid_mode').addClass('btn-success');
- $('#grid_mode').html('GRID ON <i class="fa fa-th" aria-hidden="true"></i>');
- $('#boxgrid').css('opacity', '1');
- }
- });
- // RETURN PATH(s) ARRAY FOR OBJECT + PROPERTY params => bindBox (false = open sideTool), move, resize, rotate
- function carpentryCalc(classObj, typeObj, sizeObj, thickObj, dividerObj = 10) {
- // Validate input parameters to prevent NaN propagation
- if (isNaN(sizeObj) || sizeObj <= 0) sizeObj = 60;
- if (isNaN(thickObj) || thickObj <= 0) thickObj = 20;
- if (isNaN(dividerObj) || dividerObj <= 0) dividerObj = 10;
-
- let construc = [];
- construc.params = {};
- construc.params.bindBox = false;
- construc.params.move = false;
- construc.params.resize = false;
- construc.params.resizeLimit = {};
- construc.params.resizeLimit.width = { min: false, max: false };
- construc.params.resizeLimit.height = { min: false, max: false };
- construc.params.rotate = false;
- if (classObj === 'socle') {
- pushToConstruc(construc, "M " + (-sizeObj / 2) + "," + (-thickObj / 2) + " L " + (-sizeObj / 2) + "," +
- thickObj / 2 + " L " + sizeObj / 2 + "," + thickObj / 2 + " L " + sizeObj / 2 + "," + (-thickObj / 2) +
- " Z", "#5cba79", "#5cba79", '');
- }
- if (classObj === 'doorWindow') {
- if (typeObj === 'simple') {
- pushToConstruc(construc, "M " + (-sizeObj / 2) + "," + (-thickObj / 2) + " L " + (-sizeObj / 2) + "," + thickObj / 2 +
- " L " + sizeObj / 2 + "," + thickObj / 2 + " L " + sizeObj / 2 + "," + (-thickObj / 2) + " Z", "#ccc", "none",
- '');
- pushToConstruc(construc, "M " + (-sizeObj / 2) + "," + (-thickObj / 2) + " L " + (-sizeObj / 2) + "," +
- (-sizeObj - thickObj / 2) + " A" + sizeObj + "," + sizeObj + " 0 0,1 " + sizeObj / 2 + "," + (-thickObj / 2), "none", colorWall,
- '');
- construc.params.resize = true;
- construc.params.resizeLimit.width = { min: 40, max: 120 };
- }
- if (typeObj === 'double') {
- pushToConstruc(construc, "M " + (-sizeObj / 2) + "," + (-thickObj / 2) + " L " + (-sizeObj / 2) + "," + thickObj / 2 +
- " L " + sizeObj / 2 + "," + thickObj / 2 + " L " + sizeObj / 2 + "," + (-thickObj / 2) + " Z", "#ccc", "none",
- '');
- pushToConstruc(construc, "M " + (-sizeObj / 2) + "," + (-thickObj / 2) + " L " + (-sizeObj / 2) + "," +
- (-sizeObj / 2 - thickObj / 2) + " A" + sizeObj / 2 + "," + sizeObj / 2 + " 0 0,1 0," + (-thickObj / 2), "none", colorWall,
- '');
- pushToConstruc(construc, "M " + (sizeObj / 2) + "," + (-thickObj / 2) + " L " + (sizeObj / 2) + "," +
- (-sizeObj / 2 - thickObj / 2) + " A" + sizeObj / 2 + "," + sizeObj / 2 + " 0 0,0 0," + (-thickObj / 2), "none", colorWall,
- '');
- construc.params.resize = true;
- construc.params.resizeLimit.width = { min: 40, max: 160 };
- }
- if (typeObj === 'pocket') {
- pushToConstruc(construc, "M " + (-sizeObj / 2) + "," + (-(thickObj / 2) - 4) + " L " + (-sizeObj / 2) + "," +
- thickObj / 2 + " L " + sizeObj / 2 + "," + thickObj / 2 + " L " + sizeObj / 2 + "," + (-(thickObj / 2) - 4) + " Z", "#ccc",
- "none",
- 'none');
- pushToConstruc(construc, "M " + (-sizeObj / 2) + "," + (-thickObj / 2) + " L " + (-sizeObj / 2) + "," + thickObj / 2 +
- " M " + (sizeObj / 2) + "," + (thickObj / 2) + " L " + (sizeObj / 2) + "," + (-thickObj / 2), "none", "#494646",
- '5 5');
- pushToConstruc(construc, "M " + (-sizeObj / 2) + "," + (-thickObj / 2) + " L " + (-sizeObj / 2) + "," +
- (-thickObj / 2 - 5) + " L " + (+sizeObj / 2) + "," + (-thickObj / 2 - 5) + " L " + (+sizeObj / 2) +
- "," + (-thickObj / 2) + " Z", "url(#hatch)", "#494646", '');
- construc.params.resize = true;
- construc.params.resizeLimit.width = { min: 60, max: 200 };
- }
- if (typeObj === 'aperture') {
- pushToConstruc(construc, "M " + (-sizeObj / 2) + "," + (-thickObj / 2) + " L " + (-sizeObj / 2) + "," + thickObj / 2 +
- " L " + sizeObj / 2 + "," + thickObj / 2 + " L " + sizeObj / 2 + "," + (-thickObj / 2) + " Z", "#ccc", "#494646",
- '5,5');
- pushToConstruc(construc, "M " + (-sizeObj / 2) + "," + (-(thickObj / 2)) + " L " + (-sizeObj / 2) + "," + thickObj / 2 +
- " L " + ((-sizeObj / 2) + 5) + "," + thickObj / 2 + " L " + ((-sizeObj / 2) + 5) + "," + (-(thickObj / 2)) + " Z", "none",
- "#494646",
- 'none');
- pushToConstruc(construc, "M " + ((sizeObj / 2) - 5) + "," + (-(thickObj / 2)) + " L " + ((sizeObj / 2) - 5) + "," + thickObj / 2 +
- " L " + (sizeObj / 2) + "," + thickObj / 2 + " L " + (sizeObj / 2) + "," + (-(thickObj / 2)) + " Z", "none", "#494646",
- 'none');
- construc.params.resize = true;
- construc.params.resizeLimit.width = { min: 40, max: 500 };
- }
- if (typeObj === 'fix') {
- pushToConstruc(construc, "M " + (-sizeObj / 2) + ",-2 L " + (-sizeObj / 2) + ",2 L " +
- sizeObj / 2 + ",2 L " + sizeObj / 2 + ",-2 Z", "#ccc", "none", '');
- pushToConstruc(construc, "M " + (-sizeObj / 2) + "," + (-thickObj / 2) + " L " + (-sizeObj / 2) + "," + thickObj / 2 +
- " M " + sizeObj / 2 + "," + thickObj / 2 + " L " + sizeObj / 2 + "," + (-thickObj / 2), "none", "#ccc", '');
- construc.params.resize = true;
- construc.params.resizeLimit.width = { min: 30, max: 300 };
- }
- if (typeObj === 'flap') {
- pushToConstruc(construc, "M " + (-sizeObj / 2) + ",-2 L " + (-sizeObj / 2) + ",2 L " +
- sizeObj / 2 + ",2 L " + sizeObj / 2 + ",-2 Z", "#ccc", "none", '');
- pushToConstruc(construc, "M " + (-sizeObj / 2) + "," + (-thickObj / 2) + " L " + (-sizeObj / 2) + "," + thickObj / 2 +
- " M " + sizeObj / 2 + "," + thickObj / 2 + " L " + sizeObj / 2 + "," + (-thickObj / 2), "none", "#ccc", '');
- pushToConstruc(construc, "M " + (-sizeObj / 2) + "," + (-thickObj / 2) + " L " + ((-sizeObj / 2) +
- ((sizeObj) * 0.866)) + "," + ((-sizeObj / 2) - (thickObj / 2)) + " A" + sizeObj + "," +
- sizeObj + " 0 0,1 " + sizeObj / 2 + "," + (-thickObj / 2), "none", colorWall, '');
- construc.params.resize = true;
- construc.params.resizeLimit.width = { min: 20, max: 100 };
- }
- if (typeObj === 'twin') {
- pushToConstruc(construc, "M " + (-sizeObj / 2) + ",-2 L " + (-sizeObj / 2) + ",2 L " + sizeObj / 2 +
- ",2 L " + sizeObj / 2 + ",-2 Z", "#000", "none", '');
- pushToConstruc(construc, "M " + (-sizeObj / 2) + "," + (-thickObj / 2) + " L " + (-sizeObj / 2) + "," + thickObj / 2 +
- " L " + sizeObj / 2 + "," + thickObj / 2 + " L " + sizeObj / 2 + "," + (-thickObj / 2), "#fff", "#fff", '', 0.7);
- pushToConstruc(construc, "M " + (-sizeObj / 2) + "," + (-thickObj / 2) + " L " + (-sizeObj / 2) + "," + thickObj / 2 +
- " M " + sizeObj / 2 + "," + thickObj / 2 + " L " + sizeObj / 2 + "," + (-thickObj / 2), "none", "#000", '');
- pushToConstruc(construc, "M " + (-sizeObj / 2) + "," + (-thickObj / 2) + " L " + ((-sizeObj / 2) +
- ((sizeObj / 2) * 0.866)) + "," + (-sizeObj / 4 - thickObj / 2) + " A" +
- sizeObj / 2 + "," + sizeObj / 2 + " 0 0,1 0," + (-thickObj / 2), "none", colorWall, '');
- pushToConstruc(construc, "M " + (sizeObj / 2) + "," + (-thickObj / 2) + " L " + ((sizeObj / 2) +
- ((-sizeObj / 2) * 0.866)) + "," + (-sizeObj / 4 - thickObj / 2) + " A" +
- sizeObj / 2 + "," + sizeObj / 2 + " 0 0,0 0," + (-thickObj / 2), "none", colorWall, '');
- construc.params.resize = true;
- construc.params.resizeLimit.width = { min: 40, max: 200 };
- }
- if (typeObj === 'bay') {
- pushToConstruc(construc, "M " + (-sizeObj / 2) + "," + (-thickObj / 2) + " L " + (-sizeObj / 2) + "," + thickObj / 2 +
- " M " + sizeObj / 2 + "," + thickObj / 2 + " L " + sizeObj / 2 + "," + (-thickObj / 2), "none", "#ccc", '');
- pushToConstruc(construc, "M " + (-sizeObj / 2) + ",-2 L " + (-sizeObj / 2) + ",0 L 2,0 L 2,2 L 3,2 L 3,-2 Z", "#ccc", "none", '');
- pushToConstruc(construc, "M -2,1 L -2,3 L " + sizeObj / 2 + ",3 L " + sizeObj / 2 + ",1 L -1,1 L -1,-1 L -2,-1 Z", "#ccc", "none", '');
- construc.params.resize = true;
- construc.params.resizeLimit.width = { min: 60, max: 300 };
- }
- }
- if (classObj === 'measure') {
- construc.params.bindBox = true;
- pushToConstruc(construc, "M-" + (sizeObj / 2) + ",0 l10,-10 l0,8 l" + (sizeObj - 20) +
- ",0 l0,-8 l10,10 l-10,10 l0,-8 l-" + (sizeObj - 20) + ",0 l0,8 Z", "#729eeb", "none", '');
- }
- if (classObj === 'boundingBox') {
- pushToConstruc(construc,
- "M" + (-sizeObj / 2 - 10) + "," + (-thickObj / 2 - 10) + " L" + (sizeObj / 2 + 10) + "," + (-thickObj / 2 - 10) + " L" +
- (sizeObj / 2 + 10) + "," + (thickObj / 2 + 10) + " L" + (-sizeObj / 2 - 10) + "," + (thickObj / 2 + 10) + " Z", 'none',
- "#aaa", '');
- // construc.push({'path':"M"+dividerObj[0].x+","+dividerObj[0].y+" L"+dividerObj[1].x+","+dividerObj[1].y+" L"+dividerObj[2].x+",
- // "+dividerObj[2].y+" L"+dividerObj[3].x+","+dividerObj[3].y+" Z", 'fill':'none', 'stroke':"#000", 'strokeDashArray': ''});
- }
- //typeObj = color dividerObj = text
- if (classObj === 'text') {
- construc.params.bindBox = true;
- construc.params.move = true;
- construc.params.rotate = true;
- construc.push({
- 'text': dividerObj.text,
- 'x': '0',
- 'y': '0',
- 'fill': typeObj,
- 'stroke': typeObj,
- 'fontSize': dividerObj.size + 'px',
- "strokeWidth": "0px"
- });
- }
- if (classObj === 'stair') {
- construc.params.bindBox = true;
- construc.params.move = true;
- construc.params.resize = true;
- construc.params.rotate = true;
- construc.params.width = 60;
- construc.params.height = 180;
- if (typeObj === 'simpleStair') {
- pushToConstruc(construc,
- "M " + (-sizeObj / 2) + "," + (-thickObj / 2) + " L " + (-sizeObj / 2) + "," + thickObj / 2 + " L " + sizeObj / 2 + "," +
- thickObj / 2 + " L " + sizeObj / 2 + "," + (-thickObj / 2) + " Z", "#fff", "#000", '');
- let heightStep = thickObj / (dividerObj);
- for (let i = 1; i < dividerObj + 1; i++) {
- pushToConstruc(construc, "M " + (-sizeObj / 2) + "," + ((-thickObj / 2) + (i * heightStep)) + " L " + (sizeObj / 2) + "," +
- ((-thickObj / 2) + (i * heightStep)), "none", "#000", 'none');
- }
- construc.params.resizeLimit.width = { min: 40, max: 200 };
- construc.params.resizeLimit.height = { min: 40, max: 400 };
- }
- }
- if (classObj === 'energy') {
- construc.params.bindBox = true;
- construc.params.move = true;
- construc.params.resize = false;
- construc.params.rotate = false;
- if (typeObj === 'gtl') {
- pushToConstruc(construc, "m -20,-20 l 40,0 l0,40 l-40,0 Z", "#fff", "#333", '');
- construc.push({
- 'text': "GTL",
- 'x': '0',
- 'y': '5',
- 'fill': "#333333",
- 'stroke': "none",
- 'fontSize': '0.9em',
- "strokeWidth": "0.4px"
- });
- construc.params.width = 40;
- construc.params.height = 40;
- construc.family = 'stick';
- }
- if (typeObj === 'switch') {
- pushToConstruc(construc, qSVG.circlePath(0, 0, 16), "#fff", "#333", '');
- pushToConstruc(construc, qSVG.circlePath(-2, 4, 5), "none", "#333", '');
- pushToConstruc(construc, "m 0,0 5,-9", "none", "#333", '');
- construc.params.width = 36;
- construc.params.height = 36;
- construc.family = 'stick';
- }
- if (typeObj === 'doubleSwitch') {
- pushToConstruc(construc, qSVG.circlePath(0, 0, 16), "#fff", "#333", '');
- pushToConstruc(construc, qSVG.circlePath(0, 0, 4), "none", "#333", '');
- pushToConstruc(construc, "m 2,-3 5,-8 3,2", "none", "#333", '');
- pushToConstruc(construc, "m -2,3 -5,8 -3,-2", "none", "#333", '');
- construc.params.width = 36;
- construc.params.height = 36;
- construc.family = 'stick';
- }
- if (typeObj === 'dimmer') {
- pushToConstruc(construc, qSVG.circlePath(0, 0, 16), "#fff", "#333", '');
- pushToConstruc(construc, qSVG.circlePath(-2, 4, 5), "none", "#333", '');
- pushToConstruc(construc, "m 0,0 5,-9", "none", "#333", '');
- pushToConstruc(construc, "M -2,-6 L 10,-4 L-2,-2 Z", "none", "#333", '');
- construc.params.width = 36;
- construc.params.height = 36;
- construc.family = 'stick';
- }
- if (typeObj === 'plug') {
- pushToConstruc(construc, qSVG.circlePath(0, 0, 16), "#fff", "#000", '');
- pushToConstruc(construc, "M 10,-6 a 10,10 0 0 1 -5,8 10,10 0 0 1 -10,0 10,10 0 0 1 -5,-8", "none", "#333", '');
- pushToConstruc(construc, "m 0,3 v 7", "none", "#333", '');
- pushToConstruc(construc, "m -10,4 h 20", "none", "#333", '');
- construc.params.width = 36;
- construc.params.height = 36;
- construc.family = 'stick';
- }
- if (typeObj === 'plug20') {
- pushToConstruc(construc, qSVG.circlePath(0, 0, 16), "#fff", "#000", '');
- pushToConstruc(construc, "M 10,-6 a 10,10 0 0 1 -5,8 10,10 0 0 1 -10,0 10,10 0 0 1 -5,-8", "none", "#333", '');
- pushToConstruc(construc, "m 0,3 v 7", "none", "#333", '');
- pushToConstruc(construc, "m -10,4 h 20", "none", "#333", '');
- construc.push({
- 'text': "20A",
- 'x': '0',
- 'y': '-5',
- 'fill': "#333333",
- 'stroke': "none",
- 'fontSize': '0.65em',
- "strokeWidth": "0.4px"
- });
- construc.params.width = 36;
- construc.params.height = 36;
- construc.family = 'stick';
- }
- if (typeObj === 'plug32') {
- pushToConstruc(construc, qSVG.circlePath(0, 0, 16), "#fff", "#000", '');
- pushToConstruc(construc, "M 10,-6 a 10,10 0 0 1 -5,8 10,10 0 0 1 -10,0 10,10 0 0 1 -5,-8", "none", "#333", '');
- pushToConstruc(construc, "m 0,3 v 7", "none", "#333", '');
- pushToConstruc(construc, "m -10,4 h 20", "none", "#333", '');
- construc.push({
- 'text': "32A",
- 'x': '0',
- 'y': '-5',
- 'fill': "#333333",
- 'stroke': "none",
- 'fontSize': '0.65em',
- "strokeWidth": "0.4px"
- });
- construc.params.width = 36;
- construc.params.height = 36;
- construc.family = 'stick';
- }
- if (typeObj === 'roofLight') {
- pushToConstruc(construc, qSVG.circlePath(0, 0, 16), "#fff", "#000", '');
- pushToConstruc(construc, "M -8,-8 L 8,8 M -8,8 L 8,-8", "none", "#333", '');
- construc.params.width = 36;
- construc.params.height = 36;
- construc.family = 'free';
- }
- if (typeObj === 'wallLight') {
- pushToConstruc(construc, qSVG.circlePath(0, 0, 16), "#fff", "#000", '');
- pushToConstruc(construc, "M -8,-8 L 8,8 M -8,8 L 8,-8", "none", "#333", '');
- pushToConstruc(construc, "M -10,10 L 10,10", "none", "#333", '');
- construc.params.width = 36;
- construc.params.height = 36;
- construc.family = 'stick';
- }
- if (typeObj === 'www') {
- pushToConstruc(construc, "m -20,-20 l 40,0 l0,40 l-40,0 Z", "#fff", "#333", '');
- construc.push({
- 'text': "@",
- 'x': '0',
- 'y': '4',
- 'fill': "#333333",
- 'stroke': "none",
- 'fontSize': '1.2em',
- "strokeWidth": "0.4px"
- });
- construc.params.width = 40;
- construc.params.height = 40;
- construc.family = 'free';
- }
- if (typeObj === 'rj45') {
- pushToConstruc(construc, qSVG.circlePath(0, 0, 16), "#fff", "#000", '');
- pushToConstruc(construc, "m-10,5 l0,-10 m20,0 l0,10", "none", "#333", '');
- pushToConstruc(construc, "m 0,5 v 7", "none", "#333", '');
- pushToConstruc(construc, "m -10,5 h 20", "none", "#333", '');
- construc.push({
- 'text': "RJ45",
- 'x': '0',
- 'y': '-5',
- 'fill': "#333333",
- 'stroke': "none",
- 'fontSize': '0.5em',
- "strokeWidth": "0.4px"
- });
- construc.params.width = 36;
- construc.params.height = 36;
- construc.family = 'stick';
- }
- if (typeObj === 'tv') {
- pushToConstruc(construc, qSVG.circlePath(0, 0, 16), "#fff", "#000", '');
- pushToConstruc(construc, "m-10,5 l0-10 m20,0 l0,10", "none", "#333", '');
- pushToConstruc(construc, "m-7,-5 l0,7 l14,0 l0,-7", "none", "#333", '');
- pushToConstruc(construc, "m 0,5 v 7", "none", "#333", '');
- pushToConstruc(construc, "m -10,5 h 20", "none", "#333", '');
- construc.push({
- 'text': "TV",
- 'x': '0',
- 'y': '-5',
- 'fill': "#333333",
- 'stroke': "none",
- 'fontSize': '0.5em',
- "strokeWidth": "0.4px"
- });
- construc.params.width = 36;
- construc.params.height = 36;
- construc.family = 'stick';
- }
- if (typeObj === 'heater') {
- pushToConstruc(construc, qSVG.circlePath(0, 0, 16), "#fff", "#000", '');
- pushToConstruc(construc, "m-15,-4 l30,0", "none", "#333", '');
- pushToConstruc(construc, "m-14,-8 l28,0", "none", "#333", '');
- pushToConstruc(construc, "m-11,-12 l22,0", "none", "#333", '');
- pushToConstruc(construc, "m-16,0 l32,0", "none", "#333", '');
- pushToConstruc(construc, "m-15,4 l30,0", "none", "#333", '');
- pushToConstruc(construc, "m-14,8 l28,0", "none", "#333", '');
- pushToConstruc(construc, "m-11,12 l22,0", "none", "#333", '');
- construc.params.width = 36;
- construc.params.height = 36;
- construc.family = 'stick';
- }
- if (typeObj === 'radiator') {
- pushToConstruc(construc, "m -20,-10 l 40,0 l0,20 l-40,0 Z", "#fff", "#333", '');
- pushToConstruc(construc, "M -15,-10 L -15,10", "#fff", "#333", '');
- pushToConstruc(construc, "M -10,-10 L -10,10", "#fff", "#333", '');
- pushToConstruc(construc, "M -5,-10 L -5,10", "#fff", "#333", '');
- pushToConstruc(construc, "M -0,-10 L -0,10", "#fff", "#333", '');
- pushToConstruc(construc, "M 5,-10 L 5,10", "#fff", "#333", '');
- pushToConstruc(construc, "M 10,-10 L 10,10", "#fff", "#333", '');
- pushToConstruc(construc, "M 15,-10 L 15,10", "#fff", "#333", '');
- construc.params.width = 40;
- construc.params.height = 20;
- construc.family = 'stick';
- }
- }
- if (classObj === 'furniture') {
- construc.params.bindBox = true;
- construc.params.move = true;
- construc.params.resize = true;
- construc.params.rotate = true;
- }
- return construc;
- }
- function setBestEqPoint(bestEqPoint, distance, index, x, y, x1, y1, x2, y2, way) {
- bestEqPoint.distance = distance;
- bestEqPoint.node = index;
- bestEqPoint.x = x;
- bestEqPoint.y = y;
- bestEqPoint.x1 = x1;
- bestEqPoint.y1 = y1;
- bestEqPoint.x2 = x2;
- bestEqPoint.y2 = y2;
- bestEqPoint.way = way;
- }
- function pushToRibMaster(ribMaster, firstIndex, secondIndex, wallIndex, crossEdge, side, coords, distance) {
- ribMaster[firstIndex][secondIndex].push({
- wallIndex: wallIndex,
- crossEdge: crossEdge,
- side: side,
- coords: coords,
- distance: distance
- });
- }
- function pushToConstruc(construc, path, fill, stroke, strokeDashArray, opacity = 1) {
- construc.push({
- 'path': path,
- 'fill': fill,
- 'stroke': stroke,
- 'strokeDashArray': strokeDashArray,
- 'opacity': opacity
- });
- }
- // Export button event handler
- document.getElementById('export_mode').addEventListener('click', function() {
- // Generate filename with current date
- const now = new Date();
- const dateStr = now.getFullYear() + '-' +
- String(now.getMonth() + 1).padStart(2, '0') + '-' +
- String(now.getDate()).padStart(2, '0');
- const filename = 'floorplan_' + dateStr;
-
- // Call the export function
- if (exportFloorplanJSON(filename, true)) {
- $('#boxinfo').html('Floorplan exported successfully!');
- } else {
- $('#boxinfo').html('Export failed. Please try again.');
- }
- });
- // Blender export button event handler
- document.getElementById('export_blender_mode').addEventListener('click', function() {
- // Generate filename with current date
- const now = new Date();
- const dateStr = now.getFullYear() + '-' +
- String(now.getMonth() + 1).padStart(2, '0') + '-' +
- String(now.getDate()).padStart(2, '0');
- const filename = 'floorplan_blender_' + dateStr;
-
- // Call the Blender export function
- if (exportForBlender(filename, 2.8, 0.08)) {
- $('#boxinfo').html('Floorplan exported for Blender successfully!');
- } else {
- $('#boxinfo').html('Blender export failed. Please try again.');
- }
- });
- // Import button event handler
- document.getElementById('import_mode').addEventListener('click', function() {
- // Show confirmation dialog before importing (will clear current work)
- if (WALLS.length > 0 || OBJDATA.length > 0 || ROOM.length > 0) {
- if (!confirm('Importing will replace your current floorplan. Are you sure you want to continue?')) {
- $('#boxinfo').html('Import cancelled');
- return;
- }
- }
-
- // Trigger the file selection dialog
- triggerImportDialog();
- });
- // Import from AI button event handler
- document.getElementById('import_ai_mode').addEventListener('click', function () {
- // Show confirmation dialog before importing (will clear current work)
- if (typeof WALLS !== 'undefined' && (WALLS.length > 0 || (typeof OBJDATA !== 'undefined' && OBJDATA.length > 0) || (typeof ROOM !== 'undefined' && ROOM.length > 0))) {
- if (!confirm('Importing will replace your current floorplan. Are you sure you want to continue?')) {
- if (typeof $('#boxinfo') !== 'undefined') $('#boxinfo').html('Import cancelled');
- return;
- }
- }
- // Trigger the AI import dialog
- if (typeof triggerAIImportDialog === 'function') {
- triggerAIImportDialog();
- } else {
- console.error('triggerAIImportDialog is not available');
- if (typeof $('#boxinfo') !== 'undefined') $('#boxinfo').html('AI import is not available');
- }
- });
- // Import image button event handler
- document.getElementById('import_image_mode').addEventListener('click', function() {
- // Trigger the image import dialog
- triggerImageImportDialog();
- });
- // Background image opacity slider event handler (guard against missing element)
- (function(){
- const opacitySlider = document.getElementById('backgroundImageOpacitySlider');
- if (opacitySlider) {
- opacitySlider.addEventListener('input', function() {
- const opacityValue = this.value;
- if (typeof setBackgroundImageOpacity === 'function') setBackgroundImageOpacity(opacityValue);
- const label = document.getElementById('backgroundImageOpacityVal');
- if (label) label.textContent = opacityValue;
- });
- }
- })();
- // Background image remove button event handler (guard against missing element)
- (function(){
- const removeBtn = document.getElementById('backgroundImageRemove');
- if (removeBtn) {
- removeBtn.addEventListener('click', function() {
- if (confirm('Are you sure you want to remove the background image?')) {
- if (typeof removeBackgroundImage === 'function') removeBackgroundImage();
- if (typeof hideBackgroundImageTools === 'function') hideBackgroundImageTools();
- if (typeof $ !== 'undefined') $('#boxinfo').html('Background image removed');
- }
- });
- }
- })();
- // Combined Import (JSON + Image) modal handlers
- (function(){
- const jsonInput = document.getElementById('combined_json_input');
- const imageInput = document.getElementById('combined_image_input');
- const importBtn = document.getElementById('combined_import_btn');
- const jsonName = document.getElementById('combined_json_name');
- const imageName = document.getElementById('combined_image_name');
- const errMsg = document.getElementById('combined_error_msg');
- const okMsg = document.getElementById('combined_success_msg');
- if (!(jsonInput && imageInput && importBtn)) return; // Modal not present
- function resetMessages() {
- if (errMsg) errMsg.textContent = '';
- if (okMsg) okMsg.textContent = '';
- }
- function validateEnable() {
- const jf = jsonInput.files && jsonInput.files[0];
- const imf = imageInput.files && imageInput.files[0];
- let ok = true;
- resetMessages();
- if (jf) {
- const validJson = /\.json$/i.test(jf.name);
- if (!validJson) { ok = false; if (errMsg) errMsg.textContent = 'Selected JSON file is not a .json'; }
- } else { ok = false; }
- // Image is optional; if provided, validate type
- if (imf) {
- const validImg = /\.(png|jpe?g)$/i.test(imf.name);
- if (!validImg) { ok = false; if (errMsg) errMsg.textContent = 'Selected image must be PNG or JPG'; }
- }
- importBtn.disabled = !ok;
- }
- jsonInput.addEventListener('change', function(){
- if (jsonName) jsonName.textContent = this.files[0] ? this.files[0].name : '';
- validateEnable();
- });
- imageInput.addEventListener('change', function(){
- if (imageName) imageName.textContent = this.files[0] ? this.files[0].name : '';
- validateEnable();
- });
- importBtn.addEventListener('click', async function(){
- resetMessages();
- // Confirm replacing current work if any
- try {
- if ((typeof WALLS !== 'undefined' && WALLS.length) || (typeof OBJDATA !== 'undefined' && OBJDATA.length) || (typeof ROOM !== 'undefined' && ROOM.length)) {
- if (!confirm('Importing will replace your current floorplan. Continue?')) {
- if (typeof $ !== 'undefined') $('#boxinfo').html('Import cancelled');
- return;
- }
- }
- } catch(e) { /* ignore */ }
- const jf = jsonInput.files[0];
- const imf = imageInput.files[0];
- importBtn.disabled = true;
- importBtn.textContent = 'Importing...';
- try {
- // Use AI importer exclusively per request
- const jsonOk = await (typeof importAIFloorplanJSON === 'function' ? importAIFloorplanJSON(jf) : Promise.resolve(false));
- if (!jsonOk) {
- if (errMsg) errMsg.textContent = 'Failed to import floorplan JSON using AI format.';
- importBtn.textContent = 'Import';
- validateEnable();
- return;
- }
- // Image is optional: only try importing if provided
- let imgOk = true;
- if (imf) {
- imgOk = await (typeof importBackgroundImage === 'function' ? importBackgroundImage(imf) : Promise.resolve(false));
- if (!imgOk) {
- if (errMsg) errMsg.textContent = 'Floorplan JSON loaded, but background image import failed.';
- importBtn.textContent = 'Import';
- validateEnable();
- return;
- }
- }
- if (okMsg) okMsg.textContent = imf ? 'Imported successfully!' : 'Floorplan JSON imported successfully.';
- if (typeof $ !== 'undefined') $('#boxinfo').html(imf ? 'Floorplan and image imported successfully' : 'Floorplan JSON imported successfully');
- // Close modal after short delay and clear inputs
- setTimeout(function(){
- const modalEl = document.getElementById('combinedImportModal');
- if (modalEl && typeof bootstrap !== 'undefined' && bootstrap.Modal) {
- const instance = bootstrap.Modal.getInstance(modalEl) || new bootstrap.Modal(modalEl);
- instance.hide();
- }
- jsonInput.value = '';
- imageInput.value = '';
- if (jsonName) jsonName.textContent = '';
- if (imageName) imageName.textContent = '';
- importBtn.textContent = 'Import';
- validateEnable();
- }, 400);
- } catch (e) {
- console.error('Combined import error:', e);
- if (errMsg) errMsg.textContent = 'Unexpected error during import.';
- if (typeof $ !== 'undefined') $('#boxinfo').html('Import failed');
- importBtn.textContent = 'Import';
- validateEnable();
- }
- });
- })();
|