[지오프롭테크] 도시 바람길 분석 시뮬레이션
지오프롭테크 (GeoProptech) = 지리정보(geographic information system) + 부동산 (Property) + 기술 (Tech)
건물 공간정보 기반 2D Wind Flow Analysis
| “건물 공간정보를 기반으로 2차원 유동장을 계산하고, 변화된 속도장을 따라 바람길을 자동 추적하여 도시공간의 상대적 바람강도와 건물 후면의 역류·재순환 영역을 분석하는 GIS 기반 경량 도시 바람길 분석 기술” |
건물 공간정보 기반 2D 도시 바람길 분석 기능은 건물의 위치·형상·높이와 설정된 주풍향을 기반으로 건축물 주변의 2차원 유동장을 계산하고, 계산된 유동장을 따라 바람의 흐름을 자동 추적하여 도시 공간 내 바람길과 건물 후면의 역류·재순환 영역을 시각적으로 분석하는 기능이다.
단순히 건물 주변에 바람선을 임의로 생성하는 방식이 아니라, 건물 형상에 의해 변화되는 유동장을 먼저 계산한 후 그 결과를 기반으로 바람길을 자동 생성한다. 또한 바람세기를 절대 풍속(m/s)이 아닌 기준풍 대비 상대강도(%)로 표현하여 공간별 바람의 강약을 직관적으로 비교할 수 있다.
건물 → 유동장 → Streamline → 상대강도 → 후류·재순환의 분석 흐름을 하나의 GIS 화면에서 연결합니다.
사용자가 바람길을 직접 그리는 방식이 아니라 계산된 속도장을 따라 바람길이 자동 생성됩니다.
‘건물에 선을 피해 그리는 방식’이 아니라, 건물이 유동장을 변화시키고 그 유동장을 따라 바람길이 생성됩니다.
① 건물 후면 역류
바람이 건물을 지나간 뒤 흐름이 약해지고 일부가 반대 방향으로 돌아가는 재순환 영역입니다. 오염물질이나 열이 머무를 가능성이 있는 구역을 검토할 때 참고할 수 있습니다.
② 건물 모서리·교차부 역류
건물 배치가 복잡하거나 흐름이 급격히 바뀌는 곳에서 역류 영역이 여러 개 나타날 수 있습니다. 다만 역류가 있다고 해서 모두 실제 회오리라고 단정할 수는 없습니다.
③ 단지 내부의 재순환
건물로 둘러싸인 공간에서 바람이 빠져나가지 못하거나 되돌아 흐르는 영역을 확인합니다. 소스는 유출 경계와 연결되지 않은 내부 격자를 별도로 처리하므로, 막힌 공간의 결과는 경계 설정에도 영향을 받습니다.
이 기능은 단순히 건물 주변에 바람 방향 화살표를 그리는 것이 아니라 건물 배치에 따른 풍속 변화, 건물 후면의 바람 정체·역류, 좁은 통로의 풍속 증가, 회오리 영역 등을 지도에 표현하는 바람길 분석기입니다.
특히 소스에는 바람의 속도장을 먼저 계산한 뒤 그 흐름을 따라 유선(Streamline)을 그리고, 역류 영역을 별도 회오리 레이어로 표시하는 구조가 있습니다. 풍속은 기준풍 대비 백분율로 나타내며, fluid 근사 해석과 lbm 격자 볼츠만 기반 해석을 선택할 수 있습니다.
(1) 건물 회피: 건물 영역을 격자의 고체 셀로 처리하고, 계산된 속도장을 따라 유선을 생성합니다.
(2) 건물 사이의 바람: 격자별 속도장을 이용해 유선을 추적하므로, 건물 배치와 통로 형상에 따른 흐름 변화를 표현
(3) 건물 뒤쪽의 역류: 주풍 방향과 반대인 속도 성분을 가진 셀을 찾아 연결된 영역으로 묶고, 그 중심을 회오리 표시
(4) 애니메이션: 생성한 유선에 애니메이션 갱신을 적용해 바람이 이동하는 것처럼 표시합니다.
(5) 셀별 바람 분포: showCells와 cellMode 설정을 통해 속도 또는 주풍 방향 성분을 색상으로 표시할 수 있습니다.
| 구분 | 일반적인 바람 시각화 | 본 기능 |
| 바람선 | 단순 표시 | 유동장 기반 자동 생성 |
| 건물 | 배경/장애물 표시 | 유동 계산에 직접 반영 |
| 바람 방향 | 고정 방향 | 공간별 유동벡터에 따라 변화 |
| 바람세기 | 단순 색상 | 상대강도(%) 기반 다중 시각화 |
| 선 굵기 | 고정 | 바람강도에 따라 변화 |
| 애니메이션 | 동일 속도 | 바람강도에 따라 속도 변화 |
| 심볼 | 고정 | 바람강도에 따라 크기 변화 |
| 건물 후면 | 별도 분석 없음 | 역류·후류·재순환 후보 탐지 |
| 바람길 생성 | 사용자 직접 지정 | 다수의 시작점에서 자동 추적 |
| 공간분석 | 단순 시각화 | 2D 유동장 기반 분석 |
① 2D 바람 유동장 분석 건물 Polygon 및 건물 높이 정보를 분석 영역에 반영하여 건물에 의해 변화되는 바람의 방향과 속도장을 계산합니다. 건물 형상에 따른 바람 흐름 변화 건물 사이의 바람 흐름 건물 측면의 우회 흐름 건물 후면의 흐름 변화 공간별 상대적인 바람강도 분석 ② 바람길 자동 생성 사용자가 바람길을 직접 그리는 방식이 아니라 설정된 주풍향과 다수의 시작점을 기반으로 바람길을 자동 생성합니다. 계산된 속도장을 따라 Streamline을 자동 추적하여 건물 배치에 따라 휘어지고 분기되는 바람 흐름을 표현합니다. ③ 상대 바람강도 분석 본 시스템의 바람세기는 실제 풍속인 m/s를 직접 표시하는 값이 아니라 기준풍 대비 상대적인 바람강도(%)로 표현합니다. 따라서 동일한 분석 조건에서 도시공간별로 어느 위치의 바람이 상대적으로 강하고 약한지를 직관적으로 비교할 수 있습니다. ④ 바람강도 다중 시각화 하나의 상대 바람강도 값을 단순히 색상으로만 표현하지 않고 다양한 시각요소에 동시에 반영합니다. 색상 : 약한 바람 → 강한 바람 선 굵기 : 강한 바람일수록 굵게 표현 애니메이션 속도 : 강한 바람일수록 빠르게 표현 방향 심볼 크기 : 강한 바람일수록 크게 표현 이를 통해 정적인 분석 결과뿐만 아니라 실제 바람이 흐르는 듯한 동적인 흐름과 강약을 동시에 표현할 수 있습니다. ⑤ 후류·역류·재순환 분석 건물 후면에서 주풍향과 반대되는 흐름이 발생하는 영역을 분석하여 역류·후류·재순환 후보 영역을 별도로 탐지합니다. 지도상에서는 회전 심볼 등을 이용하여 일반적인 바람길과 구분하여 표현할 수 있습니다. |
this.vortexLayer_ = new ol.layer.Vector({ source: this.vortexSource_, style: function (feature) { var _windStrength = Number(feature.get('windStrength'));
if (!isFinite(_windStrength)) { _windStrength = 0; }
var VISUAL_MAX = 300; var ratio = _windStrength / VISUAL_MAX;
ratio = Math.max(0, Math.min(1, ratio));
feature.values_['HINT'] = '역류·재순환 : 기준풍 대비 ' + (ratio * 100).toFixed(0) + '%';
var _style = new ol.style.Style({ image: new ol.style.Icon({ src: './image/rotation.png' }) });
return _style; } });
if (this.map_) { var layers = this.map_.getLayers(); var layerCollection = layers.getArray(); var layerIndex = layerCollection.indexOf(this.layer_);
if (layerIndex >= 0) { layers.insertAt(layerIndex + 1, this.resultLayer_); layers.insertAt(layerIndex + 2, this.vortexLayer_); } }
this.layer_.on('change:visible', function () { var visible = this.layer_.getVisible();
if (!visible) { this.clear(); return; }
this.resultLayer_.setVisible(false); this.vortexLayer_.setVisible(false); });
ol.WindPathAnalyzer.prototype.clear = function() { this.NetworkLink_Animation = 0;
clearInterval(this.NetworkLink_AnimationTimer);
this.NetworkLink_AnimationTimer = null;
this.resultSource_.clear(); this.vortexSource_.clear();
this.resultLayer_.setVisible(false); this.vortexLayer_.setVisible(false); };
ol.WindPathAnalyzer.prototype.analyze = function(options) { var self = this;
this.setOptions(options);
if (!this.map_) { return; }
if (!this.layer_) { return; }
this.clear();
this.resultLayer_.setVisible(true); this.vortexLayer_.setVisible(true);
var size = this.map_.getSize();
if (!size || size[0] <= 0 || size[1] <= 0) { return; }
var extent = this.map_.getView().calculateExtent(size);
this.frame_ = this.createFrame_(extent); this.domain_ = this.createDomain_();
var buildings = this.loadBuildings_();
this.buildGrid_(buildings);
var direction = this.getDirectionVector_();
var flow = this.solveFlow_(buildings, direction);
var lines = this.traceStreamlines_(flow, direction);
for (var i = 0; i < lines.length; i++) { var coords = [];
for (var j = 0; j < lines[i].pts.length; j++) { coords.push(this.toMap_(lines[i].pts[j])); }
this.resultSource_.addFeature(new ol.Feature({ geometry: new ol.geom.LineString(coords), pathIndex: i, windStrength: lines[i].speed * 100, windHeight: this.windHeight_, direction: this.direction_ })); }
self.NetworkLink_Animation = 1.0;
this.NetworkLink_AnimationTimer = setInterval(function() { self.NetworkLink_Animation += 0.5;
if (self.NetworkLink_Animation >= 10) { self.NetworkLink_Animation = 0; }
self.resultSource_.dispatchEvent('change'); }, 100);
var vortices = this.findVortices_(flow, direction);
for (var v = 0; v < vortices.length; v++) { this.vortexSource_.addFeature(new ol.Feature({ geometry: new ol.geom.Point( this.toMap_([vortices[v].x, vortices[v].y]) ), type: 'vortex', windStrength: vortices[v].strength * 100, area: vortices[v].area })); }
this.grid_ = null; this.frame_ = null; this.domain_ = null;
this.map_.render(); };
나머지 소스가 길어 넣지 못함 ㅠㅠ |