def test_containsTheOther_BnotInAwithHole(self): exterior = [[-10, 10], [10, 10], [10, -10], [-10, -10]] hole = [[-1, 1], [1, 1], [1, -1], [-1, -1]] a = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={ 'type': 'Polygon', 'coordinates': [exterior, hole] }) b = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={ 'type': 'Polygon', 'coordinates': [[[100, 100], [101, 100], [101, 99], [100, 99]]] }) aContainsB = doesGeographyContainTheOther(container=a, target=b) self.assertFalse(aContainsB) bContainsA = doesGeographyContainTheOther(container=b, target=a) self.assertFalse(bContainsA)
def test_updateBlockContainerData_squareWithinAnother(self): exterior = [[-10, 10], [10, 10], [10, -10], [-10, -10]] shape1 = [[-1, 1], [1, 1], [1, -1], [-1, -1]] shape2 = [[-5, 5], [-4, 5], [-4, 4], [-5, 4]] a = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={'type': 'Polygon', 'coordinates': [exterior, shape1, shape2]}) b = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={ "type": "MultiPolygon", "coordinates": [ [shape1], [shape2] ] }) blocks = [a, b] blockContainer = CensusContainer() blockContainer.children = blocks self.assertEqual(blockContainer.population, 2) self.assertEqual(blockContainer.geometry, Polygon(exterior))
def test_attachOrphanBlocksToClosestNeighbor_Orphans(self): a = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={'type': 'Polygon', 'coordinates': [[[-1, 0], [-1, 1], [1, 1], [1, 0]]]}) b = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={'type': 'Polygon', 'coordinates': [[[4, 4], [4, 5], [5, 5], [5, 4]]]}) testRedistGroup = RedistrictingGroup(childrenBlocks=[a,b]) testGroups = [testRedistGroup] convertAllCensusBlocksToAtomicBlocks(testGroups) assignNeighboringBlocksToBlocksForRedistrictingGroups(testGroups) attachOrphanBlocksToClosestNeighborForRedistrictingGroups(testGroups) self.assertTrue(testRedistGroup.children[0].isNeighbor(testRedistGroup.children[1])) self.assertTrue(testRedistGroup.children[1].isNeighbor(testRedistGroup.children[0]))
def test_containsTheOther_BInButOnBorderOfA(self): # def isBoundaryGeometry(parent, child): # return parent.geometry.boundary.intersects(child.geometry.boundary) a = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={ 'type': 'Polygon', 'coordinates': [[[-5, 0], [5, 0], [5, 5], [-5, 5]]] }) b = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={ 'type': 'Polygon', 'coordinates': [[[0, 0], [1, 0], [1, 1], [0, 1]]] }) aContainsB = doesGeographyContainTheOther(container=a, target=b) self.assertTrue(aContainsB) bContainsA = doesGeographyContainTheOther(container=b, target=a) self.assertFalse(bContainsA)
def test_containsTheOther_BinA(self): a = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={ 'type': 'Polygon', 'coordinates': [[[-10, 10], [10, 10], [10, -10], [-10, -10]]] }) b = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={ 'type': 'Polygon', 'coordinates': [[[-1, 1], [1, 1], [1, -1], [-1, -1]]] }) aContainsB = doesGeographyContainTheOther(container=a, target=b) self.assertTrue(aContainsB) bContainsA = doesGeographyContainTheOther(container=b, target=a) self.assertFalse(bContainsA)
def test_containsTheOther_BMultiploygoninAWithHoles(self): exterior = [[-10, 10], [10, 10], [10, -10], [-10, -10]] shape1 = [[-1, 1], [1, 1], [1, -1], [-1, -1]] shape2 = [[-5, 5], [-4, 5], [-4, 4], [-5, 4]] a = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={ 'type': 'Polygon', 'coordinates': [exterior, shape1, shape2] }) b = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={ "type": "MultiPolygon", "coordinates": [[shape1], [shape2]] }) aContainsB = doesGeographyContainTheOther(container=a, target=b) self.assertTrue(aContainsB) bContainsA = doesGeographyContainTheOther(container=b, target=a) self.assertFalse(bContainsA)
def test_intersectingGeometries_BinAwithHole(self): exterior = [[-10, 10], [10, 10], [10, -10], [-10, -10]] hole = [[-1, 1], [1, 1], [1, -1], [-1, -1]] a = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={ 'type': 'Polygon', 'coordinates': [exterior, hole] }) b = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={ 'type': 'Polygon', 'coordinates': [hole] }) aIntersectsB = intersectingGeometries(a, b) bIntersectsA = intersectingGeometries(b, a) self.assertTrue(aIntersectsB and bIntersectsA)
def test_updateBlockContainerData_singleCircle(self): a = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={'type': 'Polygon', 'coordinates': [[[0,0], [-1, 1], [1, 1], [1, 0]]]}) circle = Point(0,0).buffer(1) #replace the geometry a.geometry = circle blocks = [a] blockContainer = CensusContainer() blockContainer.children = blocks self.assertEqual(blockContainer.population, 1) self.assertEqual(blockContainer.geometry, circle)
def createAtomicBlocksFromBlockList(blockList): # some blocks aren't contiguous (typically uninhabited islands), so we break them up into separate blocks tqdm.write(' *** Separating Blocks if necessary ***') updatedBlocks = [] with tqdm(total=len(blockList)) as pbar: for block in blockList: if type(block.geometry) is MultiPolygon: blockPolygons = list(block.geometry) popSplit = math.floor(block.population / len(blockPolygons)) popTotalSoFar = 0 i = 1 for blockPolygon in blockPolygons: popTotalSoFar += popSplit if blockPolygons.index( blockPolygon) == len(blockPolygons) - 1: diffInPop = block.population - popTotalSoFar popSplit += diffInPop newFIPS = block.FIPS + str(i) splitBlock = CensusBlock(countyFIPS=block.countyFIPS, tractFIPS=block.tractFIPS, blockFIPS=newFIPS, population=int(popSplit), isWater=block.isWater, geometry=blockPolygon) updatedBlocks.append(splitBlock) i += 1 else: updatedBlocks.append(block) pbar.update(1) tqdm.write(' *** Creating Atomic Blocks ***') atomicBlockList = [] with tqdm(total=len(updatedBlocks)) as pbar: for i in reversed(range(len(updatedBlocks))): block = updatedBlocks[i] convertedAtomicBlock = createAtomicBlockFromCensusBlock(block) atomicBlockList.append(convertedAtomicBlock) for j in reversed(range(len(updatedBlocks))): otherBlock = updatedBlocks[j] if block != otherBlock: if doesGeographyContainTheOther(container=block, target=otherBlock): convertedAtomicBlock.importCensusBlock(otherBlock) del updatedBlocks[updatedBlocks.index(otherBlock)] atomicBlockThatAlreadyExists = atomicBlockWithBlock( block=otherBlock, atomicBlockList=atomicBlockList) if atomicBlockThatAlreadyExists: del atomicBlockList[atomicBlockList.index( atomicBlockThatAlreadyExists)] pbar.update(1) return atomicBlockList
def test_splitDistrict_singleRedistrictingGroup(self): blockOne = AtomicBlock(childrenBlocks=[ CensusBlock( countyFIPS='01', tractFIPS='01', blockFIPS='01', population=10, isWater=False, geoJSONGeometry={ 'type': 'Polygon', 'coordinates': [[[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]] }) ]) blockTwo = AtomicBlock(childrenBlocks=[ CensusBlock( countyFIPS='01', tractFIPS='01', blockFIPS='02', population=10, isWater=False, geoJSONGeometry={ 'type': 'Polygon', 'coordinates': [[[0, 0], [0, -1], [1, -1], [1, 0], [0, 0]]] }) ]) singleRedistrictingGroup = RedistrictingGroup( childrenBlocks=[blockOne, blockTwo]) singleRedistrictingGroup.assignNeighboringBlocksToBlocks() testDistrictCandidate = createDistrictFromRedistrictingGroups( [singleRedistrictingGroup]) splits = testDistrictCandidate.splitDistrict( numberOfDistricts=2, populationDeviation=1, weightingMethod=WeightingMethod.distance, breakingMethod=BreakingMethod.splitGroupsOnEdge, shouldMergeIntoFormerRedistrictingGroups=True, fastCalculations=False, showDetailedProgress=False, shouldSaveProgress=False) self.assertEqual(len(splits), 2)
def test_intersectingGeometries_BsharesSideWithA(self): a = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={ 'type': 'Polygon', 'coordinates': [[[-1, 0], [-1, 1], [0, 1], [0, 0]]] }) b = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={ 'type': 'Polygon', 'coordinates': [[[0, 0], [0, 1], [1, 1], [1, 0]]] }) aIntersectsB = intersectingGeometries(a, b) bIntersectsA = intersectingGeometries(b, a) self.assertTrue(aIntersectsB and bIntersectsA)
def test_intersectingGeometries_BnotInA(self): a = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={ 'type': 'Polygon', 'coordinates': [[[5, 5], [6, 5], [6, 4], [5, 4]]] }) b = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={ 'type': 'Polygon', 'coordinates': [[[-1, 1], [1, 1], [1, -1], [-1, -1]]] }) aIntersectsB = intersectingGeometries(a, b) bIntersectsA = intersectingGeometries(b, a) self.assertFalse(aIntersectsB and bIntersectsA)
def test_updateBlockContainerData_touchingSquares(self): a = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={'type': 'Polygon', 'coordinates': [[[-1, 0], [-1, 1], [1, 1], [1, 0]]]}) b = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={'type': 'Polygon', 'coordinates': [[[-1, 1], [-1, 2], [1, 2], [1, 1]]]}) blocks = [a,b] blockContainer = CensusContainer() blockContainer.children = blocks self.assertEqual(blockContainer.population, 2) combinedPolygon = Polygon([(-1, 0), (-1, 2), (1, 2), (1, 0)]) self.assertEqual(blockContainer.geometry, combinedPolygon)
def test_containsTheOther_BinAMultiPolygon(self): a = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={ "type": "MultiPolygon", "coordinates": [[[[-82.60879799999999, 43.743775], [-82.60899999999999, 43.743736], [-82.609098, 43.74378], [-82.60789800000001, 43.744233], [-82.607466, 43.744281], [-82.607097, 43.744456], [-82.606692, 43.744626], [-82.606404, 43.74435], [-82.606708, 43.744312], [-82.607049, 43.744302], [-82.607451, 43.744177], [-82.607694, 43.74415], [-82.608666, 43.743801], [-82.60879799999999, 43.743775]]], [[[-82.606212, 43.734192], [-82.606246, 43.734014], [-82.606542, 43.733894], [-82.60693000000001, 43.733642], [-82.607241, 43.733473], [-82.60751399999999, 43.733501], [-82.606617, 43.734042], [-82.606464, 43.734251], [-82.606207, 43.734217], [-82.606212, 43.734192]]], [[[-82.608132, 43.746174], [-82.608152, 43.746201], [-82.60801499999999, 43.746305], [-82.60791500000001, 43.746425], [-82.607719, 43.746397], [-82.607742, 43.746309], [-82.60781, 43.746315], [-82.607871, 43.746227], [-82.608108, 43.746142], [-82.608132, 43.746174]]]] }) b = CensusBlock(countyFIPS='01', tractFIPS='01', blockFIPS='01', population=int('1'), isWater=False, geoJSONGeometry={ "type": "Polygon", "coordinates": [[[-82.59254199999999, 43.777148], [-82.599344, 43.777084], [-82.599521, 43.777149], [-82.609269, 43.789296], [-82.608028, 43.79799], [-82.621675, 43.826759], [-82.62451, 43.836733], [-82.62539700000001, 43.847984], [-82.639571, 43.862742], [-82.63938400000001, 43.862746], [-82.593673, 43.863701], [-82.59366799999999, 43.863332], [-82.593637, 43.860939], [-82.59254199999999, 43.777148]]] }) aContainsB = doesGeographyContainTheOther(container=a, target=b) self.assertFalse(aContainsB) bContainsA = doesGeographyContainTheOther(container=b, target=a) self.assertFalse(bContainsA)