require 'csvigo' require 'image' local pl = require 'pl.import_into' () local utils = {} function utils.roomTypeMap() local roomTypeMap = {} roomTypeMap[1] = 'living_room' roomTypeMap[2] = 'kitchen' roomTypeMap[3] = 'bedroom' roomTypeMap[4] = 'bathroom' roomTypeMap[5] = 'restroom' roomTypeMap[6] = 'balcony' roomTypeMap[7] = 'closet' roomTypeMap[8] = 'corridor' roomTypeMap[9] = 'stairs' roomTypeMap[10] = 'PS' return roomTypeMap end function utils.keyMap() local roomTypeMap = utils.roomTypeMap() local keyMap = {} keyMap['b'] = {'icons', 'bathtub'} keyMap['c'] = {'icons', 'cooking_counter'} keyMap['t'] = {'icons', 'toilet'} keyMap['s'] = {'icons', 'special'} keyMap['e'] = {'icons', 'entrance'} keyMap['w'] = {'icons', 'washing_basin'} for i = 1, 10 do keyMap[tostring(i % 10)] = {'labels', roomTypeMap[i]} end keyMap['a'] = {'walls', 'wall'} keyMap['d'] = {'doors', 'door'} return keyMap end function utils.classMap() local classMap = {} classMap.labels = {} classMap.labels['living_room'] = 1 classMap.labels['kitchen'] = 2 classMap.labels['bedroom'] = 3 classMap.labels['bathroom'] = 4 classMap.labels['restroom'] = 5 classMap.labels['balcony'] = 6 classMap.labels['closet'] = 7 classMap.labels['corridor'] = 8 classMap.labels['stairs'] = 9 classMap.labels['PS'] = 10 classMap.icons = {} classMap.icons['bathtub'] = 1 classMap.icons['cooking_counter'] = 2 classMap.icons['toilet'] = 3 classMap.icons['entrance'] = 4 classMap.icons['washing_basin'] = 5 classMap.icons['special'] = 6 return classMap end function utils.modeMap() local modeMap = {} local keyMap = utils.keyMap() for _, modeNamePair in pairs(keyMap) do modeMap[modeNamePair[2]] = modeNamePair[1] end return modeMap end function utils.numItemsPerCell() local numItemsPerCell = {} numItemsPerCell.points = 2 numItemsPerCell.doors = 2 numItemsPerCell.icons = 2 numItemsPerCell.labels = 2 return numItemsPerCell end function utils.numFeaturesPerItem() local numFeaturesPerItem = {} numFeaturesPerItem.points = 5 numFeaturesPerItem.doors = 5 numFeaturesPerItem.icons = 5 numFeaturesPerItem.labels = 5 return numFeaturesPerItem end function utils.offsetsBB() local numItemsPerCell = utils.numItemsPerCell() local numFeaturesPerItem = utils.numFeaturesPerItem() local offsetsBB = {} offsetsBB.points = 0 offsetsBB.doors = offsetsBB.points + numFeaturesPerItem.points * numItemsPerCell.points offsetsBB.icons = offsetsBB.doors + numFeaturesPerItem.doors * numItemsPerCell.doors offsetsBB.labels = offsetsBB.icons + numFeaturesPerItem.icons * numItemsPerCell.icons return offsetsBB end function utils.numFeaturesBB() local numItemsPerCell = utils.numItemsPerCell() local offsetsBB = utils.offsetsBB() local numFeaturesPerItem = utils.numFeaturesPerItem() local numFeaturesBB = offsetsBB.labels + numFeaturesPerItem.labels * numItemsPerCell.labels return numFeaturesBB end function utils.offsetsClass() local numItemsPerCell = utils.numItemsPerCell() local numFeaturesPerItem = utils.numFeaturesPerItem() local numFeaturesBB = utils.numFeaturesBB() local offsetsClass = {} offsetsClass.points = numFeaturesBB offsetsClass.doors = offsetsClass.points + numItemsPerCell.points offsetsClass.icons = offsetsClass.doors + numItemsPerCell.doors offsetsClass.labels = offsetsClass.icons + numItemsPerCell.icons return offsetsClass end function utils.numFeaturesClass() local numItemsPerCell = utils.numItemsPerCell() local numFeaturesClass = numItemsPerCell.points + numItemsPerCell.doors + numItemsPerCell.icons + numItemsPerCell.labels return numFeaturesClass end function utils.lineDim(line) if math.abs(line[1][1] - line[2][1]) > math.abs(line[1][2] - line[2][2]) and math.abs(line[1][2] - line[2][2]) <= 1 then return 1 elseif math.abs(line[1][2] - line[2][2]) > math.abs(line[1][1] - line[2][1]) and math.abs(line[1][1] - line[2][1]) <= 1 then return 2 else return 0 end end function utils.cutoffRange(range, max) local lowerBound = math.max(range[1], 1) local upperBound = math.min(range[2], max) if lowerBound > upperBound then return {} else return {lowerBound, upperBound} end end function utils.drawLineMask(width, height, lines, lineDim, lineWidth) local lineMask = torch.zeros(width, height) local size = {width, height} for _, line in pairs(lines) do if utils.lineDim(line) == lineDim then local fixedDim = 3 - lineDim local fixedValue = (line[1][fixedDim] + line[2][fixedDim]) / 2 local fixedRange = utils.cutoffRange({fixedValue - lineWidth, fixedValue + lineWidth}, size[fixedDim]) if #fixedRange > 0 then local lineRange = utils.cutoffRange({line[1][lineDim] - lineWidth, line[2][lineDim] + lineWidth}, size[lineDim]) if lineDim == 1 then lineMask[{{lineRange[1], lineRange[2]}, {fixedRange[1], fixedRange[2]}}] = 1 else lineMask[{{fixedRange[1], fixedRange[2]}, {lineRange[1], lineRange[2]}}] = 1 end end end end end function utils.sortLines(lines) for lineIndex, line in pairs(lines) do local lineDim = utils.lineDim(line) if lineDim > 0 and line[1][lineDim] > line[2][lineDim] then local temp = lines[lineIndex][1][lineDim] lines[lineIndex][1][lineDim] = lines[lineIndex][2][lineDim] lines[lineIndex][2][lineDim] = temp end end return lines end function utils.calcDistance(point_1, point_2) return math.sqrt(math.pow(point_1[1] - point_2[1], 2) + math.pow(point_1[2] - point_2[2], 2)) end function utils.findNearestEndPointPair(line_1, line_2, gap) local nearestPair local minDistance for index_1 = 1, 2 do for index_2 = 1, 2 do local distance = utils.calcDistance(line_1[index_1], line_2[index_2]) if minDistance == nil or distance < minDistance then nearestPair = {index_1, index_2} minDistance = distance end end end if minDistance > gap then local lineDim_1 = utils.lineDim(line_1) local lineDim_2 = utils.lineDim(line_2) local fixedValue_1 = (line_1[1][3 - lineDim_1] + line_1[2][3 - lineDim_1]) / 2 local fixedValue_2 = (line_2[1][3 - lineDim_2] + line_2[2][3 - lineDim_2]) / 2 if lineDim_1 + lineDim_2 == 3 then if line_2[1][lineDim_2] < fixedValue_1 and line_2[2][lineDim_2] > fixedValue_1 then for index = 1, 2 do local distance = math.abs(line_1[index][lineDim_1] - fixedValue_2) if distance < minDistance then nearestPair = {index, 0} minDistance = distance end end end if line_1[1][lineDim_1] < fixedValue_2 and line_1[2][lineDim_1] > fixedValue_2 then for index = 1, 2 do local distance = math.abs(line_2[index][lineDim_2] - fixedValue_1) if distance < minDistance then nearestPair = {0, index} minDistance = distance end end end end end if #line_1 >= 3 and line_1[3][2] == 2 and line_2[3][2] == 1 then nearestPair[2] = 0 end if #line_2 >= 3 and line_2[3][2] == 2 and line_1[3][2] == 1 then nearestPair[1] = 0 end return nearestPair, minDistance end function utils.stitchLines(lines, gap) for lineIndex_1, line_1 in pairs(lines) do local lineDim_1 = utils.lineDim(line_1) if lineDim_1 > 0 then local fixedValue_1 = (line_1[1][3 - lineDim_1] + line_1[2][3 - lineDim_1]) / 2 for lineIndex_2, line_2 in pairs(lines) do if lineIndex_2 > lineIndex_1 then local lineDim_2 = utils.lineDim(line_2) if lineDim_2 > 0 then local fixedValue_2 = (line_2[1][3 - lineDim_2] + line_2[2][3 - lineDim_2]) / 2 local nearestPair, minDistance = utils.findNearestEndPointPair(line_1, line_2, gap) --print(minDistance .. ' ' .. lineDim_1 .. ' ' .. lineDim_2) if minDistance <= gap and lineDim_1 + lineDim_2 == 3 then local pointIndex_1 = nearestPair[1] local pointIndex_2 = nearestPair[2] --print(lineIndex_1 .. ' ' .. lineIndex_2) if pointIndex_1 > 0 and pointIndex_2 > 0 then lines[lineIndex_1][pointIndex_1][lineDim_1] = fixedValue_2 lines[lineIndex_2][pointIndex_2][lineDim_2] = fixedValue_1 elseif pointIndex_1 > 0 and pointIndex_2 == 0 then lines[lineIndex_1][pointIndex_1][lineDim_1] = fixedValue_2 elseif pointIndex_1 == 0 and pointIndex_2 > 0 then lines[lineIndex_2][pointIndex_2][lineDim_2] = fixedValue_1 end end end end end end end return lines end function utils.gridPoint(width, height, gridWidth, gridHeight, point) local cellWidth = width / gridWidth local cellHeight = height / gridHeight local gridX = math.floor((point[1] - 1) / cellWidth) + 1 local gridY = math.floor((point[2] - 1) / cellHeight) + 1 local cellX = ((point[1] - 1) - (gridX - 1) * cellWidth) / (cellWidth - 1) local cellY = ((point[2] - 1) - (gridY - 1) * cellHeight) / (cellHeight - 1) return {{gridX, gridY}, {cellX, cellY}} end function utils.gridRectangle(width, height, gridWidth, gridHeight, point_1, point_2) if point_2 == nil then local rectangle = utils.gridPoint(width, height, gridWidth, gridHeight, point_1) table.insert(rectangle, {0, 0}) return rectangle end local center = utils.gridPoint(width, height, gridWidth, gridHeight, {(point_1[1] + point_2[1]) / 2, (point_1[2] + point_2[2]) / 2}) local rectangle = center table.insert(rectangle, {(point_2[1] - point_1[1] + 1) / width, (point_2[2] - point_1[2] + 1) / height}) return rectangle end function utils.imageRectangle(width, height, gridWidth, gridHeight, rectangle) local cellWidth = width / gridWidth local cellHeight = height / gridHeight local centerX = (rectangle[1][1] - 1) * cellWidth + rectangle[2][1] * (cellWidth - 1) + 1 local centerY = (rectangle[1][2] - 1) * cellHeight + rectangle[2][2] * (cellHeight - 1) + 1 return {{centerX - (rectangle[3][1] * width - 1) / 2, centerY - (rectangle[3][2] * height - 1) / 2}, {centerX + (rectangle[3][1] * width - 1) / 2, centerY + (rectangle[3][2] * height - 1) / 2}} end function utils.convertRepresentation(width, height, representationGeneral, representationType, gap) local representation = {} if representationType == 'P' then local points = {} local usedLinePointMask = {} for lineIndex, line in pairs(representationGeneral.walls) do usedLinePointMask[lineIndex] = {false, false} end for lineIndex_1, line_1 in pairs(representationGeneral.walls) do local lineDim_1 = utils.lineDim(line_1) if lineDim_1 > 0 then local fixedValue_1 = (line_1[1][3 - lineDim_1] + line_1[2][3 - lineDim_1]) / 2 for lineIndex_2, line_2 in pairs(representationGeneral.walls) do if lineIndex_2 > lineIndex_1 then local lineDim_2 = utils.lineDim(line_2) if lineDim_2 > 0 then local fixedValue_2 = (line_2[1][3 - lineDim_2] + line_2[2][3 - lineDim_2]) / 2 local nearestPair, minDistance = utils.findNearestEndPointPair(line_1, line_2, gap) if minDistance <= gap and lineDim_1 + lineDim_2 == 3 then local pointIndex_1 = nearestPair[1] local pointIndex_2 = nearestPair[2] if pointIndex_1 > 0 and pointIndex_2 > 0 then local point = {} point[lineDim_1] = fixedValue_2 point[lineDim_2] = fixedValue_1 local side = {} side[lineDim_1] = line_1[3 - pointIndex_1][lineDim_1] - fixedValue_2 side[lineDim_2] = line_2[3 - pointIndex_2][lineDim_2] - fixedValue_1 if side[1] < 0 and side[2] < 0 then table.insert(points, {point, {'point', 2, 1}}) elseif side[1] > 0 and side[2] < 0 then table.insert(points, {point, {'point', 2, 2}}) elseif side[1] > 0 and side[2] > 0 then table.insert(points, {point, {'point', 2, 3}}) elseif side[1] < 0 and side[2] > 0 then table.insert(points, {point, {'point', 2, 4}}) end usedLinePointMask[lineIndex_1][pointIndex_1] = true usedLinePointMask[lineIndex_2][pointIndex_2] = true elseif (pointIndex_1 > 0 and pointIndex_2 == 0) or (pointIndex_1 == 0 and pointIndex_2 > 0) then local lineDim local pointIndex local fixedValue local pointValue if pointIndex_1 > 0 then lineDim = lineDim_1 pointIndex = pointIndex_1 fixedValue = fixedValue_2 pointValue = line_1[pointIndex_1][3 - lineDim_1] usedLinePointMask[lineIndex_1][pointIndex_1] = true else lineDim = lineDim_2 pointIndex = pointIndex_2 fixedValue = fixedValue_1 pointValue = line_2[pointIndex_2][3 - lineDim_2] usedLinePointMask[lineIndex_2][pointIndex_2] = true end local point = {} point[lineDim] = fixedValue point[3 - lineDim] = pointValue if pointIndex == 1 then if lineDim == 1 then table.insert(points, {point, {'point', 3, 4}}) else table.insert(points, {point, {'point', 3, 1}}) end else if lineDim == 1 then table.insert(points, {point, {'point', 3, 2}}) else table.insert(points, {point, {'point', 3, 3}}) end end elseif line_1[1][lineDim_1] < fixedValue_2 and line_1[2][lineDim_1] > fixedValue_2 and line_2[1][lineDim_2] < fixedValue_1 and line_2[2][lineDim_2] > fixedValue_1 then local point = {} point[lineDim_1] = fixedValue_2 point[lineDim_2] = fixedValue_1 table.insert(points, {point, {'point', 4, 1}}) end --print(lineIndex_1 .. '\t' .. lineIndex_2) --print(nearestPair[1] .. '\t' .. nearestPair[2] .. '\t' .. minDistance) --local point = points[#points] --print(#points .. '\t' .. point[1][1] .. '\t' .. point[1][2] .. '\t' .. point[2][2]) end end end end end end --for _, point in pairs(points) do --print(point[1][1] .. '\t' .. point[1][2] .. '\t' .. point[2][2]) --end --os.exit(1) for lineIndex, pointMask in pairs(usedLinePointMask) do local lineDim = utils.lineDim(representationGeneral.walls[lineIndex]) for pointIndex = 1, 2 do if pointMask[pointIndex] == false then local point = {representationGeneral.walls[lineIndex][pointIndex][1], representationGeneral.walls[lineIndex][pointIndex][2]} if pointIndex == 1 then if lineDim == 1 then table.insert(points, {point, {'point', 1, 4}}) else table.insert(points, {point, {'point', 1, 1}}) end else if lineDim == 1 then table.insert(points, {point, {'point', 1, 2}}) else table.insert(points, {point, {'point', 1, 3}}) end end end end end representation.points = points representation.doors = representationGeneral.doors representation.icons = representationGeneral.icons representation.labels = representationGeneral.labels end --[[ print('from') for mode, items in pairs(representationGeneral) do print(mode .. '\t' .. #items) end print('to') for mode, items in pairs(representation) do print(mode .. '\t' .. #items) end ]]-- return representation end function utils.convertRepresentationToTensor(width, height, gridWidth, gridHeight, representationGlobal) local representation = {} representation.points = {} for _, point in pairs(representationGlobal.points) do local newPoint = utils.gridRectangle(width, height, gridWidth, gridHeight, point[1]) table.insert(newPoint, point[2]) if newPoint[1][1] >= 1 and newPoint[1][1] <= gridWidth and newPoint[1][2] >= 1 and newPoint[1][2] <= gridHeight then table.insert(representation.points, newPoint) end end representation.doors = {} for _, door in pairs(representationGlobal.doors) do local newRectangle = utils.gridRectangle(width, height, gridWidth, gridHeight, door[1], door[2]) table.insert(newRectangle, door[3]) if newRectangle[1][1] >= 1 and newRectangle[1][1] <= gridWidth and newRectangle[1][2] >= 1 and newRectangle[1][2] <= gridHeight then table.insert(representation.doors, newRectangle) end end representation.icons = {} for _, icon in pairs(representationGlobal.icons) do local newRectangle = utils.gridRectangle(width, height, gridWidth, gridHeight, icon[1], icon[2]) table.insert(newRectangle, icon[3]) if newRectangle[1][1] >= 1 and newRectangle[1][1] <= gridWidth and newRectangle[1][2] >= 1 and newRectangle[1][2] <= gridHeight then table.insert(representation.icons, newRectangle) end end representation.labels = {} for _, label in pairs(representationGlobal.labels) do local newPoint = utils.gridRectangle(width, height, gridWidth, gridHeight, label[1], label[2]) --table.remove(newPoint) table.insert(newPoint, label[3]) if newPoint[1][1] >= 1 and newPoint[1][1] <= gridWidth and newPoint[1][2] >= 1 and newPoint[1][2] <= gridHeight then table.insert(representation.labels, newPoint) end end local offsetsBB = utils.offsetsBB() local offsetsClass = utils.offsetsClass() local numFeaturesBB = utils.numFeaturesBB() local numFeaturesClass = utils.numFeaturesClass() local classMap = utils.classMap() local numItemsPerCell = utils.numItemsPerCell() local numFeaturesPerItem = utils.numFeaturesPerItem() local representationTensor = torch.zeros(numFeaturesBB + numFeaturesClass, gridHeight, gridWidth) local gridItems = {} for y = 1, gridHeight do gridItems[y] = {} for x = 1, gridWidth do gridItems[y][x] = {} for mode, offset in pairs(offsetsBB) do gridItems[y][x][mode] = {} end end end for mode, items in pairs(representation) do for __, item in pairs(items) do --if gridItems[item[1][2]][item[1][1]][mode] ~= nil then table.insert(gridItems[item[1][2]][item[1][1]][mode], item) --end end end for x = 1, gridWidth do for y = 1, gridHeight do for mode, items in pairs(gridItems[y][x]) do local numFeatures = numFeaturesPerItem[mode] local sortedItems = {} for _, item in pairs(items) do table.insert(sortedItems, {item[2][1] + item[2][2], item}) end table.sort(sortedItems, function(a, b) return a[1] < b[1] end) for i = numItemsPerCell[mode] + 1, #sortedItems do table.remove(sortedItems) end local offsetBB = offsetsBB[mode] for itemIndex, item in pairs(sortedItems) do item = item[2] local itemTensor = representationTensor[{{offsetBB + (itemIndex - 1) * numFeatures + 1, offsetBB + (itemIndex - 1) * numFeatures + numFeatures}, y, x}] itemTensor[1] = item[2][1] itemTensor[2] = item[2][2] itemTensor[3] = item[3][1] itemTensor[4] = item[3][2] itemTensor[5] = 1 end local offsetClass = offsetsClass[mode] for itemIndex, item in pairs(sortedItems) do item = item[2] local class if mode == 'points' then class = (item[4][2] - 1) * 4 + item[4][3] elseif mode == 'doors' then class = item[4][2] elseif mode == 'icons' then class = classMap[mode][item[4][1]] elseif mode == 'labels' then class = classMap[mode][item[4][1]] end --print(mode) --print(item[4][1]) --print(class) representationTensor[{offsetClass + itemIndex, y, x}] = class end end end end return representationTensor end function utils.convertTensorToRepresentation(width, height, representationTensor, confidenceThreshold) local offsetsBB = utils.offsetsBB() local offsetsClass = utils.offsetsClass() local numItemsPerCell = utils.numItemsPerCell() local numFeaturesPerItem = utils.numFeaturesPerItem() local representation = {} representation.points = {} representation.doors = {} representation.icons = {} representation.labels = {} local gridWidth = representationTensor:size(3) local gridHeight = representationTensor:size(2) local confidenceThreshold = confidenceThreshold or 0.5 for x = 1, gridWidth do for y = 1, gridHeight do for mode, numItems in pairs(numItemsPerCell) do local offsetBB = offsetsBB[mode] local offsetClass = offsetsClass[mode] local numFeatures = numFeaturesPerItem[mode] for itemIndex = 1, numItems do local item = representationTensor[{{offsetBB + (itemIndex - 1) * numFeatures + 1, offsetBB + (itemIndex - 1) * numFeatures + numFeatures}, y, x}] local class = representationTensor[{offsetClass + itemIndex, y, x}] --if torch.max(item) > 0 then --print(mode) --print(item) --end if item[5] > confidenceThreshold then if mode == 'points' then table.insert(representation[mode], {{x, y}, {item[1], item[2]}, {item[3], item[4]}, {'point', math.floor((class - 1) / 4) + 1, (class - 1) % 4 + 1}}) elseif mode == 'doors' then table.insert(representation[mode], {{x, y}, {item[1], item[2]}, {item[3], item[4]}, {'door', 1, 1}}) elseif mode == 'icons' then table.insert(representation[mode], {{x, y}, {item[1], item[2]}, {item[3], item[4]}, {'icon', 1, 1}}) elseif mode == 'labels' then table.insert(representation[mode], {{x, y}, {item[1], item[2]}, {item[3], item[4]}, {'label', 1, 1}}) end end end end end end return representation end function utils.cropRepresentation(representation, startX, startY, endX, endY) local newRepresentation = {} for mode, items in pairs(representation) do newRepresentation[mode] = {} for _, item in pairs(items) do if (item[1][1] + item[2][1]) / 2 <= endX and (item[1][2] + item[2][2]) / 2 <= endY then for pointIndex = 1, 2 do item[pointIndex][1] = item[pointIndex][1] - startX item[pointIndex][2] = item[pointIndex][2] - startY end --[[ print(mode) for i = 1, 3 do print(item[i][1] .. ' ' .. item[i][2]) end ]]-- table.insert(newRepresentation[mode], item) end end end return newRepresentation end function utils.scaleRepresentation(representation, width, height, newWidth, newHeight) local newRepresentation = {} for mode, items in pairs(representation) do newRepresentation[mode] = {} for _, item in pairs(items) do for pointIndex = 1, 2 do item[pointIndex][1] = torch.round((item[pointIndex][1] - 1) / (width - 1) * (newWidth - 1) + 1) item[pointIndex][2] = torch.round((item[pointIndex][2] - 1) / (height - 1) * (newHeight - 1) + 1) end table.insert(newRepresentation[mode], item) end end return newRepresentation end function utils.rotateRepresentation(representation, width, height, orientation) if orientation == 1 then return representation end local newRepresentation = {} for mode, items in pairs(representation) do newRepresentation[mode] = {} for _, item in pairs(items) do for pointIndex = 1, 2 do local x = item[pointIndex][1] local y = item[pointIndex][2] if orientation == 2 then item[pointIndex][1] = height - y item[pointIndex][2] = x elseif orientation == 3 then item[pointIndex][1] = width - x item[pointIndex][2] = height - y else item[pointIndex][1] = y item[pointIndex][2] = width - x end end table.insert(newRepresentation[mode], item) end end newRepresentation.walls = utils.sortLines(newRepresentation.walls) newRepresentation.doors = utils.sortLines(newRepresentation.doors) return newRepresentation end function utils.drawRepresentationImage(width, height, gridWidth, gridHeight, floorplan, representation, representationType, renderingType, lineWidth) representationType = representationType or 'P' renderingType = renderingType or 'P' if representationType == 'P' and renderingType == 'P' then local colorMap = {} colorMap[1] = {255, 0, 0} colorMap[2] = {0, 255, 0} colorMap[3] = {0, 0, 255} colorMap[4] = {255, 255, 0} colorMap[5] = {0, 255, 255} colorMap[6] = {255, 0, 255} colorMap[7] = {128, 0, 0} colorMap[8] = {0, 128, 0} colorMap[9] = {0, 0, 128} local representationImage = floorplan for mode, items in pairs(representation) do if mode == 'points' or mode == 'doors' or mode == 'icons' or mode == 'labels' then for __, item in pairs(items) do local rectangle = utils.imageRectangle(width, height, gridWidth, gridHeight, item) local center = {(rectangle[2][1] + rectangle[1][1]) / 2, (rectangle[2][2] + rectangle[1][2]) / 2} local rectangleWidth = math.max(rectangle[2][1] - rectangle[1][1] + 1, 10) local rectangleHeight = math.max(rectangle[2][2] - rectangle[1][2] + 1, 10) local color = colorMap[item[4][2]] lineWidth = 2 if mode == 'points' then lineWidth = 10 end --[[ print(mode) print(width .. ' ' .. height) print(center[1] .. ' ' .. center[2]) print(rectangleWidth .. ' ' .. rectangleHeight) print(#representationImage) print(math.max(center[1] - rectangleWidth / 2, 1) .. ' ' .. math.max(center[2] - rectangleHeight / 2, 1) .. ' ' .. math.min(center[1] + rectangleWidth / 2, width) .. ' ' .. math.min(center[2] + rectangleHeight / 2, height)) ]]-- --representationImage = image.drawRect(representationImage, math.max(center[1] - rectangleWidth / 2, 1), math.max(center[2] - rectangleHeight / 2, 1), math.min(center[1] + rectangleWidth / 2, width), math.min(center[2] + rectangleHeight / 2, height), {lineWidth = lineWidth, color = color}) success, newRepresentationImage = pcall(function() return image.drawRect(representationImage, math.max(center[1] - rectangleWidth / 2, 1), math.max(center[2] - rectangleHeight / 2, 1), math.min(center[1] + rectangleWidth / 2, width), math.min(center[2] + rectangleHeight / 2, height), {lineWidth = lineWidth, color = color}) end) if success then representationImage = newRepresentationImage else --[[ print('Fail to draw rectangle') print(#representationImage) print(center[1] .. '\t' .. center[2] .. '\t' .. rectangleWidth .. '\t' .. rectangleHeight .. '\t' .. lineWidth) ]]-- end end end end return representationImage elseif representationType == 'P' and renderingType == 'L' then local representationImage = torch.ones(#floorplan) local usedPointLineMask = {} local pointOrientations = {} for pointIndex, point in pairs(representation.points) do usedPointLineMask[pointIndex] = {true, true, true, true} local orientations = {} local orientation = point[3][3] if point[3][2] == 1 then table.insert(orientations, (orientation + 2 - 1) % 4 + 1) elseif point[3][2] == 2 then table.insert(orientations, orientation) table.insert(orientations, (orientation + 3 - 1) % 4 + 1) elseif point[3][2] == 3 then for i = 1, 4 do if i ~= orientation then table.insert(orientations, i) end end else for i = 1, 4 do table.insert(orientations, i) end end pointOrientations[pointIndex] = orientations for _, orientation in pairs(orientations) do usedPointLineMask[orientation] = false end end for pointIndex, point in pairs(representation.points) do local orientations = pointOrientations[pointIndex] local x = point[1][1] local y = point[1][2] for _, orientation in pairs(orientations) do if usedPointLineMask[pointIndex][orientation] == false then local min_x, max_x, min_y, max_y if orientation == 1 or orientation == 3 then min_x = x - lineWidth max_x = x - lineWidth if orientation = 1 then min_y = 1 max_y = y else min_y = y max_y = height end else min_y = y - lineWidth max_y = y - lineWidth if orientation = 2 then min_x = x max_x = width else min_x = 1 max_x = x end end local orientationOpposite = (orientation + 2 - 1) % 4 + 1 for otherPointIndex, otherPoint in pairs(representation.points) do if otherPointIndex ~= pointIndex and usedPointLineMask[otherPoint][orientationOpposite] == false then for mode, items in pairs(representation) do if mode == 'points' or mode == 'doors' or mode == 'icons' or mode == 'labels' then for __, item in pairs(items) do local rectangle = utils.imageRectangle(width, height, gridWidth, gridHeight, item) local center = {(rectangle[2][1] + rectangle[1][1]) / 2, (rectangle[2][2] + rectangle[1][2]) / 2} local rectangleWidth = math.max(rectangle[2][1] - rectangle[1][1] + 1, 10) local rectangleHeight = math.max(rectangle[2][2] - rectangle[1][2] + 1, 10) local color = colorMap[item[4][2]] lineWidth = 2 if mode == 'points' then lineWidth = 10 end success, newRepresentationImage = pcall(function() return image.drawRect(representationImage, math.max(center[1] - rectangleWidth / 2, 1), math.max(center[2] - rectangleHeight / 2, 1), math.min(center[1] + rectangleWidth / 2, width), math.min(center[2] + rectangleHeight / 2, height), {lineWidth = lineWidth, color = color}) end) if success then representationImage = newRepresentationImage else --[[ print('Fail to draw rectangle') print(#representationImage) print(center[1] .. '\t' .. center[2] .. '\t' .. rectangleWidth .. '\t' .. rectangleHeight .. '\t' .. lineWidth) ]]-- end end end end return representationImage end end function utils.loadRepresentation(filename) local representationExists, representationInfo = pcall(function() return csvigo.load({path=filename, mode="large", header=false, separator='\t', verbose=false}) end) if representationExists and representationInfo ~= nil then local representation = {} representation.walls = {} representation.doors = {} representation.icons = {} representation.labels = {} local modeMap = utils.modeMap() for _, item in pairs(representationInfo) do local itemMode = modeMap[item[5]] local itemInfo = {{tonumber(item[1]), tonumber(item[2])}, {tonumber(item[3]), tonumber(item[4])}, {item[5], tonumber(item[6]), tonumber(item[7])}} table.insert(representation[itemMode], itemInfo) end return representation else return nil end end function utils.finalizeRepresentation(representation) representation.walls = utils.stitchLines(utils.sortLines(representation.walls), 5) representation.doors = utils.sortLines(representation.doors) return representation end function utils.saveRepresentation(filename, representation) --local representationExists, representationFile = pcall(function() --return io.open(filename, 'r') --end) --local override = false --if representationExists then --end print('save representation') representation = utils.finalizeRepresentation(representation) pl.dir.makepath(filename:match('(.+)/(.+)')) local representationFile = io.open(filename, 'w') for itemMode, items in pairs(representation) do for _, item in pairs(items) do for __, field in pairs(item) do if __ <= 3 then for ___, value in pairs(field) do representationFile:write(value .. '\t') end end end representationFile:write('\n') end end representationFile:close() end --[[ lines = {} table.insert(lines, {{1, 1}, {1, 10}}) table.insert(lines, {{1, 11}, {20, 11}}) print(lines) print(stitchLines(lines, 5)) ]]-- return utils