From cd79fe46a2acf55bc51d776439e8001615d73c52 Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Sun, 16 Jun 2024 16:40:23 -0400 Subject: [PATCH 1/6] move intersection component code to a separate file --- src/components/intersection.js | 353 ++++++++++++++++++++++++++++++++ src/index.js | 354 +-------------------------------- 2 files changed, 354 insertions(+), 353 deletions(-) create mode 100644 src/components/intersection.js diff --git a/src/components/intersection.js b/src/components/intersection.js new file mode 100644 index 000000000..93cf057fe --- /dev/null +++ b/src/components/intersection.js @@ -0,0 +1,353 @@ +/* global AFRAME */ +AFRAME.registerComponent('intersection', { + schema: { + dimensions: { type: 'string', default: '20 20' }, + sidewalk: { type: 'string', default: '0 0 0 0' }, + northeastcurb: { type: 'string', default: '0 0' }, + southwestcurb: { type: 'string', default: '0 0' }, + southeastcurb: { type: 'string', default: '0 0' }, + northwestcurb: { type: 'string', default: '0 0' }, + stopsign: { type: 'string', default: '0 0 0 0' }, + trafficsignal: { type: 'string', default: '0 0 0 0' }, + crosswalk: { type: 'string', default: '0 0 0 0' } + }, + init: function () { + var data = this.data; + var el = this.el; + + // remove all child nodes if exists + while (el.firstChild) { + el.removeChild(el.lastChild); + } + const dimensionsArray = data.dimensions.split(' ').map((i) => Number(i)); + const positionArray = [ + this.el.getAttribute('position').x, + this.el.getAttribute('position').y, + this.el.getAttribute('position').z + ]; + const sidewalkArray = data.sidewalk.split(' ').map((i) => Number(i)); + const northeastcurbArray = data.northeastcurb + .split(' ') + .map((i) => Number(i)); + const southwestcurbArray = data.southwestcurb + .split(' ') + .map((i) => Number(i)); + const southeastcurbArray = data.southeastcurb + .split(' ') + .map((i) => Number(i)); + const northwestcurbArray = data.northwestcurb + .split(' ') + .map((i) => Number(i)); + const stopsignArray = data.stopsign.split(' ').map((i) => Number(i)); + const trafficsignalArray = data.trafficsignal + .split(' ') + .map((i) => Number(i)); + const crosswalklArray = data.crosswalk.split(' ').map((i) => Number(i)); + + const intersectWidth = dimensionsArray[0]; + const intersectDepth = dimensionsArray[1]; + + this.el.setAttribute( + 'geometry', + `primitive:box; width: ${intersectWidth}; height: ${intersectDepth}; depth:0.2` + ); + this.el.setAttribute('position', { + x: positionArray[0], + y: -0.1, + z: positionArray[2] + }); + this.el.setAttribute('rotation', '-90 0 0'); + this.el.setAttribute( + 'material', + 'src: #asphalt-texture; repeat:5 5; roughness:1' + ); + + function createSidewalkElem({ + length, + width, + positionVec, + scaleVec = { x: 1, y: 1, z: 1 }, + rotationVec + }) { + const sd = document.createElement('a-entity'); + const repeatCountInter = []; + repeatCountInter[0] = width / 2; + // every 2 meters repeat sidewalk texture + repeatCountInter[1] = parseInt(length / 2); + + sd.setAttribute('geometry', 'primitive', 'box'); + sd.setAttribute('geometry', 'height: 0.4'); + sd.setAttribute('position', positionVec); + sd.setAttribute('scale', scaleVec); + sd.setAttribute('geometry', 'depth', length); + sd.setAttribute('geometry', 'width', width); + sd.setAttribute('rotation', rotationVec); + sd.setAttribute('mixin', 'sidewalk'); + sd.setAttribute( + 'material', + `repeat: ${repeatCountInter[0]} ${repeatCountInter[1]}` + ); + el.appendChild(sd); + } + + // describe sidewalk parameters + const sidewalkParams = { + west: { + positionVec: { x: intersectWidth / 2 - sidewalkArray[0] / 2, z: 0.1 }, + rotationVec: { x: 90, y: 0, z: 0 }, + length: intersectDepth, + width: sidewalkArray[0] + }, + east: { + positionVec: { x: -intersectWidth / 2 + sidewalkArray[1] / 2, z: 0.1 }, + rotationVec: { x: 90, y: 0, z: 0 }, + length: intersectDepth, + width: sidewalkArray[1] + }, + north: { + positionVec: { + y: -intersectDepth / 2 + sidewalkArray[2] / 2, + // add x offset to avoid sidewalk's element overlap + x: sidewalkArray[1] / 2 - sidewalkArray[0] / 2, + z: 0.1 + }, + rotationVec: { x: 0, y: 90, z: -90 }, + // minus the width of the crossing sidewalk + length: intersectWidth - sidewalkArray[1] - sidewalkArray[0], + width: sidewalkArray[2] + }, + south: { + positionVec: { + y: intersectDepth / 2 - sidewalkArray[3] / 2, + // add x offset to avoid sidewalk's element overlap + x: sidewalkArray[1] / 2 - sidewalkArray[0] / 2, + z: 0.1 + }, + rotationVec: { x: 0, y: 90, z: -90 }, + // minus the width of the crossing sidewalk + length: intersectWidth - sidewalkArray[1] - sidewalkArray[0], + width: sidewalkArray[3] + } + }; + + // create sidewalks if they are given in sidewalkArray + const selectedSidewalks = Object.keys(sidewalkParams).filter( + (el, ind) => sidewalkArray[ind] + ); + + selectedSidewalks.forEach((sidewalkName, ind) => { + const params = sidewalkParams[sidewalkName]; + createSidewalkElem(params); + }); + + // describe curb parameters + const curbParams = { + northeast: { + positionVec: { + x: intersectWidth / 2 - northeastcurbArray[0] / 2, + y: intersectDepth / 2 - northeastcurbArray[1] / 2, + z: 0.1 + }, + rotationVec: { x: 0, y: 90, z: -90 }, + length: northeastcurbArray[0], + width: northeastcurbArray[1] + }, + southwest: { + positionVec: { + x: -intersectWidth / 2 + southwestcurbArray[0] / 2, + y: -intersectDepth / 2 + southwestcurbArray[1] / 2, + z: 0.1 + }, + rotationVec: { x: 0, y: 90, z: -90 }, + length: southwestcurbArray[0], + width: southwestcurbArray[1] + }, + southeast: { + positionVec: { + x: intersectWidth / 2 - southeastcurbArray[0] / 2, + y: -intersectDepth / 2 + southeastcurbArray[1] / 2, + z: 0.1 + }, + rotationVec: { x: 0, y: 90, z: -90 }, + length: southeastcurbArray[0], + width: southeastcurbArray[1] + }, + northwest: { + positionVec: { + x: -intersectWidth / 2 + northwestcurbArray[0] / 2, + y: intersectDepth / 2 - northwestcurbArray[1] / 2, + z: 0.1 + }, + rotationVec: { x: 0, y: 90, z: -90 }, + length: northwestcurbArray[0], + width: northwestcurbArray[1] + } + }; + + // create curbs if they are given + for (const [curbName, params] of Object.entries(curbParams)) { + if (data[`${curbName}curb`] !== '0 0') { + createSidewalkElem(params); + } + } + + if (stopsignArray[0]) { + const ss1 = document.createElement('a-entity'); + ss1.setAttribute('position', { + x: intersectWidth / 2, + y: intersectDepth / 3, + z: 0.1 + }); + ss1.setAttribute('rotation', { x: 0, y: 90, z: 90 }); + ss1.setAttribute('mixin', 'stop_sign'); + el.appendChild(ss1); + } + if (stopsignArray[1]) { + const ss2 = document.createElement('a-entity'); + ss2.setAttribute('position', { + x: -intersectWidth / 2, + y: -intersectDepth / 3, + z: 0.1 + }); + ss2.setAttribute('rotation', { x: 0, y: -90, z: -90 }); + ss2.setAttribute('mixin', 'stop_sign'); + el.appendChild(ss2); + } + if (stopsignArray[2]) { + const ss3 = document.createElement('a-entity'); + ss3.setAttribute('position', { + x: -intersectWidth / 3, + y: intersectDepth / 2, + z: 0.1 + }); + ss3.setAttribute('rotation', { x: -90, y: 90, z: 90 }); + ss3.setAttribute('mixin', 'stop_sign'); + el.appendChild(ss3); + } + if (stopsignArray[3]) { + const ss4 = document.createElement('a-entity'); + ss4.setAttribute('position', { + x: intersectWidth / 3, + y: -intersectDepth / 2, + z: 0.1 + }); + ss4.setAttribute('rotation', { x: 90, y: -90, z: -90 }); + ss4.setAttribute('mixin', 'stop_sign'); + el.appendChild(ss4); + } + + if (trafficsignalArray[0]) { + const ts1 = document.createElement('a-entity'); + ts1.setAttribute('position', { + x: intersectWidth / 2, + y: intersectDepth / 3, + z: 0.3 + }); + ts1.setAttribute('rotation', { x: 210, y: 90, z: 90 }); + ts1.setAttribute('mixin', 'signal_left'); + el.appendChild(ts1); + const ts2 = document.createElement('a-entity'); + ts2.setAttribute('position', { + x: intersectWidth / 2, + y: -intersectDepth / 3, + z: 0.3 + }); + ts2.setAttribute('rotation', { x: 180, y: 90, z: 90 }); + ts2.setAttribute('mixin', 'signal_right'); + el.appendChild(ts2); + } + if (trafficsignalArray[1]) { + const ts3 = document.createElement('a-entity'); + ts3.setAttribute('position', { + x: -intersectWidth / 2, + y: -intersectDepth / 3, + z: 0.3 + }); + ts3.setAttribute('rotation', { x: 30, y: 90, z: 90 }); + ts3.setAttribute('mixin', 'signal_left'); + el.appendChild(ts3); + const ts4 = document.createElement('a-entity'); + ts4.setAttribute('position', { + x: -intersectWidth / 2, + y: intersectDepth / 3, + z: 0.3 + }); + ts4.setAttribute('rotation', { x: 0, y: 90, z: 90 }); + ts4.setAttribute('mixin', 'signal_right'); + el.appendChild(ts4); + } + if (trafficsignalArray[2]) { + const ts5 = document.createElement('a-entity'); + ts5.setAttribute('position', { + x: -intersectWidth / 3, + y: intersectDepth / 2, + z: 0.1 + }); + ts5.setAttribute('rotation', { x: 120, y: 90, z: 90 }); + ts5.setAttribute('mixin', 'signal_left'); + el.appendChild(ts5); + const ts6 = document.createElement('a-entity'); + ts6.setAttribute('position', { + x: intersectWidth / 3, + y: intersectDepth / 2, + z: 0.1 + }); + ts6.setAttribute('rotation', { x: 90, y: 90, z: 90 }); + ts6.setAttribute('mixin', 'signal_right'); + el.appendChild(ts6); + } + if (trafficsignalArray[3]) { + const ts7 = document.createElement('a-entity'); + ts7.setAttribute('position', { + x: intersectWidth / 3, + y: -intersectDepth / 2, + z: 0.1 + }); + ts7.setAttribute('rotation', { x: -60, y: 90, z: 90 }); + ts7.setAttribute('mixin', 'signal_left'); + el.appendChild(ts7); + const ts8 = document.createElement('a-entity'); + ts8.setAttribute('position', { + x: -intersectWidth / 3, + y: -intersectDepth / 2, + z: 0.1 + }); + ts8.setAttribute('rotation', { x: -90, y: 90, z: 90 }); + ts8.setAttribute('mixin', 'signal_right'); + el.appendChild(ts8); + } + + if (crosswalklArray[0]) { + const cw1 = document.createElement('a-entity'); + cw1.setAttribute('position', { x: intersectWidth / 2 - 2, z: 0.11 }); + cw1.setAttribute('rotation', { x: 0, y: 0, z: 180 }); + cw1.setAttribute('scale', { y: intersectDepth / 12 }); + cw1.setAttribute('mixin', 'markings crosswalk-zebra'); + el.appendChild(cw1); + } + if (crosswalklArray[1]) { + const cw2 = document.createElement('a-entity'); + cw2.setAttribute('position', { x: -intersectWidth / 2 + 2, z: 0.11 }); + cw2.setAttribute('rotation', { x: 0, y: 0, z: 180 }); + cw2.setAttribute('scale', { y: intersectDepth / 12 }); + cw2.setAttribute('mixin', 'markings crosswalk-zebra'); + el.appendChild(cw2); + } + if (crosswalklArray[2]) { + const cw3 = document.createElement('a-entity'); + cw3.setAttribute('position', { y: -intersectDepth / 2 + 2, z: 0.11 }); + cw3.setAttribute('rotation', { x: 0, y: 0, z: 90 }); + cw3.setAttribute('scale', { y: intersectWidth / 12 }); + cw3.setAttribute('mixin', 'markings crosswalk-zebra'); + el.appendChild(cw3); + } + if (crosswalklArray[3]) { + const cw4 = document.createElement('a-entity'); + cw4.setAttribute('position', { y: intersectDepth / 2 - 2, z: 0.11 }); + cw4.setAttribute('rotation', { x: 0, y: 0, z: 90 }); + cw4.setAttribute('scale', { y: intersectWidth / 12 }); + cw4.setAttribute('mixin', 'markings crosswalk-zebra'); + el.appendChild(cw4); + } + } +}); diff --git a/src/index.js b/src/index.js index 20c089e7f..fce84ad08 100644 --- a/src/index.js +++ b/src/index.js @@ -19,6 +19,7 @@ require('./components/screentock.js'); require('aframe-atlas-uvs-component'); require('./components/streetplan-loader'); require('./components/street-geo.js'); +require('./components/intersection.js'); AFRAME.registerComponent('street', { schema: { @@ -200,359 +201,6 @@ AFRAME.registerComponent('streetmix-loader', { } }); -AFRAME.registerComponent('intersection', { - schema: { - dimensions: { type: 'string', default: '20 20' }, - sidewalk: { type: 'string', default: '0 0 0 0' }, - northeastcurb: { type: 'string', default: '0 0' }, - southwestcurb: { type: 'string', default: '0 0' }, - southeastcurb: { type: 'string', default: '0 0' }, - northwestcurb: { type: 'string', default: '0 0' }, - stopsign: { type: 'string', default: '0 0 0 0' }, - trafficsignal: { type: 'string', default: '0 0 0 0' }, - crosswalk: { type: 'string', default: '0 0 0 0' } - }, - init: function () { - var data = this.data; - var el = this.el; - - // remove all child nodes if exists - while (el.firstChild) { - el.removeChild(el.lastChild); - } - const dimensionsArray = data.dimensions.split(' ').map((i) => Number(i)); - const positionArray = [ - this.el.getAttribute('position').x, - this.el.getAttribute('position').y, - this.el.getAttribute('position').z - ]; - const sidewalkArray = data.sidewalk.split(' ').map((i) => Number(i)); - const northeastcurbArray = data.northeastcurb - .split(' ') - .map((i) => Number(i)); - const southwestcurbArray = data.southwestcurb - .split(' ') - .map((i) => Number(i)); - const southeastcurbArray = data.southeastcurb - .split(' ') - .map((i) => Number(i)); - const northwestcurbArray = data.northwestcurb - .split(' ') - .map((i) => Number(i)); - const stopsignArray = data.stopsign.split(' ').map((i) => Number(i)); - const trafficsignalArray = data.trafficsignal - .split(' ') - .map((i) => Number(i)); - const crosswalklArray = data.crosswalk.split(' ').map((i) => Number(i)); - - const intersectWidth = dimensionsArray[0]; - const intersectDepth = dimensionsArray[1]; - - this.el.setAttribute( - 'geometry', - `primitive:box; width: ${intersectWidth}; height: ${intersectDepth}; depth:0.2` - ); - this.el.setAttribute('position', { - x: positionArray[0], - y: -0.1, - z: positionArray[2] - }); - this.el.setAttribute('rotation', '-90 0 0'); - this.el.setAttribute( - 'material', - 'src: #asphalt-texture; repeat:5 5; roughness:1' - ); - - function createSidewalkElem({ - length, - width, - positionVec, - scaleVec = { x: 1, y: 1, z: 1 }, - rotationVec - }) { - const sd = document.createElement('a-entity'); - const repeatCountInter = []; - repeatCountInter[0] = width / 2; - // every 2 meters repeat sidewalk texture - repeatCountInter[1] = parseInt(length / 2); - - sd.setAttribute('geometry', 'primitive', 'box'); - sd.setAttribute('geometry', 'height: 0.4'); - sd.setAttribute('position', positionVec); - sd.setAttribute('scale', scaleVec); - sd.setAttribute('geometry', 'depth', length); - sd.setAttribute('geometry', 'width', width); - sd.setAttribute('rotation', rotationVec); - sd.setAttribute('mixin', 'sidewalk'); - sd.setAttribute( - 'material', - `repeat: ${repeatCountInter[0]} ${repeatCountInter[1]}` - ); - el.appendChild(sd); - } - - // describe sidewalk parameters - const sidewalkParams = { - west: { - positionVec: { x: intersectWidth / 2 - sidewalkArray[0] / 2, z: 0.1 }, - rotationVec: { x: 90, y: 0, z: 0 }, - length: intersectDepth, - width: sidewalkArray[0] - }, - east: { - positionVec: { x: -intersectWidth / 2 + sidewalkArray[1] / 2, z: 0.1 }, - rotationVec: { x: 90, y: 0, z: 0 }, - length: intersectDepth, - width: sidewalkArray[1] - }, - north: { - positionVec: { - y: -intersectDepth / 2 + sidewalkArray[2] / 2, - // add x offset to avoid sidewalk's element overlap - x: sidewalkArray[1] / 2 - sidewalkArray[0] / 2, - z: 0.1 - }, - rotationVec: { x: 0, y: 90, z: -90 }, - // minus the width of the crossing sidewalk - length: intersectWidth - sidewalkArray[1] - sidewalkArray[0], - width: sidewalkArray[2] - }, - south: { - positionVec: { - y: intersectDepth / 2 - sidewalkArray[3] / 2, - // add x offset to avoid sidewalk's element overlap - x: sidewalkArray[1] / 2 - sidewalkArray[0] / 2, - z: 0.1 - }, - rotationVec: { x: 0, y: 90, z: -90 }, - // minus the width of the crossing sidewalk - length: intersectWidth - sidewalkArray[1] - sidewalkArray[0], - width: sidewalkArray[3] - } - }; - - // create sidewalks if they are given in sidewalkArray - const selectedSidewalks = Object.keys(sidewalkParams).filter( - (el, ind) => sidewalkArray[ind] - ); - - selectedSidewalks.forEach((sidewalkName, ind) => { - const params = sidewalkParams[sidewalkName]; - createSidewalkElem(params); - }); - - // describe curb parameters - const curbParams = { - northeast: { - positionVec: { - x: intersectWidth / 2 - northeastcurbArray[0] / 2, - y: intersectDepth / 2 - northeastcurbArray[1] / 2, - z: 0.1 - }, - rotationVec: { x: 0, y: 90, z: -90 }, - length: northeastcurbArray[0], - width: northeastcurbArray[1] - }, - southwest: { - positionVec: { - x: -intersectWidth / 2 + southwestcurbArray[0] / 2, - y: -intersectDepth / 2 + southwestcurbArray[1] / 2, - z: 0.1 - }, - rotationVec: { x: 0, y: 90, z: -90 }, - length: southwestcurbArray[0], - width: southwestcurbArray[1] - }, - southeast: { - positionVec: { - x: intersectWidth / 2 - southeastcurbArray[0] / 2, - y: -intersectDepth / 2 + southeastcurbArray[1] / 2, - z: 0.1 - }, - rotationVec: { x: 0, y: 90, z: -90 }, - length: southeastcurbArray[0], - width: southeastcurbArray[1] - }, - northwest: { - positionVec: { - x: -intersectWidth / 2 + northwestcurbArray[0] / 2, - y: intersectDepth / 2 - northwestcurbArray[1] / 2, - z: 0.1 - }, - rotationVec: { x: 0, y: 90, z: -90 }, - length: northwestcurbArray[0], - width: northwestcurbArray[1] - } - }; - - // create curbs if they are given - for (const [curbName, params] of Object.entries(curbParams)) { - if (data[`${curbName}curb`] !== '0 0') { - createSidewalkElem(params); - } - } - - if (stopsignArray[0]) { - const ss1 = document.createElement('a-entity'); - ss1.setAttribute('position', { - x: intersectWidth / 2, - y: intersectDepth / 3, - z: 0.1 - }); - ss1.setAttribute('rotation', { x: 0, y: 90, z: 90 }); - ss1.setAttribute('mixin', 'stop_sign'); - el.appendChild(ss1); - } - if (stopsignArray[1]) { - const ss2 = document.createElement('a-entity'); - ss2.setAttribute('position', { - x: -intersectWidth / 2, - y: -intersectDepth / 3, - z: 0.1 - }); - ss2.setAttribute('rotation', { x: 0, y: -90, z: -90 }); - ss2.setAttribute('mixin', 'stop_sign'); - el.appendChild(ss2); - } - if (stopsignArray[2]) { - const ss3 = document.createElement('a-entity'); - ss3.setAttribute('position', { - x: -intersectWidth / 3, - y: intersectDepth / 2, - z: 0.1 - }); - ss3.setAttribute('rotation', { x: -90, y: 90, z: 90 }); - ss3.setAttribute('mixin', 'stop_sign'); - el.appendChild(ss3); - } - if (stopsignArray[3]) { - const ss4 = document.createElement('a-entity'); - ss4.setAttribute('position', { - x: intersectWidth / 3, - y: -intersectDepth / 2, - z: 0.1 - }); - ss4.setAttribute('rotation', { x: 90, y: -90, z: -90 }); - ss4.setAttribute('mixin', 'stop_sign'); - el.appendChild(ss4); - } - - if (trafficsignalArray[0]) { - const ts1 = document.createElement('a-entity'); - ts1.setAttribute('position', { - x: intersectWidth / 2, - y: intersectDepth / 3, - z: 0.3 - }); - ts1.setAttribute('rotation', { x: 210, y: 90, z: 90 }); - ts1.setAttribute('mixin', 'signal_left'); - el.appendChild(ts1); - const ts2 = document.createElement('a-entity'); - ts2.setAttribute('position', { - x: intersectWidth / 2, - y: -intersectDepth / 3, - z: 0.3 - }); - ts2.setAttribute('rotation', { x: 180, y: 90, z: 90 }); - ts2.setAttribute('mixin', 'signal_right'); - el.appendChild(ts2); - } - if (trafficsignalArray[1]) { - const ts3 = document.createElement('a-entity'); - ts3.setAttribute('position', { - x: -intersectWidth / 2, - y: -intersectDepth / 3, - z: 0.3 - }); - ts3.setAttribute('rotation', { x: 30, y: 90, z: 90 }); - ts3.setAttribute('mixin', 'signal_left'); - el.appendChild(ts3); - const ts4 = document.createElement('a-entity'); - ts4.setAttribute('position', { - x: -intersectWidth / 2, - y: intersectDepth / 3, - z: 0.3 - }); - ts4.setAttribute('rotation', { x: 0, y: 90, z: 90 }); - ts4.setAttribute('mixin', 'signal_right'); - el.appendChild(ts4); - } - if (trafficsignalArray[2]) { - const ts5 = document.createElement('a-entity'); - ts5.setAttribute('position', { - x: -intersectWidth / 3, - y: intersectDepth / 2, - z: 0.1 - }); - ts5.setAttribute('rotation', { x: 120, y: 90, z: 90 }); - ts5.setAttribute('mixin', 'signal_left'); - el.appendChild(ts5); - const ts6 = document.createElement('a-entity'); - ts6.setAttribute('position', { - x: intersectWidth / 3, - y: intersectDepth / 2, - z: 0.1 - }); - ts6.setAttribute('rotation', { x: 90, y: 90, z: 90 }); - ts6.setAttribute('mixin', 'signal_right'); - el.appendChild(ts6); - } - if (trafficsignalArray[3]) { - const ts7 = document.createElement('a-entity'); - ts7.setAttribute('position', { - x: intersectWidth / 3, - y: -intersectDepth / 2, - z: 0.1 - }); - ts7.setAttribute('rotation', { x: -60, y: 90, z: 90 }); - ts7.setAttribute('mixin', 'signal_left'); - el.appendChild(ts7); - const ts8 = document.createElement('a-entity'); - ts8.setAttribute('position', { - x: -intersectWidth / 3, - y: -intersectDepth / 2, - z: 0.1 - }); - ts8.setAttribute('rotation', { x: -90, y: 90, z: 90 }); - ts8.setAttribute('mixin', 'signal_right'); - el.appendChild(ts8); - } - - if (crosswalklArray[0]) { - const cw1 = document.createElement('a-entity'); - cw1.setAttribute('position', { x: intersectWidth / 2 - 2, z: 0.11 }); - cw1.setAttribute('rotation', { x: 0, y: 0, z: 180 }); - cw1.setAttribute('scale', { y: intersectDepth / 12 }); - cw1.setAttribute('mixin', 'markings crosswalk-zebra'); - el.appendChild(cw1); - } - if (crosswalklArray[1]) { - const cw2 = document.createElement('a-entity'); - cw2.setAttribute('position', { x: -intersectWidth / 2 + 2, z: 0.11 }); - cw2.setAttribute('rotation', { x: 0, y: 0, z: 180 }); - cw2.setAttribute('scale', { y: intersectDepth / 12 }); - cw2.setAttribute('mixin', 'markings crosswalk-zebra'); - el.appendChild(cw2); - } - if (crosswalklArray[2]) { - const cw3 = document.createElement('a-entity'); - cw3.setAttribute('position', { y: -intersectDepth / 2 + 2, z: 0.11 }); - cw3.setAttribute('rotation', { x: 0, y: 0, z: 90 }); - cw3.setAttribute('scale', { y: intersectWidth / 12 }); - cw3.setAttribute('mixin', 'markings crosswalk-zebra'); - el.appendChild(cw3); - } - if (crosswalklArray[3]) { - const cw4 = document.createElement('a-entity'); - cw4.setAttribute('position', { y: intersectDepth / 2 - 2, z: 0.11 }); - cw4.setAttribute('rotation', { x: 0, y: 0, z: 90 }); - cw4.setAttribute('scale', { y: intersectWidth / 12 }); - cw4.setAttribute('mixin', 'markings crosswalk-zebra'); - el.appendChild(cw4); - } - } -}); - AFRAME.registerComponent('street-environment', { schema: { preset: { From 7ecda9246c2a4e9545041d28f88b93badf2a602c Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Sun, 16 Jun 2024 20:19:33 -0400 Subject: [PATCH 2/6] add segment type attribute to segment element --- src/aframe-streetmix-parsers.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/aframe-streetmix-parsers.js b/src/aframe-streetmix-parsers.js index 553d52ea8..6dd7c286e 100644 --- a/src/aframe-streetmix-parsers.js +++ b/src/aframe-streetmix-parsers.js @@ -1702,6 +1702,7 @@ function processSegments( // append the new surfaceElement to the segmentParentEl streetParentEl.append(segmentParentEl); segmentParentEl.setAttribute('position', segmentPositionX + ' 0 0'); + segmentParentEl.setAttribute('data-type', segments[i].type); segmentParentEl.setAttribute( 'data-layer-name', 'Segment • ' + segments[i].type + ', ' + variantList[0] From e14a8693904e61fec9acd912b71018137ca69a49 Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Sun, 16 Jun 2024 22:06:05 -0400 Subject: [PATCH 3/6] add data-variant attribute to segmentParentEl --- src/aframe-streetmix-parsers.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/aframe-streetmix-parsers.js b/src/aframe-streetmix-parsers.js index 6dd7c286e..0a834ceda 100644 --- a/src/aframe-streetmix-parsers.js +++ b/src/aframe-streetmix-parsers.js @@ -1703,6 +1703,7 @@ function processSegments( streetParentEl.append(segmentParentEl); segmentParentEl.setAttribute('position', segmentPositionX + ' 0 0'); segmentParentEl.setAttribute('data-type', segments[i].type); + segmentParentEl.setAttribute('data-variant', variantList.join('|')); segmentParentEl.setAttribute( 'data-layer-name', 'Segment • ' + segments[i].type + ', ' + variantList[0] From ca543195e5c3d7cf96703219c32795fcf1d2162e Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Thu, 11 Jul 2024 13:28:01 -0400 Subject: [PATCH 4/6] add auto-intersection component --- src/aframe-streetmix-parsers.js | 1 + src/components/auto-intersection.js | 198 ++++++++++++++++++++++++++++ src/components/intersection.js | 22 ++-- src/index.js | 1 + 4 files changed, 211 insertions(+), 11 deletions(-) create mode 100644 src/components/auto-intersection.js diff --git a/src/aframe-streetmix-parsers.js b/src/aframe-streetmix-parsers.js index 0a834ceda..8ffd41db2 100644 --- a/src/aframe-streetmix-parsers.js +++ b/src/aframe-streetmix-parsers.js @@ -1704,6 +1704,7 @@ function processSegments( segmentParentEl.setAttribute('position', segmentPositionX + ' 0 0'); segmentParentEl.setAttribute('data-type', segments[i].type); segmentParentEl.setAttribute('data-variant', variantList.join('|')); + segmentParentEl.setAttribute('data-width', segments[i].width); segmentParentEl.setAttribute( 'data-layer-name', 'Segment • ' + segments[i].type + ', ' + variantList[0] diff --git a/src/components/auto-intersection.js b/src/components/auto-intersection.js new file mode 100644 index 000000000..ea8d9b4f3 --- /dev/null +++ b/src/components/auto-intersection.js @@ -0,0 +1,198 @@ +/* global AFRAME */ +AFRAME.registerComponent('auto-intersection', { + dependencies: ['intersection'], + schema: { + // selectors of street elements for create intersection + northStreet: { type: 'selector' }, + southStreet: { type: 'selector' }, + westStreet: { type: 'selector' }, + eastStreet: { type: 'selector' } + }, + update: function () { + const el = this.el; + const intersectionProps = this.calculateDataForIntersection(); + el.setAttribute('intersection', intersectionProps); + }, + // calculate all properties in string format for the intersection component + calculateDataForIntersection() { + const data = this.data; + + // cardinal directions clockwise + const cardinal = ['north', 'east', 'south', 'west']; + + // dimensions of the left, right sidewalk pedestrian parts of the street + // (with sidewalk segment types) and total street width + const dimensions = { + north: {}, + east: {}, + south: {}, + west: {} + }; + cardinal.forEach((cardinalDir) => { + const sideStreetEl = data[cardinalDir + 'Street']; + const streetParent = sideStreetEl + ? sideStreetEl.querySelector('.street-parent') + : null; + if (streetParent) { + dimensions[cardinalDir] = this.getStreetWidths(streetParent); + } + }); + + // get dimensions of sidewalks at corners + let curbSizes = { + northeast: [ + dimensions['north']['right'] || 0, + dimensions['east']['right'] || 0 + ], + southeast: [ + dimensions['south']['right'] || 0, + dimensions['east']['left'] || 0 + ], + southwest: [ + dimensions['south']['left'] || 0, + dimensions['west']['left'] || 0 + ], + northwest: [ + dimensions['north']['left'] || 0, + dimensions['west']['right'] || 0 + ] + }; + function getCurbValue(curbSizes) { + if (curbSizes[0] > 0 && curbSizes[1] > 0) { + return curbSizes.join(' '); + } else { + return '0 0'; + } + } + // string values of curbs for the intersection component + const InterNortheastcurb = getCurbValue(curbSizes['northeast']); + const InterSouthwestcurb = getCurbValue(curbSizes['southwest']); + const InterSoutheastcurb = getCurbValue(curbSizes['southeast']); + const InterNorthwestcurb = getCurbValue(curbSizes['northwest']); + + // get sidewalk values (string) for the intersection component + const interSidewalk = [ + data['westStreet'] + ? curbSizes['northeast'][0] || curbSizes['southeast'][0] + : 0, + data['eastStreet'] + ? curbSizes['northwest'][0] || curbSizes['southwest'][0] + : 0, + data['northStreet'] + ? curbSizes['southeast'][1] || curbSizes['southwest'][1] + : 0, + data['southStreet'] + ? curbSizes['northwest'][1] || curbSizes['northeast'][1] + : 0 + ].join(' '); + + // get dimensions (string) for the intersection component + // assume that width of north street == width of south street. Same for west-east + const interDimensions = [ + dimensions['north'].total || dimensions['south'].total, + dimensions['west'].total || dimensions['east'].total + ].join(' '); + + // cardinal order in the intersection component schema + const cardinalOrder = ['east', 'west', 'north', 'south']; + + // get data for stopsignals, trafficsignal, crosswalk + const interStreetProps = cardinalOrder + .map((side) => { + if (data[side + 'Street']) { + return '1'; + } else { + return '0'; + } + }, []) + .join(' '); + + return { + dimensions: interDimensions, + sidewalk: interSidewalk, + northeastcurb: InterNortheastcurb, + southwestcurb: InterSouthwestcurb, + southeastcurb: InterSoutheastcurb, + northwestcurb: InterNorthwestcurb, + stopsign: interStreetProps, + trafficsignal: interStreetProps, + crosswalk: interStreetProps + }; + }, + /* + * calculate left, right sidewalk pedestrian parts of the street (with sidewalk segment types) + * and total street width + */ + getStreetWidths: function (streetParent) { + const sectionsWidths = this.getSectionsWidth(streetParent); + const leftSidewalkWidth = + sectionsWidths[0].type === 'sidewalk' ? sectionsWidths[0].width : 0; + const lastSection = sectionsWidths[sectionsWidths.length - 1]; + const rightSidewalkWidth = + lastSection.type === 'sidewalk' ? lastSection.width : 0; + const streetWidth = sectionsWidths.reduce( + (totalWidth, section) => section.width + totalWidth, + 0 + ); + return { + left: leftSidewalkWidth.toFixed(3), + right: rightSidewalkWidth.toFixed(3), + total: streetWidth.toFixed(3) + }; + }, + /* + * calculate width of street sections (segments of the same type following each other) + */ + getSectionsWidth: function (streetParentEl) { + // sidewalk segment types + const sidewalkTypes = [ + 'sidewalk', + 'sidewalk-wayfinding', + 'sidewalk-bench', + 'sidewalk-bike-rack', + 'sidewalk-tree', + 'utilities', + 'sidewalk-lamp', + 'outdoor-dining', + 'bikeshare' + ]; + + // one section is the summed value of the widths of sidewalk or 'drive-lane' segments + // ('drive-lane' here is an all other segments types). + // If there is a sidewalk in the middle of the street, it will also be taken into account as section + const streetSections = []; + let currentType = null; + let currentWidth = 0; + + for (const segmentParentEl of streetParentEl.children) { + const segmentType = segmentParentEl.getAttribute('data-type'); + const segmentVariant = segmentParentEl.getAttribute('data-variant'); + const segmentWidth = parseFloat( + segmentParentEl.getAttribute('data-width') + ); + + if (!segmentType) continue; + let sectionType = + sidewalkTypes.includes(segmentType) || + segmentVariant.includes('sidewalk') + ? 'sidewalk' + : 'drive-lane'; + + if (sectionType !== currentType) { + if (currentType !== null) { + streetSections.push({ type: currentType, width: currentWidth }); + } + currentType = sectionType; + currentWidth = segmentWidth; + } else { + currentWidth += segmentWidth; + } + } + // Add the last accumulated segment + if (currentType !== null) { + streetSections.push({ type: currentType, width: currentWidth }); + } + + return streetSections; + } +}); diff --git a/src/components/intersection.js b/src/components/intersection.js index 93cf057fe..ef3e8cf7b 100644 --- a/src/components/intersection.js +++ b/src/components/intersection.js @@ -11,9 +11,9 @@ AFRAME.registerComponent('intersection', { trafficsignal: { type: 'string', default: '0 0 0 0' }, crosswalk: { type: 'string', default: '0 0 0 0' } }, - init: function () { - var data = this.data; - var el = this.el; + update: function () { + const data = this.data; + const el = this.el; // remove all child nodes if exists while (el.firstChild) { @@ -334,14 +334,6 @@ AFRAME.registerComponent('intersection', { el.appendChild(cw2); } if (crosswalklArray[2]) { - const cw3 = document.createElement('a-entity'); - cw3.setAttribute('position', { y: -intersectDepth / 2 + 2, z: 0.11 }); - cw3.setAttribute('rotation', { x: 0, y: 0, z: 90 }); - cw3.setAttribute('scale', { y: intersectWidth / 12 }); - cw3.setAttribute('mixin', 'markings crosswalk-zebra'); - el.appendChild(cw3); - } - if (crosswalklArray[3]) { const cw4 = document.createElement('a-entity'); cw4.setAttribute('position', { y: intersectDepth / 2 - 2, z: 0.11 }); cw4.setAttribute('rotation', { x: 0, y: 0, z: 90 }); @@ -349,5 +341,13 @@ AFRAME.registerComponent('intersection', { cw4.setAttribute('mixin', 'markings crosswalk-zebra'); el.appendChild(cw4); } + if (crosswalklArray[3]) { + const cw3 = document.createElement('a-entity'); + cw3.setAttribute('position', { y: -intersectDepth / 2 + 2, z: 0.11 }); + cw3.setAttribute('rotation', { x: 0, y: 0, z: 90 }); + cw3.setAttribute('scale', { y: intersectWidth / 12 }); + cw3.setAttribute('mixin', 'markings crosswalk-zebra'); + el.appendChild(cw3); + } } }); diff --git a/src/index.js b/src/index.js index fce84ad08..83dc8ba7f 100644 --- a/src/index.js +++ b/src/index.js @@ -20,6 +20,7 @@ require('aframe-atlas-uvs-component'); require('./components/streetplan-loader'); require('./components/street-geo.js'); require('./components/intersection.js'); +require('./components/auto-intersection.js'); AFRAME.registerComponent('street', { schema: { From ac610285d601ab3f0e5ffd18b75500f9e9156442 Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Tue, 16 Jul 2024 20:16:24 -0400 Subject: [PATCH 5/6] use intersection.js from main branch --- src/components/intersection.js | 352 +++++++++++++++++++-------------- 1 file changed, 202 insertions(+), 150 deletions(-) diff --git a/src/components/intersection.js b/src/components/intersection.js index ef3e8cf7b..77a519f03 100644 --- a/src/components/intersection.js +++ b/src/components/intersection.js @@ -2,6 +2,7 @@ AFRAME.registerComponent('intersection', { schema: { dimensions: { type: 'string', default: '20 20' }, + // cardinal direction order for sidewalk, stopsign, crosswalk: west, east, north, south sidewalk: { type: 'string', default: '0 0 0 0' }, northeastcurb: { type: 'string', default: '0 0' }, southwestcurb: { type: 'string', default: '0 0' }, @@ -9,22 +10,32 @@ AFRAME.registerComponent('intersection', { northwestcurb: { type: 'string', default: '0 0' }, stopsign: { type: 'string', default: '0 0 0 0' }, trafficsignal: { type: 'string', default: '0 0 0 0' }, - crosswalk: { type: 'string', default: '0 0 0 0' } + crosswalk: { type: 'string', default: '0 0 0 0' }, + synchronize: { default: true } }, update: function () { const data = this.data; const el = this.el; + // do not call the update function when the data.synchronize is set to false + if (!data.synchronize) return; + + this.createIntersectionElements(); + + // the intersecton elements has been created, set the synchronize flag to false + el.setAttribute('intersection', 'synchronize', false); + }, + createIntersectionElements: function () { + const data = this.data; + const el = this.el; + const directionOrder = ['west', 'east', 'north', 'south']; + // remove all child nodes if exists while (el.firstChild) { el.removeChild(el.lastChild); } + const dimensionsArray = data.dimensions.split(' ').map((i) => Number(i)); - const positionArray = [ - this.el.getAttribute('position').x, - this.el.getAttribute('position').y, - this.el.getAttribute('position').z - ]; const sidewalkArray = data.sidewalk.split(' ').map((i) => Number(i)); const northeastcurbArray = data.northeastcurb .split(' ') @@ -51,11 +62,7 @@ AFRAME.registerComponent('intersection', { 'geometry', `primitive:box; width: ${intersectWidth}; height: ${intersectDepth}; depth:0.2` ); - this.el.setAttribute('position', { - x: positionArray[0], - y: -0.1, - z: positionArray[2] - }); + this.el.object3D.position.setY(-0.1); this.el.setAttribute('rotation', '-90 0 0'); this.el.setAttribute( 'material', @@ -67,26 +74,27 @@ AFRAME.registerComponent('intersection', { width, positionVec, scaleVec = { x: 1, y: 1, z: 1 }, - rotationVec + rotationVec, + displayName }) { const sd = document.createElement('a-entity'); - const repeatCountInter = []; - repeatCountInter[0] = width / 2; // every 2 meters repeat sidewalk texture - repeatCountInter[1] = parseInt(length / 2); + const repeatCountInter = [width / 2, parseInt(length / 2)]; - sd.setAttribute('geometry', 'primitive', 'box'); - sd.setAttribute('geometry', 'height: 0.4'); + sd.setAttribute( + 'geometry', + `primitive:box; depth: ${length}; width: ${width}; height: 0.4` + ); sd.setAttribute('position', positionVec); sd.setAttribute('scale', scaleVec); - sd.setAttribute('geometry', 'depth', length); - sd.setAttribute('geometry', 'width', width); sd.setAttribute('rotation', rotationVec); sd.setAttribute('mixin', 'sidewalk'); + sd.classList.add('autocreated'); sd.setAttribute( 'material', `repeat: ${repeatCountInter[0]} ${repeatCountInter[1]}` ); + sd.setAttribute('data-layer-name', 'Sidewalk � ' + displayName); el.appendChild(sd); } @@ -96,37 +104,41 @@ AFRAME.registerComponent('intersection', { positionVec: { x: intersectWidth / 2 - sidewalkArray[0] / 2, z: 0.1 }, rotationVec: { x: 90, y: 0, z: 0 }, length: intersectDepth, - width: sidewalkArray[0] + width: sidewalkArray[0], + displayName: 'West' }, east: { positionVec: { x: -intersectWidth / 2 + sidewalkArray[1] / 2, z: 0.1 }, rotationVec: { x: 90, y: 0, z: 0 }, length: intersectDepth, - width: sidewalkArray[1] + width: sidewalkArray[1], + displayName: 'East' }, north: { positionVec: { - y: -intersectDepth / 2 + sidewalkArray[2] / 2, // add x offset to avoid sidewalk's element overlap x: sidewalkArray[1] / 2 - sidewalkArray[0] / 2, + y: -intersectDepth / 2 + sidewalkArray[2] / 2, z: 0.1 }, rotationVec: { x: 0, y: 90, z: -90 }, // minus the width of the crossing sidewalk length: intersectWidth - sidewalkArray[1] - sidewalkArray[0], - width: sidewalkArray[2] + width: sidewalkArray[2], + displayName: 'North' }, south: { positionVec: { - y: intersectDepth / 2 - sidewalkArray[3] / 2, // add x offset to avoid sidewalk's element overlap x: sidewalkArray[1] / 2 - sidewalkArray[0] / 2, + y: intersectDepth / 2 - sidewalkArray[3] / 2, z: 0.1 }, rotationVec: { x: 0, y: 90, z: -90 }, // minus the width of the crossing sidewalk length: intersectWidth - sidewalkArray[1] - sidewalkArray[0], - width: sidewalkArray[3] + width: sidewalkArray[3], + displayName: 'South' } }; @@ -150,7 +162,8 @@ AFRAME.registerComponent('intersection', { }, rotationVec: { x: 0, y: 90, z: -90 }, length: northeastcurbArray[0], - width: northeastcurbArray[1] + width: northeastcurbArray[1], + displayName: 'Northeast' }, southwest: { positionVec: { @@ -160,7 +173,8 @@ AFRAME.registerComponent('intersection', { }, rotationVec: { x: 0, y: 90, z: -90 }, length: southwestcurbArray[0], - width: southwestcurbArray[1] + width: southwestcurbArray[1], + displayName: 'Southwest' }, southeast: { positionVec: { @@ -170,7 +184,8 @@ AFRAME.registerComponent('intersection', { }, rotationVec: { x: 0, y: 90, z: -90 }, length: southeastcurbArray[0], - width: southeastcurbArray[1] + width: southeastcurbArray[1], + displayName: 'Southeast' }, northwest: { positionVec: { @@ -180,7 +195,8 @@ AFRAME.registerComponent('intersection', { }, rotationVec: { x: 0, y: 90, z: -90 }, length: northwestcurbArray[0], - width: northwestcurbArray[1] + width: northwestcurbArray[1], + displayName: 'Northwest' } }; @@ -191,138 +207,168 @@ AFRAME.registerComponent('intersection', { } } - if (stopsignArray[0]) { - const ss1 = document.createElement('a-entity'); - ss1.setAttribute('position', { - x: intersectWidth / 2, - y: intersectDepth / 3, - z: 0.1 - }); - ss1.setAttribute('rotation', { x: 0, y: 90, z: 90 }); - ss1.setAttribute('mixin', 'stop_sign'); - el.appendChild(ss1); - } - if (stopsignArray[1]) { - const ss2 = document.createElement('a-entity'); - ss2.setAttribute('position', { - x: -intersectWidth / 2, - y: -intersectDepth / 3, - z: 0.1 - }); - ss2.setAttribute('rotation', { x: 0, y: -90, z: -90 }); - ss2.setAttribute('mixin', 'stop_sign'); - el.appendChild(ss2); - } - if (stopsignArray[2]) { - const ss3 = document.createElement('a-entity'); - ss3.setAttribute('position', { - x: -intersectWidth / 3, - y: intersectDepth / 2, - z: 0.1 - }); - ss3.setAttribute('rotation', { x: -90, y: 90, z: 90 }); - ss3.setAttribute('mixin', 'stop_sign'); - el.appendChild(ss3); - } - if (stopsignArray[3]) { - const ss4 = document.createElement('a-entity'); - ss4.setAttribute('position', { - x: intersectWidth / 3, - y: -intersectDepth / 2, - z: 0.1 - }); - ss4.setAttribute('rotation', { x: 90, y: -90, z: -90 }); - ss4.setAttribute('mixin', 'stop_sign'); - el.appendChild(ss4); - } + // describe stop signals parameters + const stopsignals = { + west: { + position: { + x: intersectWidth / 2, + y: intersectDepth / 3, + z: 0.1 + }, + rotation: { x: 0, y: 90, z: 90 } + }, + east: { + position: { + x: -intersectWidth / 2, + y: -intersectDepth / 3, + z: 0.1 + }, + rotation: { x: 0, y: -90, z: -90 } + }, + north: { + position: { + x: -intersectWidth / 3, + y: intersectDepth / 2, + z: 0.1 + }, + rotation: { x: -90, y: 90, z: 90 } + }, + south: { + position: { + x: intersectWidth / 3, + y: -intersectDepth / 2, + z: 0.1 + }, + rotation: { x: 90, y: -90, z: -90 } + } + }; - if (trafficsignalArray[0]) { - const ts1 = document.createElement('a-entity'); - ts1.setAttribute('position', { - x: intersectWidth / 2, - y: intersectDepth / 3, - z: 0.3 - }); - ts1.setAttribute('rotation', { x: 210, y: 90, z: 90 }); - ts1.setAttribute('mixin', 'signal_left'); - el.appendChild(ts1); - const ts2 = document.createElement('a-entity'); - ts2.setAttribute('position', { - x: intersectWidth / 2, - y: -intersectDepth / 3, - z: 0.3 - }); - ts2.setAttribute('rotation', { x: 180, y: 90, z: 90 }); - ts2.setAttribute('mixin', 'signal_right'); - el.appendChild(ts2); - } - if (trafficsignalArray[1]) { - const ts3 = document.createElement('a-entity'); - ts3.setAttribute('position', { - x: -intersectWidth / 2, - y: -intersectDepth / 3, - z: 0.3 - }); - ts3.setAttribute('rotation', { x: 30, y: 90, z: 90 }); - ts3.setAttribute('mixin', 'signal_left'); - el.appendChild(ts3); - const ts4 = document.createElement('a-entity'); - ts4.setAttribute('position', { - x: -intersectWidth / 2, - y: intersectDepth / 3, - z: 0.3 - }); - ts4.setAttribute('rotation', { x: 0, y: 90, z: 90 }); - ts4.setAttribute('mixin', 'signal_right'); - el.appendChild(ts4); + function createStopSignal(direction) { + const stopSignEl = document.createElement('a-entity'); + const params = stopsignals[direction]; + stopSignEl.setAttribute('position', params['position']); + stopSignEl.setAttribute('rotation', params['rotation']); + stopSignEl.setAttribute('mixin', 'stop_sign'); + stopSignEl.classList.add('autocreated'); + stopSignEl.setAttribute('data-layer-name', 'Traffic Control � Stop Sign'); + return stopSignEl; } - if (trafficsignalArray[2]) { - const ts5 = document.createElement('a-entity'); - ts5.setAttribute('position', { - x: -intersectWidth / 3, - y: intersectDepth / 2, - z: 0.1 - }); - ts5.setAttribute('rotation', { x: 120, y: 90, z: 90 }); - ts5.setAttribute('mixin', 'signal_left'); - el.appendChild(ts5); - const ts6 = document.createElement('a-entity'); - ts6.setAttribute('position', { - x: intersectWidth / 3, - y: intersectDepth / 2, - z: 0.1 - }); - ts6.setAttribute('rotation', { x: 90, y: 90, z: 90 }); - ts6.setAttribute('mixin', 'signal_right'); - el.appendChild(ts6); - } - if (trafficsignalArray[3]) { - const ts7 = document.createElement('a-entity'); - ts7.setAttribute('position', { - x: intersectWidth / 3, - y: -intersectDepth / 2, - z: 0.1 - }); - ts7.setAttribute('rotation', { x: -60, y: 90, z: 90 }); - ts7.setAttribute('mixin', 'signal_left'); - el.appendChild(ts7); - const ts8 = document.createElement('a-entity'); - ts8.setAttribute('position', { - x: -intersectWidth / 3, - y: -intersectDepth / 2, - z: 0.1 + + // create stop signals + directionOrder.forEach((direction, index) => { + if (stopsignArray[index]) { + const stopSignEl = createStopSignal(direction); + el.appendChild(stopSignEl); + } + }); + + // describe traffic signals parameters + const trafficSignals = { + west: { + left: { + position: { + x: intersectWidth / 2, + y: intersectDepth / 3, + z: 0.3 + }, + rotation: { x: 210, y: 90, z: 90 } + }, + right: { + position: { + x: intersectWidth / 2, + y: -intersectDepth / 3, + z: 0.3 + }, + rotation: { x: 180, y: 90, z: 90 } + } + }, + east: { + left: { + position: { + x: -intersectWidth / 2, + y: -intersectDepth / 3, + z: 0.3 + }, + rotation: { x: 210, y: 90, z: 90 } + }, + right: { + position: { + x: -intersectWidth / 2, + y: intersectDepth / 3, + z: 0.3 + }, + rotation: { x: 0, y: 90, z: 90 } + } + }, + north: { + left: { + position: { + x: -intersectWidth / 3, + y: intersectDepth / 2, + z: 0.1 + }, + rotation: { x: 120, y: 90, z: 90 } + }, + right: { + position: { + x: intersectWidth / 3, + y: intersectDepth / 2, + z: 0.1 + }, + rotation: { x: 90, y: 90, z: 90 } + } + }, + south: { + left: { + position: { + x: intersectWidth / 3, + y: -intersectDepth / 2, + z: 0.1 + }, + rotation: { x: -60, y: 90, z: 90 } + }, + right: { + position: { + x: -intersectWidth / 3, + y: -intersectDepth / 2, + z: 0.1 + }, + rotation: { x: -90, y: 90, z: 90 } + } + } + }; + + function createTrafficSignals(direction) { + const params = trafficSignals[direction]; + ['left', 'right'].forEach((side) => { + const trafficSignalEl = document.createElement('a-entity'); + trafficSignalEl.setAttribute('position', params[side].position); + trafficSignalEl.setAttribute('rotation', params[side].rotation); + trafficSignalEl.setAttribute('mixin', `signal_${side}`); + trafficSignalEl.classList.add('autocreated'); + trafficSignalEl.setAttribute( + 'data-layer-name', + 'Traffic Signal � ' + direction + ' ' + side + ); + el.appendChild(trafficSignalEl); }); - ts8.setAttribute('rotation', { x: -90, y: 90, z: 90 }); - ts8.setAttribute('mixin', 'signal_right'); - el.appendChild(ts8); } + // create traffic signals + directionOrder.forEach((direction, index) => { + if (trafficsignalArray[index]) { + createTrafficSignals(direction); + } + }); + if (crosswalklArray[0]) { const cw1 = document.createElement('a-entity'); cw1.setAttribute('position', { x: intersectWidth / 2 - 2, z: 0.11 }); cw1.setAttribute('rotation', { x: 0, y: 0, z: 180 }); cw1.setAttribute('scale', { y: intersectDepth / 12 }); cw1.setAttribute('mixin', 'markings crosswalk-zebra'); + cw1.setAttribute('data-layer-name', 'Crosswalk � East'); + cw1.classList.add('autocreated'); el.appendChild(cw1); } if (crosswalklArray[1]) { @@ -331,14 +377,18 @@ AFRAME.registerComponent('intersection', { cw2.setAttribute('rotation', { x: 0, y: 0, z: 180 }); cw2.setAttribute('scale', { y: intersectDepth / 12 }); cw2.setAttribute('mixin', 'markings crosswalk-zebra'); + cw2.setAttribute('data-layer-name', 'Crosswalk � West'); + cw2.classList.add('autocreated'); el.appendChild(cw2); } if (crosswalklArray[2]) { const cw4 = document.createElement('a-entity'); cw4.setAttribute('position', { y: intersectDepth / 2 - 2, z: 0.11 }); + cw4.setAttribute('data-layer-name', 'Crosswalk � Zebra (Continental)'); cw4.setAttribute('rotation', { x: 0, y: 0, z: 90 }); cw4.setAttribute('scale', { y: intersectWidth / 12 }); cw4.setAttribute('mixin', 'markings crosswalk-zebra'); + cw4.classList.add('autocreated'); el.appendChild(cw4); } if (crosswalklArray[3]) { @@ -347,6 +397,8 @@ AFRAME.registerComponent('intersection', { cw3.setAttribute('rotation', { x: 0, y: 0, z: 90 }); cw3.setAttribute('scale', { y: intersectWidth / 12 }); cw3.setAttribute('mixin', 'markings crosswalk-zebra'); + cw3.setAttribute('data-layer-name', 'Crosswalk � Zebra (Continental)'); + cw3.classList.add('autocreated'); el.appendChild(cw3); } } From 202cb68ff9226812ce11a9c9b37d7c8696fd2b55 Mon Sep 17 00:00:00 2001 From: Alexander Goryushkin Date: Tue, 16 Jul 2024 20:48:19 -0400 Subject: [PATCH 6/6] fix issues add auto align street positions --- src/components/auto-intersection.js | 75 ++++++++++++++++++++++------- 1 file changed, 58 insertions(+), 17 deletions(-) diff --git a/src/components/auto-intersection.js b/src/components/auto-intersection.js index ea8d9b4f3..4df82ba5e 100644 --- a/src/components/auto-intersection.js +++ b/src/components/auto-intersection.js @@ -1,6 +1,5 @@ /* global AFRAME */ AFRAME.registerComponent('auto-intersection', { - dependencies: ['intersection'], schema: { // selectors of street elements for create intersection northStreet: { type: 'selector' }, @@ -10,25 +9,70 @@ AFRAME.registerComponent('auto-intersection', { }, update: function () { const el = this.el; - const intersectionProps = this.calculateDataForIntersection(); + // cardinal order in the intersection component schema + this.cardinalOrder = ['east', 'west', 'north', 'south']; + + const intersectionProps = (this.intersectionProps = + this.calculateDataForIntersection()); el.setAttribute('intersection', intersectionProps); + this.alignStreetsToIntersection(); + }, + alignStreetsToIntersection: function () { + const dimensions = this.dimensions; + const interDimensions = this.intersectionProps.dimensions.split(' '); + const data = this.data; + const interElPos = this.el.getAttribute('position'); + let newPos; + for (const streetDirection of this.cardinalOrder) { + // streetDirection = east, west, north, south + if (dimensions[streetDirection].total) { + const streetEl = data[streetDirection + 'Street']; + const length = streetEl.getAttribute('street').length; + + switch (streetDirection) { + case 'north': + newPos = { + x: interElPos.x, + z: interElPos.z - interDimensions[1] / 2 - length / 2 + }; + break; + case 'south': + newPos = { + x: interElPos.x, + z: interElPos.z + interDimensions[1] / 2 + length / 2 + }; + break; + case 'west': + newPos = { + x: interElPos.x - interDimensions[0] / 2 - length / 2, + z: interElPos.z + }; + break; + case 'east': + newPos = { + x: interElPos.x + interDimensions[0] / 2 + length / 2, + z: interElPos.z + }; + break; + } + streetEl.setAttribute('position', newPos); + } + } }, // calculate all properties in string format for the intersection component calculateDataForIntersection() { const data = this.data; - - // cardinal directions clockwise - const cardinal = ['north', 'east', 'south', 'west']; + const cardinalOrder = this.cardinalOrder; // dimensions of the left, right sidewalk pedestrian parts of the street // (with sidewalk segment types) and total street width - const dimensions = { + const dimensions = (this.dimensions = { north: {}, east: {}, south: {}, west: {} - }; - cardinal.forEach((cardinalDir) => { + }); + cardinalOrder.forEach((cardinalDir) => { const sideStreetEl = data[cardinalDir + 'Street']; const streetParent = sideStreetEl ? sideStreetEl.querySelector('.street-parent') @@ -72,17 +116,17 @@ AFRAME.registerComponent('auto-intersection', { // get sidewalk values (string) for the intersection component const interSidewalk = [ - data['westStreet'] + !data['eastStreet'] ? curbSizes['northeast'][0] || curbSizes['southeast'][0] : 0, - data['eastStreet'] + !data['westStreet'] ? curbSizes['northwest'][0] || curbSizes['southwest'][0] : 0, - data['northStreet'] - ? curbSizes['southeast'][1] || curbSizes['southwest'][1] - : 0, - data['southStreet'] + !data['northStreet'] ? curbSizes['northwest'][1] || curbSizes['northeast'][1] + : 0, + !data['southStreet'] + ? curbSizes['southeast'][1] || curbSizes['southwest'][1] : 0 ].join(' '); @@ -93,9 +137,6 @@ AFRAME.registerComponent('auto-intersection', { dimensions['west'].total || dimensions['east'].total ].join(' '); - // cardinal order in the intersection component schema - const cardinalOrder = ['east', 'west', 'north', 'south']; - // get data for stopsignals, trafficsignal, crosswalk const interStreetProps = cardinalOrder .map((side) => {