first commit

This commit is contained in:
Senad Uka
2017-11-07 09:23:57 +01:00
commit 0eee92660a
356 changed files with 747259 additions and 0 deletions

View File

@@ -0,0 +1,206 @@
import '../../../lib/easeljs.js';
import $ from "jquery";
import {Panel} from './panel';
import Colors from "./colors";
class ArrayVisualization {
constructor(panelData, isDualTilt, subarrayDisplay, buildings) {
this.panelData = panelData;
this.isDualTilt = isDualTilt;
this.subarrayDisplay = subarrayDisplay;
this.buildings = buildings;
this.scale = 10;
}
init() {
this.stage = new createjs.Stage("arrayCanvas");
this.container = new createjs.Container();
let background = new createjs.Shape();
background.graphics.beginFill(Colors.canvas_background).drawRect(0, 0, 850, 850);
this.stage.addChild(background);
this.stage.mouseMoveOutside = true;
this.adjustScale(this.buildings);
this.drawArray(this.container, this.panelData, this.scale);
this.container.x = 0;
this.container.y = 0;
this.stage.addChild(this.container);
this.drawBuildings(this.buildings,this.scale);
this.stage.update();
var lastMove = undefined;
var self = this;
// Panning
this.stage.on("pressmove", function (event) {
let x = event.stageX;
let y = event.stageY;
if (lastMove != undefined) {
let deltaX = x - lastMove.x;
let deltaY = y - lastMove.y;
self.container.x += deltaX;
self.container.y += deltaY;
self.stage.update();
}
lastMove = {x: x, y: y};
});
this.stage.on("pressup", function () {
lastMove = undefined;
});
}
adjustScale(buildings) {
if (!buildings || buildings.length === 0) return; // leave scale as default
// we cannot determine canvas size
// we are in a test or in a very impossible state
// so we better not touch anything
if(!this.stage.canvas) return;
let all_x = ([].concat(...buildings)).map( (building) => building.x * this.scale );
let all_y = ([].concat(...buildings)).map( (building) => building.y * this.scale );
let max_x = Math.max(...all_x);
let max_y = Math.max(...all_y);
let ratio_y = this.stage.canvas.height * 1.0 / max_y;
let ratio_x = this.stage.canvas.width * 1.0 / max_x;
const MARGIN = 0.05;
this.scale = this.scale * Math.min(ratio_y, ratio_x) * (1 - MARGIN);
}
drawBuildings(buildings, scale) {
if (!buildings) {
console.log("No Buildings!");
return;
}
if (!scale) {
console.log("No Scale - don't know how big the buildings should be!");
return;
}
let line = new createjs.Shape();
let color = createjs.Graphics.getRGB(0x010101, 1);
line.graphics.setStrokeStyle(3);
for (let i = 0; i < buildings.length; i++) {
let building = buildings[i];
let firstPoint = building[0];
let nextPoint = null;
line.graphics.beginStroke(color);
line.graphics.moveTo(firstPoint.x * scale, firstPoint.y * scale);
for (let j = 1; j < building.length; j++ ) {
nextPoint = building[j];
line.graphics.lineTo(nextPoint.x * scale ,nextPoint.y * scale);
line.graphics.moveTo(nextPoint.x * scale,nextPoint.y * scale);
}
line.graphics.lineTo(firstPoint.x * scale, firstPoint.y * scale );
line.graphics.endStroke();
}
this.container.addChild(line);
}
refreshPanels(panelData) {
this.panelData = panelData;
for (let i = 0; i < this.panels.length; i++) {
this.container.removeChild(this.panels[i]);
}
this.drawArray(this.container, this.panelData, this.scale);
let selectedPanel = this.selectedPanel;
this.selectedPanel = undefined;
this.selectPanel(selectedPanel);
this.setOverlay(this.overlay);
this.subarrayDisplay.didModifyPanels(panelData);
this.stage.update();
}
drawArray(container, panels) {
this.panels = [];
let treatCoordinatesAsCenterpoints = this.buildings && this.buildings.length > 0;
for (let i = 0; i < panels.length; i++) {
let panel = panels[i];
let box = new Panel(panel, this.isDualTilt, this.scale, treatCoordinatesAsCenterpoints);
container.addChild(box);
this.panels.push(box);
let self = this;
box.on("click", function () {
self.selectPanel(i);
});
}
}
selectPanel(panelIndex) {
let panel = this.panels[panelIndex];
if (this.selectedPanel !== undefined) {
let previousPanel = this.panels[this.selectedPanel];
previousPanel.deselect();
}
if (this.selectedPanel === panelIndex) {
this.selectedPanel = undefined;
} else {
this.selectedPanel = panelIndex;
panel.select();
}
this.stage.update();
}
setZoom(zoomLevel) {
this.container.scaleX = zoomLevel;
this.container.scaleY = zoomLevel;
this.stage.update();
}
setOverlay(overlay) {
this.overlay = overlay;
this.panels.forEach((panel) => {
panel.setOverlay(overlay);
});
this.stage.update();
}
addSeismicAnchor() {
if (this.selectedPanel !== undefined) {
this.panelData[this.selectedPanel].data.seismic_anchors++;
this.panels[this.selectedPanel].redrawOverlays();
this.stage.update();
this.subarrayDisplay.didModifyPanels(this.panelData);
}
}
removeSeismicAnchor() {
if (this.selectedPanel !== undefined) {
let seismicAnchors = this.panelData[this.selectedPanel].data.seismic_anchors;
if (seismicAnchors > 0) {
this.panelData[this.selectedPanel].data.seismic_anchors--;
this.panels[this.selectedPanel].redrawOverlays();
this.stage.update();
this.subarrayDisplay.didModifyPanels(this.panelData);
}
}
}
}
export default ArrayVisualization;

View File

@@ -0,0 +1,23 @@
let AutoUpload = () => {
$("#file_upload").change((e) => {
var ten_megabyte_max_upload = 10000000;
$("#error_container_txt").empty();
if(e.currentTarget.files[0].size < ten_megabyte_max_upload){
e.currentTarget.form.submit();
}else{
$("#error_container_txt").append('<span class="error_message centered_error" id="error_message_txt">The system configuration you have uploaded is too large. Try splitting your design into two separate text files and run the tool twice.</span>');
}
});
$("#dxf_upload").change((e) => {
var ten_megabyte_max_upload = 10000000;
$("#error_container_dxf").empty();
if(e.currentTarget.files[0].size < ten_megabyte_max_upload){
e.currentTarget.form.submit();
}else{
$("#error_container_dxf").append('<span class="error_message centered_error" id="error_message_dxf">The system configuration you have uploaded is too large. Try splitting your design into two separate text files and run the tool twice.</span>');
}
});
};
export default AutoUpload;

View File

@@ -0,0 +1,13 @@
let Colors = {
canvas_background: '#F9F9F9',
seismic_background: '#F1E8A2',
wind_background: '#B8F3E5',
default_background: '#133256',
selected_background: 'white',
light_text: 'white',
dark_text: '#6490BA',
border: '#537DAA'
};
export default Colors

View File

@@ -0,0 +1,20 @@
"use strict";
import ArrayVisualization from './array_visualization';
import ZoomControl from './zoom_control';
import OverlayControl from './overlay_control';
import SeismicControl from './seismic_control';
import SubarrayDisplay from './subarray_display';
import AutoUpload from './auto_upload';
$(document).ready(function () {
AutoUpload();
let subarrayDisplay = new SubarrayDisplay();
subarrayDisplay.init($('#current_anchors'), $('#needed_anchors'), $('#subarray_weight'), panel_data);
let arrayVisualization = new ArrayVisualization(panel_data, is_dual_tilt, subarrayDisplay, buildings_coordinates);
arrayVisualization.init();
new ZoomControl(arrayVisualization).init($('#zoom_control'));
new OverlayControl(arrayVisualization).init($('#overlay_control'), $('#legend_container'));
new SeismicControl(arrayVisualization, subarrayDisplay).init($('.seismic_anchor_control'), $("#seismic_save"));
window.arrayVisualization = arrayVisualization;
});

View File

@@ -0,0 +1,43 @@
import $ from "jquery";
class OverlayControl {
constructor(arrayVisualization) {
this.visualization = arrayVisualization;
}
init(overlaySelector, legendSelector) {
let self = this;
this.setOverlay("ANCHOR", overlaySelector, legendSelector);
overlaySelector.find("#anchor_overlay").click(function () {
self.setOverlay("ANCHOR", overlaySelector, legendSelector);
});
overlaySelector.find("#all_overlay").click(function () {
self.setOverlay("ALL", overlaySelector, legendSelector);
});
}
setOverlay(overlay, overlaySelector, legendSelector) {
let selectedButton;
let selectedLegend;
if (overlay == "ANCHOR") {
selectedButton = overlaySelector.find("#anchor_overlay");
selectedLegend = legendSelector.find("img.anchors_mode");
} else if (overlay == "ALL") {
selectedButton = overlaySelector.find("#all_overlay");
selectedLegend = legendSelector.find("img.all_mode");
}
this.visualization.setOverlay(overlay);
overlaySelector.find('.overlay_toggle').removeClass("overlay_active");
selectedButton.addClass("overlay_active");
legendSelector.find('.legend').hide();
selectedLegend.show();
}
}
export default OverlayControl;

View File

@@ -0,0 +1,169 @@
import "../../../lib/easeljs.js";
import Colors from "./colors";
import $ from "jquery";
function Panel(panel, isDualTilt, scale = 10, treatCoordinatesAsCenterpoints = true) {
this.Container_constructor();
this.panel = panel;
this.isDualTilt = isDualTilt;
this.textOverlays = {};
this.selected = false;
this.scale = scale;
this.treatCoordinatesAsCenterpoints = treatCoordinatesAsCenterpoints;
this.setup();
}
const panelMethods = {
setup() {
if (this.treatCoordinatesAsCenterpoints) {
this.x = (this.panel.x - (this.panel.width / 2.0)) * this.scale;
this.y = (this.panel.y - (this.panel.height / 2.0)) * this.scale;
} else {
this.x = this.panel.x * this.scale;
this.y = this.panel.y * this.scale;
}
this.width = this.scale * this.panel.width;
this.height = this.scale * this.panel.height;
this.drawBackground();
},
drawBackground() {
if (this.background === undefined) {
this.background = new createjs.Shape();
} else {
this.removeChild(this.background);
}
let fillColor;
let borderColor;
let textColor;
let secondFillColor;
if (this.panel.data.seismic_anchors > 0 && this.panel.data.wind_anchors > 0) {
fillColor = Colors.seismic_background;
secondFillColor = Colors.wind_background;
textColor = Colors.dark_text;
borderColor = Colors.border;
} else if (this.panel.data.seismic_anchors > 0) {
fillColor = Colors.seismic_background;
textColor = Colors.dark_text;
borderColor = Colors.border;
} else if (this.panel.data.wind_anchors > 0) {
fillColor = Colors.wind_background;
textColor = Colors.dark_text;
borderColor = Colors.border;
} else {
fillColor = Colors.default_background;
textColor = Colors.light_text;
borderColor = fillColor;
}
if (this.selected) {
fillColor = Colors.selected_background;
textColor = Colors.dark_text;
borderColor = Colors.border;
}
this.textColor = textColor;
let width = this.width;
let height = this.height;
let borderWidth = 0.5;
// main background fill rectangle with white border
this.background.graphics.setStrokeStyle(borderWidth)
.beginStroke('white')
.beginFill(fillColor)
.drawRect(0, 0, width, height)
.endFill()
.endStroke();
// diagonal split background color for multiple anchor types
if (secondFillColor !== undefined) {
this.background.graphics.beginFill(secondFillColor)
.moveTo(borderWidth, borderWidth)
.lineTo(width - borderWidth, height - borderWidth)
.lineTo(width - borderWidth, borderWidth)
.closePath()
.endFill()
.endStroke();
}
// inner border for use with light background colors
this.background.graphics.beginStroke(borderColor)
.drawRect(borderWidth, borderWidth, width - 2 * borderWidth, height - 2 * borderWidth)
.endStroke();
// line drawing of dual-tilt indicator (the right-facing triangle)
if (this.isDualTilt) {
this.background.graphics.setStrokeStyle(0.25)
.beginStroke(Colors.border)
.moveTo(width / 2., borderWidth)
.lineTo(width / 2., height - borderWidth)
.lineTo(width - borderWidth, height / 2.)
.closePath()
.endStroke();
}
this.addChildAt(this.background, 0);
},
select() {
this.selected = true;
this.drawBackground();
this.redrawOverlays();
},
deselect() {
this.selected = false;
this.drawBackground();
this.redrawOverlays();
},
setOverlay(overlay) {
let data = this.panel.data;
let self = this;
$.each(this.textOverlays, function (idx, overlay) {
self.removeChild(overlay);
});
this.textOverlays = {};
if (overlay == "ALL") {
this.addOverlay('panel_id', data.panel_id, "2.5px", 0.3, 0.55);
this.addOverlay('wind_zones', data.wind_zones, '2.5px', 0.7, 0.55);
this.addOverlay('ballast', data.ballast, "1.5px", 0.125, 0.25);
this.addOverlay('wind_anchors', data.wind_anchors, "1.5px", 0.125, 0.8);
this.addOverlay('seismic_anchors', "S".repeat(data.seismic_anchors), "1.5px", 0.35, 0.8);
this.addOverlay('cross_trays', data.cross_trays, "1.5px", 0.6, 0.25);
this.addOverlay('link_trays', data.link_trays, "1.5px", 0.85, 0.25);
this.addOverlay('subarray', data.subarray, "1.5px", 0.6, 0.8);
this.addOverlay('psf', data.psf.toPrecision(3), "1.5px", 0.35, 0.25);
this.addOverlay('panel_type', data.panel_type, "1.5px", 0.85, 0.8);
} else if (overlay == 'ANCHOR') {
this.addOverlay('ballast', data.ballast, "2.5px", 0.3, 0.55);
this.addOverlay('anchors', data.seismic_anchors + data.wind_anchors, '2.5px', 0.7, 0.55);
}
this.currentOverlay = overlay;
},
addOverlay(name, text, fontSize, relativeX, relativeY) {
let overlay = new createjs.Text();
overlay.text = text;
overlay.font = fontSize + " sans-serif";
overlay.x = this.width * relativeX;
overlay.y = this.height * relativeY;
overlay.textAlign = "center";
overlay.textBaseline = "middle";
overlay.color = this.textColor;
overlay.maxWidth = this.width * 0.5;
this.textOverlays[name] = overlay;
this.addChild(overlay);
},
redrawOverlays() {
this.setOverlay(this.currentOverlay);
}
};
Object.assign(Panel.prototype, createjs.extend(Panel, createjs.Container));
Object.assign(Panel.prototype, panelMethods);
Panel = createjs.promote(Panel, "Container");
export {Panel};

View File

@@ -0,0 +1,73 @@
import $ from 'jquery';
class SeismicControl {
constructor(arrayVisualization, subarrayDisplay) {
this.visualization = arrayVisualization;
this.subarrayDisplay = subarrayDisplay;
}
init(seismicSelector, bannerSelector) {
let self = this;
seismicSelector.find("#add_seismic").click(function () {
self.visualization.addSeismicAnchor();
});
seismicSelector.find("#remove_seismic").click(function () {
self.visualization.removeSeismicAnchor();
});
seismicSelector.find("#save_seismic_changes").click(function () {
let updatedData = self.visualization.panelData.map((panel) => {
return {
panel_id: panel.data.panel_id,
seismic_anchors: panel.data.seismic_anchors
};
});
$.ajax({
url: "/api/update_panel_data",
data: JSON.stringify(updatedData),
contentType: "application/json; charset=utf-8",
method: 'POST'
})
.then(function (data) {
bannerSelector.removeClass("seismic_error");
bannerSelector.removeClass("seismic_success");
bannerSelector.removeClass("hidden");
let seismicClass;
let bannerText;
bannerSelector.find(".circle").removeClass("icon-ok");
bannerSelector.find(".circle").text("!");
if (data.status !== undefined && data.status == "success") {
seismicClass = "seismic_success";
bannerText = "Changes to the Seismic Anchors have been successfully saved!";
bannerSelector.find(".circle").addClass("icon-ok");
bannerSelector.find(".circle").text("");
self.visualization.refreshPanels(data.panel_data);
self.subarrayDisplay.didUpdateSubarrayData(data.subarray_data);
} else if (data.error !== undefined) {
seismicClass = "seismic_error";
bannerText = data.error;
self.subarrayDisplay.didUpdateSubarrayData(data.subarray_data);
} else {
seismicClass = "seismic_error";
bannerText = "Unknown error, please try again.";
}
bannerSelector.addClass(seismicClass);
bannerSelector.find(".seismic_save_message").text(bannerText);
});
});
bannerSelector.find(".dismiss_button").click(function () {
bannerSelector.addClass("hidden");
bannerSelector.removeClass("seismic_error");
bannerSelector.removeClass("seismic_success");
});
}
}
export default SeismicControl;

View File

@@ -0,0 +1,49 @@
class SubarrayDisplay {
init(currentSeismicCountSelector, neededAnchorSelector, weightSelector, panelData) {
this.currentSeismicCountSelector = currentSeismicCountSelector;
this.neededAnchorSelector = neededAnchorSelector;
this.weightSelector = weightSelector;
this.didModifyPanels(panelData);
}
didModifyPanels(panelData) {
let seismicCount = this.computeSeismicAnchorCounts(panelData);
this.assignSeismicCountItems(seismicCount);
}
didUpdateSubarrayData(subarrayData) {
for (let i = 0; i < subarrayData.length; i++) {
let data = subarrayData[i];
let subarray = i + 2;
let neededAnchors = data.required_seismic_anchors;
let weight = data.weight;
this.neededAnchorSelector.find('td:nth-child(' + subarray + ')').text(neededAnchors);
this.weightSelector.find('td:nth-child(' + subarray + ')').text(weight.toLocaleString());
}
}
computeSeismicAnchorCounts(panelData) {
let seismicCount = {};
for (let i = 0; i < panelData.length; i++) {
let panel = panelData[i].data;
if (seismicCount[panel.subarray] === undefined) {
seismicCount[panel.subarray] = 0;
}
seismicCount[panel.subarray] += panel.seismic_anchors;
}
return seismicCount
}
assignSeismicCountItems(seismicAnchorCounts) {
for (var subarray in seismicAnchorCounts) {
if (seismicAnchorCounts.hasOwnProperty(subarray)) {
const childId = parseInt(Object.keys(seismicAnchorCounts).indexOf(subarray)) + 2;
this.currentSeismicCountSelector.find(`td:nth-child(${childId})`).text(seismicAnchorCounts[subarray]);
}
}
}
}
export default SubarrayDisplay;

View File

@@ -0,0 +1,48 @@
import $ from "jquery";
class ZoomControl {
constructor(arrayVisualization) {
this.visualization = arrayVisualization;
this.zooms = [1, 2, 3, 4, 5, 6, 7];
this.zoomLevel = 0;
}
init(zoomSelector) {
let self = this;
zoomSelector.find("#increase_zoom").click(function () {
if (self.zoomLevel != (self.zooms.length - 1)) {
self.setZoom(self.zoomLevel + 1, zoomSelector);
}
});
zoomSelector.find("#decrease_zoom").click(function () {
if (self.zoomLevel != 0) {
self.setZoom(self.zoomLevel - 1, zoomSelector);
}
});
for (let i = 0; i < self.zooms.length; i++) {
zoomSelector.find("#zoom_indicator_" + i).click(function () {
self.setZoom(i, zoomSelector);
});
}
self.setZoom(0, zoomSelector);
}
setZoom(zoomLevel, zoomSelector) {
const oldZoom = this.zoomLevel;
const totalZooms = this.zooms.length;
this.zoomLevel = zoomLevel % totalZooms;
const zoom = this.zooms[this.zoomLevel];
const zoom_percentage = Math.round((100 / (totalZooms - 1)) * this.zoomLevel);
this.visualization.setZoom(zoom);
zoomSelector.find("#zoom_indicator_" + oldZoom).removeClass("zoom_active");
zoomSelector.find("#zoom_indicator_" + this.zoomLevel).addClass("zoom_active");
zoomSelector.find("#zoom_level").text(zoom_percentage + "%");
}
}
export default ZoomControl;