95 lines
3.7 KiB
Python
95 lines
3.7 KiB
Python
import io
|
|
|
|
import dxfgrabber
|
|
|
|
from helix.constants.file_validation_error import FileValidationMessage
|
|
from helix.models.dxf.dxf_error import OldDxfFormatException
|
|
|
|
|
|
class DXFService(object):
|
|
"""
|
|
Takes the contents of a DXF file and creates modules, buildings, panels,
|
|
subarrays, and polygons based on the data
|
|
"""
|
|
|
|
# l_b is expected to be in inches, not feet!
|
|
def parse(self, dxf_file_contents, module_constants, system_type, l_b, dxf_helper, subarray_validator):
|
|
"""Parse will generate the panels, subarrays, buildings
|
|
and modules that are present in the dxf file
|
|
|
|
Arguments:
|
|
dxf_file_contents (str) Content of the uploaded file
|
|
"""
|
|
|
|
dxf = dxfgrabber.read(io.StringIO(dxf_file_contents, newline=None))
|
|
|
|
buildings, modules = dxf_helper.build_polygons(dxf.entities)
|
|
|
|
"""
|
|
A new type of aurora format file was added in the project
|
|
The visibile difference if you read the file, is that the
|
|
new format contains the string buildings.
|
|
The old version doesn't
|
|
|
|
"""
|
|
|
|
pair_spacing = None
|
|
dxf_helper.is_new_aurora_format()
|
|
if hasattr(module_constants, "spacing_size_inches"):
|
|
pair_spacing = module_constants.spacing_size_inches
|
|
|
|
if dxf_helper.should_consolidate_modules(modules, system_type,
|
|
module_constants):
|
|
modules = dxf_helper.consolidate_dual_tilt_modules(modules,
|
|
system_type,
|
|
pair_spacing)
|
|
|
|
translated_buildings, translated_modules = dxf_helper.translate_towards_origin(buildings, modules)
|
|
translated_buildings_ccw = dxf_helper.get_polygons_counterclockwise(translated_buildings)
|
|
buildings_ccw = dxf_helper.get_polygons_counterclockwise(buildings)
|
|
|
|
|
|
|
|
panels = dxf_helper.generate_panels(modules, translated_modules)
|
|
node_graph = dxf_helper.build_node_graph(panels, module_constants.panel_spacing)
|
|
subarrays = dxf_helper.detect_subarrays(node_graph, panels)
|
|
for subarray in subarrays:
|
|
subarray_validator.validate_subarray(node_graph, subarray.subarray_number, system_type)
|
|
dxf_helper.detect_panel_types(node_graph)
|
|
dxf_helper.detect_wind_zones(panels, translated_buildings_ccw, translated_modules, l_b, system_type)
|
|
|
|
all_points = [p.points for p in translated_buildings_ccw + translated_modules]
|
|
|
|
points = [point for points_list in all_points for point in points_list]
|
|
|
|
max_x = max(p[0] for p in points)
|
|
max_y = max(p[1] for p in points)
|
|
|
|
panel_orientation = panels[0].coordinate.rotation
|
|
|
|
return {
|
|
'size': (max_x, max_y), # Used for debugging
|
|
'buildings': buildings_ccw,
|
|
'modules': translated_modules,
|
|
'panels': panels,
|
|
'subarrays': subarrays,
|
|
'lb_polygons': dxf_helper.l_b_polygons(translated_buildings_ccw, l_b, system_type, panel_orientation),
|
|
'is_panel_drawing_inaccurate': self.is_panel_drawing_inaccurate(panels)
|
|
}
|
|
|
|
def is_panel_drawing_inaccurate(self,panels):
|
|
'''True if subarrays are not rotated more than allowed tolerance, false otherwise'''
|
|
ROTATION_ACCURACY_DELTA_DEGREES = 0.1
|
|
|
|
if panels is None or panels == []:
|
|
return True
|
|
|
|
first_panel_rotation = panels[0].coordinate.rotation # rotation is in degrees
|
|
|
|
for panel in panels:
|
|
difference = abs(first_panel_rotation - panel.coordinate.rotation)
|
|
if difference >= ROTATION_ACCURACY_DELTA_DEGREES:
|
|
return True
|
|
|
|
return False
|