diff --git a/helix/presenters/panel_presenter.py b/helix/presenters/panel_presenter.py index 22ecae0..b0ca095 100644 --- a/helix/presenters/panel_presenter.py +++ b/helix/presenters/panel_presenter.py @@ -1,5 +1,5 @@ import sys -from math import sqrt, atan, degrees +from math import sqrt, degrees, acos from helix.models.corner import Corner from helix.constants.global_constants import max_corner_angle @@ -75,41 +75,43 @@ class ProjectPresenter(object): return result def get_corners(self, buildings): + + def angle(x1, y1, x2, y2): + # Use dotproduct to find angle between vectors + # This always returns an angle between 0, pi + numer = (x1 * x2 + y1 * y2) + denom = sqrt((x1 ** 2 + y1 ** 2) * (x2 ** 2 + y2 ** 2)) + return acos(numer / denom) + + + def cross_sign(x1, y1, x2, y2): + # True if cross is positive + # False if negative or zero + return x1 * y2 > x2 * y1 + + + 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] - - #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) - - 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]) + + for i in range(len(building)): + p1 = building[i] + ref = building[i - 1] + p2 = building[i - 2] + x1, y1 = p1[0] - ref[0], p1[1] - ref[1] + x2, y2 = p2[0] - ref[0], p2[1] - ref[1] - theta2 = degrees(atan(k2)) - theta1 = degrees(atan(k1)) - theta2 + corner_length_cw = sqrt(x2**2 + y2**2) + corner_length_ccw = sqrt(x1**2 + y1**2) + theta = degrees(angle(x1, y1, x2, y2)) - 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 - - if (theta1 < max_corner_angle): - presentable_building.append(Corner(corner[0], corner[1], corner_length_ccw,corner_length_cw, theta1).__dict__) - - previous_corner = corner + #print('Points', p1, ref, p2) + #print('Angle', theta) + if (cross_sign(x1, y1, x2, y2)) and (theta < max_corner_angle) : + #print('Inner Angle') + presentable_building.append(Corner(ref[0], ref[1], corner_length_ccw,corner_length_cw, theta).__dict__) return result diff --git a/test/helpers/panel_presenter_test.py b/test/helpers/panel_presenter_test.py index 10e281d..b9860cb 100644 --- a/test/helpers/panel_presenter_test.py +++ b/test/helpers/panel_presenter_test.py @@ -76,14 +76,27 @@ class PanelPresenterTest(unittest.TestCase): actual_buildings = self.subject.get_buildings(buildings,60) assert_array_equal(actual_buildings,expected_buildings) + def test_get_corners_fancy_building(self): + self.subject = ProjectPresenter(SystemType.singleTilt, ModuleType.Cell96) + buildings = [ [ [2, 5], [2, 3], [0,3], [0, 0], [2,0], [2,-3], [6,-3], [8,-1], [8,1], [6,3], [4,3], [4,5] ] ] # fancy builgin with three interior corners + expected_corners = [[ + {'length_ccw': 2.0, 'angle': 90.0, 'y': 5, 'x': 4, 'length_cw': 2.0}, + {'length_ccw': 2.0, 'angle': 90.0, 'y': 5, 'x': 2, 'length_cw': 2.0}, + {'length_ccw': 3.0, 'angle': 90.0, 'y': 3, 'x': 0, 'length_cw': 2.0}, + {'length_ccw': 2.0, 'angle': 90.0, 'y': 0, 'x': 0, 'length_cw': 3.0}, + {'length_ccw': 4.0, 'angle': 90.0, 'y': -3, 'x': 2, 'length_cw': 3.0}]] + actual_corners = self.subject.get_corners(buildings) + assert_array_equal(actual_corners,expected_corners) + + 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': 60, 'length_cw': 60, 'length_ccw':60, 'angle':90}, {'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} + {'x': 60, 'y': 60, 'length_cw': 60, 'length_ccw':60, 'angle':90} ]] actual_corners = self.subject.get_corners(buildings) assert_array_equal(actual_corners,expected_corners) @@ -92,10 +105,10 @@ class PanelPresenterTest(unittest.TestCase): 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': -30, 'y': 51.96, 'length_cw': 59.998679985479676, 'length_ccw':59.99867998547968, 'angle':90}, {'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} + {'x': 21.96, 'y': 81.96, 'length_cw': 59.998679985479676, 'length_ccw':59.998679985479676, 'angle':90.00000000000001} ]] actual_corners = self.subject.get_corners(buildings) assert_array_equal(actual_corners,expected_corners) @@ -104,10 +117,10 @@ class PanelPresenterTest(unittest.TestCase): self.subject = ProjectPresenter(SystemType.singleTilt, ModuleType.Cell96) buildings = [ [ [-3.42, 1.51], [-1.66, -1.64], [4.22, -0.87], [-0.8, 5.64]] ] expected_corners = [[ + {'x': -0.8, 'y': 5.64, 'length_cw': 8.22073597678456, 'length_ccw':4.890940604832571, 'angle':70.02691327912069}, {'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} + {'x': -1.66, 'y': -1.64, 'length_cw': 3.6083375673570233, 'length_ccw':5.930202357424239, 'angle':111.73284308914216}, + {'x': 4.22, 'y': -0.87, 'length_cw': 5.930202357424239, 'length_ccw':8.22073597678456, 'angle':59.82398240099042} ]] actual_corners = self.subject.get_corners(buildings) assert_array_equal(actual_corners,expected_corners) @@ -116,14 +129,13 @@ class PanelPresenterTest(unittest.TestCase): self.subject = ProjectPresenter(SystemType.singleTilt, ModuleType.Cell96) 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.8, 'y': 5.64, 'length_cw': 4.811319985201567, 'length_ccw':3.6208838699963852, 'angle':97.17527350158385}, {'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} + {'x': -0.78, 'y': -2.9, 'length_cw': 6.821172919667115, 'length_ccw':3.8596372886580936, 'angle':12.576112527956782}, + {'x': 0.66, 'y': -2.16, 'length_cw': 3.7643060449437424, 'length_ccw':3.424616766880639, 'angle':50.337833086033}, + {'x': 2.72, 'y': 2.36, 'length_cw': 1.7112568480505783, 'length_ccw':4.811319985201567, 'angle':87.50512700090906} ]] actual_corners = self.subject.get_corners(buildings) - print(actual_corners) assert_array_equal(actual_corners,expected_corners) def test_get_max_y(self):