From 7daa9db4edcaf56039e1b83f3da70529c4a4ebde Mon Sep 17 00:00:00 2001 From: GotPPay Date: Sun, 24 Dec 2017 23:35:11 +0100 Subject: [PATCH 1/7] extract informations about corners --- helix/main.py | 6 +++++ helix/models/corner.py | 12 ++++++++++ helix/presenters/panel_presenter.py | 37 +++++++++++++++++++++++++++-- 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 helix/models/corner.py diff --git a/helix/main.py b/helix/main.py index 5eb8a4c..12de162 100644 --- a/helix/main.py +++ b/helix/main.py @@ -290,6 +290,7 @@ def array_summary(): calculator.subarrays, max_y) context['buildings'] = project_presenter.get_buildings(calculator.buildings_for_drawing, max_y) + context['corners'] = project_presenter.get_corners(calculator.buildings) context['override_form'] = True context['cad_file_name'] = session_manager.site.cad_file_name or 'Upload System Text Data' context['dxf_file_name'] = session_manager.site.dxf_file_name or 'Upload System DXF' @@ -297,6 +298,11 @@ def array_summary(): context['inaccurate_drawing_warning'] = 'The subarrays in this design are not parallel to each other, \ and the graphical representation on this page may not be accurate.' + print("=================") + print("CORNERS : ") + print(context['corners']) + print("=================") + except FileValidationException as error: # when calculator is about to enter infinte loop # it throws an exception - it is supplied wrong data diff --git a/helix/models/corner.py b/helix/models/corner.py new file mode 100644 index 0000000..8c55640 --- /dev/null +++ b/helix/models/corner.py @@ -0,0 +1,12 @@ + + +class Corner(object): + def __init__(self, x, y, length, angle): + self.x = x + self.y = y + self.length = length + self.angle = angle + + @property + def dictionary(self): + return {"x": self.x, "y": self.y, "length": self.length, "angle": self.angle} diff --git a/helix/presenters/panel_presenter.py b/helix/presenters/panel_presenter.py index b98b2ba..f36841e 100644 --- a/helix/presenters/panel_presenter.py +++ b/helix/presenters/panel_presenter.py @@ -1,4 +1,6 @@ import sys +from math import sqrt, atan, degrees +from helix.models.corner import Corner class ProjectPresenter(object): def __init__(self, system_type, module_type): @@ -18,8 +20,6 @@ class ProjectPresenter(object): spacing_x, spacing_y = module_constants.presenter_spacing wind_zones = system_constants.wind_zones - - for panel in panels: subarray = [x for x in subarrays if x.subarray_number == panel.subarray][0] origin = subarray.origin @@ -73,6 +73,39 @@ class ProjectPresenter(object): return result + def get_corners(self, buildings): + result = [] + for building in buildings: + presentable_building = [] + result.append(presentable_building) + previous_corner = building[-1] + for i, corner in enumerate(building): + if (i+1 == len(building)): + next_corner = building[0] + else: + next_corner = building[i+1] + + corner_length = sqrt((next_corner[0] - corner[0])**2 + (next_corner[1] - corner[1])**2) + k1 = (corner[1] - previous_corner[1]) / (corner[0] - previous_corner[0]) + k2 = (next_corner[1] - corner[1]) / (next_corner[0] - corner[0]) + theta1 = degrees(atan(k1)) + theta2 = degrees(atan(k2)) + theta1 = theta1 - theta2 + if (theta1 < 0): + if (k1 < 0 and k2 < 0): + theta1 = 360 + theta1 + elif (k1 < 0 and k2 > 0): + theta1 = 180 + theta1 + else: + if (k1 > 0 and k2 > 0): + theta1 = 180 + theta1 + + corner_angle = theta1 + presentable_building.append(Corner(corner[0], corner[1], corner_length, corner_angle).__dict__) + previous_corner = corner + + return result + def get_max_y(self,buildings, panels): module_constants = self.system_type.module_constants(self.module_type) From cc490fbc6aa49591ef20d1ce1f61033f98094bb3 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Sun, 24 Dec 2017 23:42:06 +0100 Subject: [PATCH 2/7] extract informations about corners --- helix/presenters/panel_presenter.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/helix/presenters/panel_presenter.py b/helix/presenters/panel_presenter.py index f36841e..7cee812 100644 --- a/helix/presenters/panel_presenter.py +++ b/helix/presenters/panel_presenter.py @@ -88,9 +88,8 @@ class ProjectPresenter(object): corner_length = sqrt((next_corner[0] - corner[0])**2 + (next_corner[1] - corner[1])**2) k1 = (corner[1] - previous_corner[1]) / (corner[0] - previous_corner[0]) k2 = (next_corner[1] - corner[1]) / (next_corner[0] - corner[0]) - theta1 = degrees(atan(k1)) theta2 = degrees(atan(k2)) - theta1 = theta1 - theta2 + theta1 = degrees(atan(k1)) - theta2 if (theta1 < 0): if (k1 < 0 and k2 < 0): theta1 = 360 + theta1 From ef186a3754314bc322334394f79f023a13cb7cb9 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Mon, 25 Dec 2017 10:39:02 +0100 Subject: [PATCH 3/7] added length in cw direction --- helix/models/corner.py | 7 ++++--- helix/presenters/panel_presenter.py | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/helix/models/corner.py b/helix/models/corner.py index 8c55640..24e474f 100644 --- a/helix/models/corner.py +++ b/helix/models/corner.py @@ -1,12 +1,13 @@ class Corner(object): - def __init__(self, x, y, length, angle): + def __init__(self, x, y, length_ccw, length_cw, angle): self.x = x self.y = y - self.length = length + self.length_ccw = length_ccw + self.length_cw = length_cw self.angle = angle @property def dictionary(self): - return {"x": self.x, "y": self.y, "length": self.length, "angle": self.angle} + return {"x": self.x, "y": self.y, "length ccw": self.length_ccw, "length cw : ": self.length_cw, "angle": self.angle} diff --git a/helix/presenters/panel_presenter.py b/helix/presenters/panel_presenter.py index 7cee812..81720f0 100644 --- a/helix/presenters/panel_presenter.py +++ b/helix/presenters/panel_presenter.py @@ -85,7 +85,8 @@ class ProjectPresenter(object): else: next_corner = building[i+1] - corner_length = sqrt((next_corner[0] - corner[0])**2 + (next_corner[1] - corner[1])**2) + corner_length_ccw = sqrt((next_corner[0] - corner[0])**2 + (next_corner[1] - corner[1])**2) + corner_length_cw = sqrt((previous_corner[0] - corner[0])**2 + (previous_corner[1] - corner[1])**2) k1 = (corner[1] - previous_corner[1]) / (corner[0] - previous_corner[0]) k2 = (next_corner[1] - corner[1]) / (next_corner[0] - corner[0]) theta2 = degrees(atan(k2)) @@ -100,7 +101,7 @@ class ProjectPresenter(object): theta1 = 180 + theta1 corner_angle = theta1 - presentable_building.append(Corner(corner[0], corner[1], corner_length, corner_angle).__dict__) + presentable_building.append(Corner(corner[0], corner[1], corner_length_ccw,corner_length_cw, corner_angle).__dict__) previous_corner = corner return result From 7e7b7f64673a3abfab97df02ba53d06ae0594e50 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Mon, 25 Dec 2017 18:39:57 +0100 Subject: [PATCH 4/7] remove angles wider than 135 degrees --- helix/presenters/panel_presenter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/helix/presenters/panel_presenter.py b/helix/presenters/panel_presenter.py index 81720f0..3ea41a5 100644 --- a/helix/presenters/panel_presenter.py +++ b/helix/presenters/panel_presenter.py @@ -100,8 +100,8 @@ class ProjectPresenter(object): if (k1 > 0 and k2 > 0): theta1 = 180 + theta1 - corner_angle = theta1 - presentable_building.append(Corner(corner[0], corner[1], corner_length_ccw,corner_length_cw, corner_angle).__dict__) + if (theta1 < 135): + presentable_building.append(Corner(corner[0], corner[1], corner_length_ccw,corner_length_cw, theta1).__dict__) previous_corner = corner return result From 85dc45a32611b7d3e641d83bfb0cad7d27a73437 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Mon, 25 Dec 2017 18:44:18 +0100 Subject: [PATCH 5/7] remove corners wider than 135 degrees --- helix/presenters/panel_presenter.py | 1 + 1 file changed, 1 insertion(+) diff --git a/helix/presenters/panel_presenter.py b/helix/presenters/panel_presenter.py index 3ea41a5..d14e5be 100644 --- a/helix/presenters/panel_presenter.py +++ b/helix/presenters/panel_presenter.py @@ -103,6 +103,7 @@ class ProjectPresenter(object): if (theta1 < 135): presentable_building.append(Corner(corner[0], corner[1], corner_length_ccw,corner_length_cw, theta1).__dict__) previous_corner = corner + return result From b71eb244af8c489dac9f5cb3acbae9124a04d579 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Mon, 25 Dec 2017 22:24:24 +0100 Subject: [PATCH 6/7] angle calculation fix ; created tests --- helix/presenters/panel_presenter.py | 12 ++++-- test/helpers/panel_presenter_test.py | 60 ++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/helix/presenters/panel_presenter.py b/helix/presenters/panel_presenter.py index d14e5be..cb493ad 100644 --- a/helix/presenters/panel_presenter.py +++ b/helix/presenters/panel_presenter.py @@ -87,14 +87,17 @@ class ProjectPresenter(object): corner_length_ccw = sqrt((next_corner[0] - corner[0])**2 + (next_corner[1] - corner[1])**2) corner_length_cw = sqrt((previous_corner[0] - corner[0])**2 + (previous_corner[1] - corner[1])**2) - k1 = (corner[1] - previous_corner[1]) / (corner[0] - previous_corner[0]) - k2 = (next_corner[1] - corner[1]) / (next_corner[0] - corner[0]) + + k1 = float('Inf') if (corner[0]==previous_corner[0]) else (corner[1] - previous_corner[1]) / (corner[0] - previous_corner[0]) + k2 = float('Inf') if (corner[0]==next_corner[0]) else (next_corner[1] - corner[1]) / (next_corner[0] - corner[0]) + theta2 = degrees(atan(k2)) theta1 = degrees(atan(k1)) - theta2 + if (theta1 < 0): if (k1 < 0 and k2 < 0): theta1 = 360 + theta1 - elif (k1 < 0 and k2 > 0): + elif (k1 <= 0 and k2 >= 0): theta1 = 180 + theta1 else: if (k1 > 0 and k2 > 0): @@ -102,8 +105,9 @@ class ProjectPresenter(object): if (theta1 < 135): presentable_building.append(Corner(corner[0], corner[1], corner_length_ccw,corner_length_cw, theta1).__dict__) + previous_corner = corner - + return result diff --git a/test/helpers/panel_presenter_test.py b/test/helpers/panel_presenter_test.py index fe565df..3561f68 100644 --- a/test/helpers/panel_presenter_test.py +++ b/test/helpers/panel_presenter_test.py @@ -76,6 +76,66 @@ class PanelPresenterTest(unittest.TestCase): actual_buildings = self.subject.get_buildings(buildings,60) assert_array_equal(actual_buildings,expected_buildings) + def test_get_corners_box_building(self): + self.subject = ProjectPresenter(SystemType.singleTilt, ModuleType.Cell96) + buildings = [ [ [0, 0], [60, 0], [60,60], [0, 60] ] ] # big square + expected_corners = [[ + {'x': 0, 'y': 0, 'length_cw': 60, 'length_ccw':60, 'angle':90}, + {'x': 60, 'y': 0, 'length_cw': 60, 'length_ccw':60, 'angle':90}, + {'x': 60, 'y': 60, 'length_cw': 60, 'length_ccw':60, 'angle':90}, + {'x': 0, 'y': 60, 'length_cw': 60, 'length_ccw':60, 'angle':90} + ]] + actual_corners = self.subject.get_corners(buildings) + assert_array_equal(actual_corners,expected_corners) + + def test_get_corners_box_building_rotated_30_degrees(self): + self.subject = ProjectPresenter(SystemType.singleTilt, ModuleType.Cell96) + buildings = [ [ [0, 0], [51.96, 30], [21.96, 81.96], [-30, 51.96] ] ] # big square + expected_corners = [[ + {'x': 0, 'y': 0, 'length_cw': 59.99867998547968, 'length_ccw':59.99867998547968, 'angle':90}, + {'x': 51.96, 'y': 30, 'length_cw': 59.99867998547968, 'length_ccw':59.998679985479676, 'angle':90}, + {'x': 21.96, 'y': 81.96, 'length_cw': 59.998679985479676, 'length_ccw':59.998679985479676, 'angle':90}, + {'x': -30, 'y': 51.96, 'length_cw': 59.998679985479676, 'length_ccw':59.99867998547968, 'angle':90} + ]] + actual_corners = self.subject.get_corners(buildings) + assert_array_equal(actual_corners,expected_corners) + + def test_get_corners_box_building_rotated_90_degrees(self): + self.subject = ProjectPresenter(SystemType.singleTilt, ModuleType.Cell96) + buildings = [ [ [0, 0], [0, 60], [-60,60], [-60, 0] ] ] # big square + expected_corners = [[ + {'x': 0, 'y': 0, 'length_cw': 60, 'length_ccw':60, 'angle':90}, + {'x': 0, 'y': 60, 'length_cw': 60, 'length_ccw':60, 'angle':90}, + {'x': -60, 'y': 60, 'length_cw': 60, 'length_ccw':60, 'angle':90}, + {'x': -60, 'y': 0, 'length_cw': 60, 'length_ccw':60, 'angle':90} + ]] + actual_corners = self.subject.get_corners(buildings) + assert_array_equal(actual_corners,expected_corners) + + def test_get_corners_box_building_rotated_180_degrees(self): + self.subject = ProjectPresenter(SystemType.singleTilt, ModuleType.Cell96) + buildings = [ [ [0, 0], [-60, 0], [-60,-60], [0, -60] ] ] # big square + expected_corners = [[ + {'x': 0, 'y': 0, 'length_cw': 60, 'length_ccw':60, 'angle':90}, + {'x': -60, 'y': 0, 'length_cw': 60, 'length_ccw':60, 'angle':90}, + {'x': -60, 'y': -60, 'length_cw': 60, 'length_ccw':60, 'angle':90}, + {'x': 0, 'y': -60, 'length_cw': 60, 'length_ccw':60, 'angle':90} + ]] + actual_corners = self.subject.get_corners(buildings) + assert_array_equal(actual_corners,expected_corners) + + def test_get_corners_box_building_rotated_270_degrees(self): + self.subject = ProjectPresenter(SystemType.singleTilt, ModuleType.Cell96) + buildings = [ [ [0, 0], [0, -60], [60,-60], [60, 0] ] ] # big square + expected_corners = [[ + {'x': 0, 'y': 0, 'length_cw': 60, 'length_ccw':60, 'angle':90}, + {'x': 0, 'y': -60, 'length_cw': 60, 'length_ccw':60, 'angle':90}, + {'x': 60, 'y': -60, 'length_cw': 60, 'length_ccw':60, 'angle':90}, + {'x': 60, 'y': 0, 'length_cw': 60, 'length_ccw':60, 'angle':90} + ]] + actual_corners = self.subject.get_corners(buildings) + assert_array_equal(actual_corners,expected_corners) + def test_get_max_y(self): self.subject = ProjectPresenter(SystemType.singleTilt, ModuleType.Cell96) panels = [ From 627e31ef37ac32a1b831122e0ade0175cdf83df7 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Tue, 26 Dec 2017 20:58:00 +0100 Subject: [PATCH 7/7] print to browser console ; remove magic numbers ; improve tests --- helix/constants/global_constants.py | 2 ++ helix/main.py | 5 --- helix/presenters/panel_presenter.py | 6 ++-- helix/templates/array_summary.html.jinja | 10 ++++++ test/helpers/panel_presenter_test.py | 40 +++++++++--------------- 5 files changed, 31 insertions(+), 32 deletions(-) diff --git a/helix/constants/global_constants.py b/helix/constants/global_constants.py index 9d457e1..1476765 100644 --- a/helix/constants/global_constants.py +++ b/helix/constants/global_constants.py @@ -7,3 +7,5 @@ parapet_coefficients = 0.88, 1.2 system_force_capacity = 418. minimum_racking_capacity = 226 + +max_corner_angle = 135 \ No newline at end of file diff --git a/helix/main.py b/helix/main.py index 12de162..625e5b3 100644 --- a/helix/main.py +++ b/helix/main.py @@ -298,11 +298,6 @@ def array_summary(): context['inaccurate_drawing_warning'] = 'The subarrays in this design are not parallel to each other, \ and the graphical representation on this page may not be accurate.' - print("=================") - print("CORNERS : ") - print(context['corners']) - print("=================") - except FileValidationException as error: # when calculator is about to enter infinte loop # it throws an exception - it is supplied wrong data diff --git a/helix/presenters/panel_presenter.py b/helix/presenters/panel_presenter.py index cb493ad..52a583f 100644 --- a/helix/presenters/panel_presenter.py +++ b/helix/presenters/panel_presenter.py @@ -1,6 +1,7 @@ import sys from math import sqrt, atan, degrees from helix.models.corner import Corner +from helix.constants.global_constants import max_corner_angle class ProjectPresenter(object): def __init__(self, system_type, module_type): @@ -85,6 +86,8 @@ class ProjectPresenter(object): else: next_corner = building[i+1] + #x coordinate is stored as first element of corner variable + #y coordinate is stored as second element of corner variable corner_length_ccw = sqrt((next_corner[0] - corner[0])**2 + (next_corner[1] - corner[1])**2) corner_length_cw = sqrt((previous_corner[0] - corner[0])**2 + (previous_corner[1] - corner[1])**2) @@ -103,12 +106,11 @@ class ProjectPresenter(object): if (k1 > 0 and k2 > 0): theta1 = 180 + theta1 - if (theta1 < 135): + if (theta1 < max_corner_angle): presentable_building.append(Corner(corner[0], corner[1], corner_length_ccw,corner_length_cw, theta1).__dict__) previous_corner = corner - return result def get_max_y(self,buildings, panels): diff --git a/helix/templates/array_summary.html.jinja b/helix/templates/array_summary.html.jinja index 7e9147a..bb1f041 100644 --- a/helix/templates/array_summary.html.jinja +++ b/helix/templates/array_summary.html.jinja @@ -1,6 +1,16 @@ {% extends "layout.html.jinja" %} {% set title = "Helix Calculator" %} {% block contents %} + + diff --git a/test/helpers/panel_presenter_test.py b/test/helpers/panel_presenter_test.py index 3561f68..10e281d 100644 --- a/test/helpers/panel_presenter_test.py +++ b/test/helpers/panel_presenter_test.py @@ -100,40 +100,30 @@ class PanelPresenterTest(unittest.TestCase): actual_corners = self.subject.get_corners(buildings) assert_array_equal(actual_corners,expected_corners) - def test_get_corners_box_building_rotated_90_degrees(self): + def test_get_corners_building(self): self.subject = ProjectPresenter(SystemType.singleTilt, ModuleType.Cell96) - buildings = [ [ [0, 0], [0, 60], [-60,60], [-60, 0] ] ] # big square + buildings = [ [ [-3.42, 1.51], [-1.66, -1.64], [4.22, -0.87], [-0.8, 5.64]] ] expected_corners = [[ - {'x': 0, 'y': 0, 'length_cw': 60, 'length_ccw':60, 'angle':90}, - {'x': 0, 'y': 60, 'length_cw': 60, 'length_ccw':60, 'angle':90}, - {'x': -60, 'y': 60, 'length_cw': 60, 'length_ccw':60, 'angle':90}, - {'x': -60, 'y': 0, 'length_cw': 60, 'length_ccw':60, 'angle':90} + {'x': -3.42, 'y': 1.51, 'length_cw': 4.890940604832571, 'length_ccw':3.6083375673570233, 'angle':118.41626123074676}, + {'x': -1.66, 'y': -1.64, 'length_cw': 3.6083375673570233, 'length_ccw':5.930202357424239, 'angle':111.73284308914215}, + {'x': 4.22, 'y': -0.87, 'length_cw': 5.930202357424239, 'length_ccw':8.22073597678456, 'angle':59.823982400990424}, + {'x': -0.8, 'y': 5.64, 'length_cw': 8.22073597678456, 'length_ccw':4.890940604832571, 'angle':70.02691327912069} ]] actual_corners = self.subject.get_corners(buildings) assert_array_equal(actual_corners,expected_corners) - - def test_get_corners_box_building_rotated_180_degrees(self): + + def test_get_corners_wild_building_with_big_angles(self): self.subject = ProjectPresenter(SystemType.singleTilt, ModuleType.Cell96) - buildings = [ [ [0, 0], [-60, 0], [-60,-60], [0, -60] ] ] # big square + buildings = [ [ [-3.58, 3.32], [-0.78, -2.9], [-1.56,0.88], [0.66, -2.16], [1.5, 1.16], [2.72, 2.36], [-0.8, 5.64] ] ] expected_corners = [[ - {'x': 0, 'y': 0, 'length_cw': 60, 'length_ccw':60, 'angle':90}, - {'x': -60, 'y': 0, 'length_cw': 60, 'length_ccw':60, 'angle':90}, - {'x': -60, 'y': -60, 'length_cw': 60, 'length_ccw':60, 'angle':90}, - {'x': 0, 'y': -60, 'length_cw': 60, 'length_ccw':60, 'angle':90} - ]] - actual_corners = self.subject.get_corners(buildings) - assert_array_equal(actual_corners,expected_corners) - - def test_get_corners_box_building_rotated_270_degrees(self): - self.subject = ProjectPresenter(SystemType.singleTilt, ModuleType.Cell96) - buildings = [ [ [0, 0], [0, -60], [60,-60], [60, 0] ] ] # big square - expected_corners = [[ - {'x': 0, 'y': 0, 'length_cw': 60, 'length_ccw':60, 'angle':90}, - {'x': 0, 'y': -60, 'length_cw': 60, 'length_ccw':60, 'angle':90}, - {'x': 60, 'y': -60, 'length_cw': 60, 'length_ccw':60, 'angle':90}, - {'x': 60, 'y': 0, 'length_cw': 60, 'length_ccw':60, 'angle':90} + {'x': -3.58, 'y': 3.32, 'length_cw': 3.6208838699963852, 'length_ccw':6.821172919667115, 'angle':105.6106862572924}, + {'x': -0.78, 'y': -2.9, 'length_cw': 6.821172919667115, 'length_ccw':3.8596372886580936, 'angle':12.576112527956795}, + {'x': 0.66, 'y': -2.16, 'length_cw': 3.7643060449437424, 'length_ccw':3.424616766880639, 'angle':50.33783308603299}, + {'x': 2.72, 'y': 2.36, 'length_cw': 1.7112568480505783, 'length_ccw':4.811319985201567, 'angle':87.50512700090906}, + {'x': -0.8, 'y': 5.64, 'length_cw': 4.811319985201567, 'length_ccw':3.6208838699963852, 'angle':97.17527350158382} ]] actual_corners = self.subject.get_corners(buildings) + print(actual_corners) assert_array_equal(actual_corners,expected_corners) def test_get_max_y(self):