def add_line(self, entity): ''' Converts a DXF line entity (or entitines) to the proper form and adds the information to the list of vertices and to the set of segments ARGUMENTS: entity (obj) -- DXF entity from dxfgrabber RAISES: TypeError -- if entitiy.dxftype is not 'LINE' ''' # Check input if entity.dxftype != 'LINE': msg = 'dxf entitiy passed was not a LINE but a {}'.format( entity.dxftype) raise TypeError(msg) # Find end-points start = (approx(entity.start[0], tol=self.tol), approx(entity.start[1], tol=self.tol)) end = (approx(entity.end[0], tol=self.tol), approx(entity.end[1], tol=self.tol)) # Add vertices and connect them self.verts.add(start) self.verts.add(end) self.verts.connect(start, end) # Collect segment data and add to set initial_len = len(self.segments) seg = ((start, end), ()) self.vprint('adding line {}'.format(seg[0])) self.segments.add(seg) if len(self.segments) == initial_len: self.vprint('\tSegment already exists... skipped')
def test_add_line(self): '''add a line to the geometry''' # Loop through entities and add only lines tol = self.empty_dxfgeom.tol for e in self.test_dxf.entities: if e.dxftype == 'LINE': self.empty_dxfgeom.add_line(e) start = (approx(e.start[0], tol=tol), approx(e.start[1], tol=tol)) end = (e.end[0], e.end[1]) self.check_vertices((start, end), self.empty_dxfgeom, e)
def check_vertices(self, tup, dxfgeom, entity): '''vertices are in vertex list and they are connected''' tol = dxfgeom.tol start = (approx(tup[0][0], tol), approx(tup[0][1],tol)) end = (approx(tup[1][0], tol), approx(tup[1][1],tol)) # Check to make sure start and end are vertices now check = (start in dxfgeom.verts.coordinates) and (end in dxfgeom.verts.coordinates) msg = '{} and {} were not added to vertices'.format(start, end) self.assertTrue(check, msg) # Make sure vertices are connected check = end in dxfgeom.verts.vertices[start].connections msg = '{} not properly connected by line {}'.format(end, entity) self.assertTrue(check, msg)
def test_add_polyline(self): '''add a polyline to the geometry''' # Loop through entities and add only arcs tol = self.empty_dxfgeom.tol for e in self.test_dxf.entities: if e.dxftype == 'POLYLINE': self.empty_dxfgeom.add_polyline(e) for i, p in enumerate(e.points): try: p_next = e.points[i+1] except IndexError: if e.is_closed: p_next = e.points[0] else: break start = (approx(p[0], tol=tol), approx(p[1], tol=tol)) end = (approx(p_next[0], tol=tol), approx(p_next[1], tol=tol)) self.check_vertices((start, end), self.empty_dxfgeom, e)
def add_arc(self, entity): ''' Converts a DXF arc entity (or entities) to the proper form and adds the information to the list of vertices and to the set of segments. Bulge and arc information is also compiled and computed. ARGUMENTS: entity (obj) -- DXF entity from dxfgrabber RAISES: TypeError -- if entitiy.dxftype is not 'ARC' ''' # Check input if entity.dxftype != 'ARC': msg = 'dxf entitiy passed was not an ARC but a {}'.format( entity.dxftype) raise TypeError(msg) # Extract information (again ignoring z-coordinate) start_angle = np.radians(entity.startangle) end_angle = np.radians(entity.endangle) center = (approx(entity.center[0], tol=self.tol), approx(entity.center[1], tol=self.tol)) radius = approx(entity.radius, tol=1.0e-12) # Calculate bulge and start/stop information theta = ccw_angle_diff(start_angle, end_angle) bulge = np.tan(theta / 4) start = (approx(radius * np.cos(start_angle) + center[0], tol=self.tol), approx(radius * np.sin(start_angle) + center[1], tol=self.tol)) end = (approx(radius * np.cos(end_angle) + center[0], tol=self.tol), approx(radius * np.sin(end_angle) + center[1], tol=self.tol)) # Add vertices and connect them self.verts.add(start) self.verts.add(end) self.verts.connect(start, end) # Collect segment data and add to set initial_len = len(self.segments) seg = ((start, end), (bulge, start_angle, end_angle, center, radius)) self.vprint('adding arc {}'.format(seg[0])) self.segments.add(seg) if len(self.segments) == initial_len: self.vprint('\tSegment already exists... skipped')
def test_add_arc(self): '''add an arc to the geometry''' # Loop through entities and add only arcs for e in self.test_dxf.entities: if e.dxftype == 'ARC': self.empty_dxfgeom.add_arc(e) tol = self.empty_dxfgeom.tol start_angle = math.radians(e.startangle) end_angle = math.radians(e.endangle) center = (approx(e.center[0], tol=tol), approx(e.center[1], tol=tol)) radius = e.radius # Calculate bulge and start/stop information theta = ccw_angle_diff(start_angle, end_angle) bulge = math.tan(theta/4) start = (approx(radius*math.cos(start_angle) + center[0], tol=tol), approx(radius*math.sin(start_angle) + center[1], tol=tol)) end = (approx(radius*math.cos(end_angle) + center[0], tol=tol), approx(radius*math.sin(end_angle) + center[1], tol=tol)) self.check_vertices((start, end), self.empty_dxfgeom, e)
def add_polyline(self, entity): ''' Converts a DXF polyline entity into segments while transforming bulges into arcs (defined by a center of curvature and radius of curvature) and storing the vertex and segment information. ARGUMENTS: entity (obj) -- DXF entity from dxfgrabber RAISES: TypeError -- if entitiy.dxftype is not 'POLYLINE' ''' # Check input if entity.dxftype != 'POLYLINE' and entity.dxftype != 'LWPOLYLINE': msg = 'dxf entitiy passed was not a POLYLINE but a {}'.format( entity.dxftype) raise TypeError(msg) self.vprint( 'Breaking up this polyline into segments:\n{}'.format(entity)) # Loop through the points in the polyline for i, point in enumerate(entity.points): # Add the current point start = (approx(point[0], tol=self.tol), approx(point[1], tol=self.tol)) self.verts.add(start) try: # Add the next point if it exists next_point = entity.points[i + 1] except IndexError: # Next point DOESN'T exist therefore this is the end of the # polyline if entity.is_closed: # If polyline is closed, connect the last point (the current # point) back to the first point first_point = entity.points[0] end = (approx(first_point[0], tol=self.tol), approx(first_point[1], tol=self.tol)) self.verts.connect(start, end) else: # Otherwise the polyline is open so all segments have been # added already self.vprint('\tThis polyline is not closed!') break else: # The next point DOES exist so add it and connect it to the # current point end = (approx(next_point[0], tol=self.tol), approx(next_point[1], tol=self.tol)) self.verts.add(end) # Connect the two points #print start, end self.verts.connect(start, end) # Find number of segments before adding this one initial_len = len(self.segments) # Check whether there is a bulge in this segment if entity.bulge[i] != 0: # Convert bulge information to arc and store information bulge = entity.bulge[i] # Distance between points d = np.sqrt((start[0] - end[0])**2 + (start[1] - end[1])**2) # Angle between points from center theta = 4 * np.arctan(bulge) # Radius of circle making arc radius = approx(d / 2 / np.sin(abs(theta) / 2), tol=1e-12) # Find angle of segment relative to x axis alpha = np.arctan2(end[1] - start[1], end[0] - start[0]) # beta = (np.pi/2 - abs(theta)/2)*(np.pi - abs(theta))/abs(np.pi - abs(theta)) # # Angle to radius vector from x-axis is then the sum of alpha # # and beta # gamma = alpha + beta if bulge > 0: # Find angle between segment and radius. Beta is negative if # theta is greater than pi beta = np.pi / 2 - theta / 2 # Angle to radius vector from x-axis is then the SUM of # alpha and beta gamma = alpha + beta else: # Find angle between segment and radius. Beta is negative if # theta is greater than pi beta = np.pi / 2 + theta / 2 # Angle to radius vector from x-axis is then the DIFFERENCE # between alpha and beta gamma = alpha - beta # Gamma angle and radius describe the vector pointing from the # start point to the center center = (approx(radius * np.cos(gamma) + start[0], tol=self.tol), approx(radius * np.sin(gamma) + start[1], tol=self.tol)) # Now compute start and stop angles relative to horizontal in # a counter-clockwise sense start_angle = angle360( np.arctan2(start[1] - center[1], start[0] - center[0])) end_angle = angle360( np.arctan2(end[1] - center[1], end[0] - center[0])) # Compile all bulge/arc information and add it to segments seg = ((start, end), (bulge, start_angle, end_angle, center, radius)) self.vprint('\tadding arc {}'.format(seg[0])) self.segments.add(seg) if len(self.segments) == initial_len: self.vprint('\tSegment already exists... skipped') # Segment is a straight line else: seg = ((start, end), ()) # Add info to segments self.vprint('\tadding line {}'.format(seg[0])) self.segments.add(seg) if len(self.segments) == initial_len: self.vprint('\tSegment already exists... skipped')