import numpy import sys from shaperrec import manipulation # ************************************************************* # debugging def void(*l): pass def debug_on(*l): sys.stderr.write(' '.join(str(i) for i in l) +'\n') debug = void #debug = debug_on ##************************************** ## class SegmentExtender: """Extend Segments part of a list of Path by aggregating points from neighbouring Path objects. There are 2 concrete subclasses for extending forward and backward (due to technical reasons). """ def __init__(self, relD, fitQ): self.relD = relD self.fitQ = fitQ def nextPaths(self, seg): pL = [] p = self.getNext(seg) # prev or next while p : if p.isSegment(): break if p.mergedObj is None: break pL.append(p) p = self.getNext(p) if pL==[]: return [] return pL def extend(self, seg): nextPathL = self.nextPaths(seg) debug('extend ', self.extDir, seg, nextPathL, seg.length, len(nextPathL)) if nextPathL==[]: return seg pointsToTest = numpy.concatenate( [p.points for p in nextPathL] ) mergeD = seg.length*self.relD #print seg.point1 , seg.pointN, pointsToTest pointsToFit, addedPoints = self.pointsToFit(seg, pointsToTest, mergeD) if len(pointsToFit)==0: return seg newseg = manipulation.fitSingleSegment(pointsToFit) if newseg.quality()>self.fitQ: # fit failed return seg debug( ' EXTENDING ! ', len(seg.points), len(addedPoints) ) self.removePath(seg, newseg, nextPathL, addedPoints ) newseg.points = pointsToFit seg.mergedObj= newseg newseg.sourcepoints = seg.sourcepoints return newseg @staticmethod def extendSegments(segmentList, relD=0.03, qual=0.5): """Perform Segment extension from list of Path segmentList returns the updated list of Path objects""" fwdExt = FwdExtender(relD, qual) bwdExt = BwdExtender(relD, qual) # tag all objects with an attribute pointing to the extended object for seg in segmentList: seg.mergedObj = seg # by default the extended object is self # extend each segments, starting by the longest for seg in sorted(segmentList, key = lambda s : s.length, reverse=True): if seg.isSegment(): newseg=fwdExt.extend(seg) seg.mergedObj = bwdExt.extend(newseg) # the extension procedure has marked as None the mergedObj # which have been swallowed by an extension. # filter them out : updatedSegs=[seg.mergedObj for seg in segmentList if seg.mergedObj] return updatedSegs class FwdExtender(SegmentExtender): extDir='Fwd' def getNext(self, seg): return seg.__next__ if hasattr(seg, "__next__") else None def pointsToFit(self, seg, pointsToTest, mergeD): distancesToLine =abs(seg.a*pointsToTest[:, 0]+seg.b*pointsToTest[:, 1]+seg.c) goodInd=len(pointsToTest) for i, d in reversed(list(enumerate(distancesToLine))): if d