Version 14.00
This commit is contained in:
+101
-1
@@ -53,22 +53,26 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Header Files", "Header File
|
||||
Src\FEMTree.h = Src\FEMTree.h
|
||||
Src\FunctionData.h = Src\FunctionData.h
|
||||
Src\Geometry.h = Src\Geometry.h
|
||||
Src\GridWriter.h = Src\GridWriter.h
|
||||
Src\Image.h = Src\Image.h
|
||||
Src\JPEG.h = Src\JPEG.h
|
||||
Src\MarchingCubes.h = Src\MarchingCubes.h
|
||||
Src\MAT.h = Src\MAT.h
|
||||
Src\MergePlyClientServer.h = Src\MergePlyClientServer.h
|
||||
Src\MyMiscellany.h = Src\MyMiscellany.h
|
||||
Src\Ply.h = Src\Ply.h
|
||||
Src\PlyFile.h = Src\PlyFile.h
|
||||
Src\PNG.h = Src\PNG.h
|
||||
Src\PointPartition.h = Src\PointPartition.h
|
||||
Src\PointPartitionClientServer.h = Src\PointPartitionClientServer.h
|
||||
Src\PoissonRecon.h = Src\PoissonRecon.h
|
||||
Src\PoissonReconClientServer.h = Src\PoissonReconClientServer.h
|
||||
Src\Polynomial.h = Src\Polynomial.h
|
||||
Src\PPolynomial.h = Src\PPolynomial.h
|
||||
Src\PreProcessor.h = Src\PreProcessor.h
|
||||
Src\Rasterizer.h = Src\Rasterizer.h
|
||||
Src\RegularGrid.h = Src\RegularGrid.h
|
||||
Src\RegularTree.h = Src\RegularTree.h
|
||||
Src\Socket.h = Src\Socket.h
|
||||
Src\SparseMatrix.h = Src\SparseMatrix.h
|
||||
Src\SparseMatrixInterface.h = Src\SparseMatrixInterface.h
|
||||
Src\StreamingMesh.h = Src\StreamingMesh.h
|
||||
@@ -96,14 +100,21 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Inline Files", "Inline File
|
||||
Src\Geometry.inl = Src\Geometry.inl
|
||||
Src\JPEG.inl = Src\JPEG.inl
|
||||
Src\MAT.inl = Src\MAT.inl
|
||||
Src\MergePlyClientServer.inl = Src\MergePlyClientServer.inl
|
||||
Src\Ply.inl = Src\Ply.inl
|
||||
Src\PlyFile.inl = Src\PlyFile.inl
|
||||
Src\PNG.inl = Src\PNG.inl
|
||||
Src\PointPartition.inl = Src\PointPartition.inl
|
||||
Src\PointPartitionClientServer.inl = Src\PointPartitionClientServer.inl
|
||||
Src\PoissonRecon.client.inl = Src\PoissonRecon.client.inl
|
||||
Src\PoissonRecon.server.inl = Src\PoissonRecon.server.inl
|
||||
Src\PoissonReconClientServer.inl = Src\PoissonReconClientServer.inl
|
||||
Src\Polynomial.inl = Src\Polynomial.inl
|
||||
Src\PPolynomial.inl = Src\PPolynomial.inl
|
||||
Src\Rasterizer.inl = Src\Rasterizer.inl
|
||||
Src\RegularGrid.inl = Src\RegularGrid.inl
|
||||
Src\RegularTree.inl = Src\RegularTree.inl
|
||||
Src\Socket.inl = Src\Socket.inl
|
||||
Src\SparseMatrix.inl = Src\SparseMatrix.inl
|
||||
Src\SparseMatrixInterface.inl = Src\SparseMatrixInterface.inl
|
||||
Src\StreamingMesh.inl = Src\StreamingMesh.inl
|
||||
@@ -116,34 +127,123 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ChunkPLY", "ChunkPLY.vcxpro
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PointInterpolant", "PointInterpolant.vcxproj", "{D5516BBE-9613-4AE3-BE4D-E754995F944C}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PoissonReconClient", "PoissonReconClient.vcxproj", "{D9DFEEF0-7F6E-4381-9098-1363F385DEC3}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PoissonReconServer", "PoissonReconServer.vcxproj", "{649D8C83-6BE2-4419-B0A8-66F65CD4D4CB}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{D3D173AB-D306-4179-BEC4-95CE1B14E647}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D3D173AB-D306-4179-BEC4-95CE1B14E647}.Debug|x64.Build.0 = Debug|x64
|
||||
{D3D173AB-D306-4179-BEC4-95CE1B14E647}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{D3D173AB-D306-4179-BEC4-95CE1B14E647}.Debug|x86.Build.0 = Debug|Win32
|
||||
{D3D173AB-D306-4179-BEC4-95CE1B14E647}.Release|x64.ActiveCfg = Release|x64
|
||||
{D3D173AB-D306-4179-BEC4-95CE1B14E647}.Release|x64.Build.0 = Release|x64
|
||||
{D3D173AB-D306-4179-BEC4-95CE1B14E647}.Release|x86.ActiveCfg = Release|Win32
|
||||
{D3D173AB-D306-4179-BEC4-95CE1B14E647}.Release|x86.Build.0 = Release|Win32
|
||||
{477765F8-C16A-406B-807F-1302DAE74EBA}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{477765F8-C16A-406B-807F-1302DAE74EBA}.Debug|x64.Build.0 = Debug|x64
|
||||
{477765F8-C16A-406B-807F-1302DAE74EBA}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{477765F8-C16A-406B-807F-1302DAE74EBA}.Debug|x86.Build.0 = Debug|Win32
|
||||
{477765F8-C16A-406B-807F-1302DAE74EBA}.Release|x64.ActiveCfg = Release|x64
|
||||
{477765F8-C16A-406B-807F-1302DAE74EBA}.Release|x64.Build.0 = Release|x64
|
||||
{477765F8-C16A-406B-807F-1302DAE74EBA}.Release|x86.ActiveCfg = Release|Win32
|
||||
{477765F8-C16A-406B-807F-1302DAE74EBA}.Release|x86.Build.0 = Release|Win32
|
||||
{B5899B32-FAC2-477E-99AA-86736B97F2FC}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{B5899B32-FAC2-477E-99AA-86736B97F2FC}.Debug|x64.Build.0 = Debug|x64
|
||||
{B5899B32-FAC2-477E-99AA-86736B97F2FC}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{B5899B32-FAC2-477E-99AA-86736B97F2FC}.Debug|x86.Build.0 = Debug|Win32
|
||||
{B5899B32-FAC2-477E-99AA-86736B97F2FC}.Release|x64.ActiveCfg = Release|x64
|
||||
{B5899B32-FAC2-477E-99AA-86736B97F2FC}.Release|x64.Build.0 = Release|x64
|
||||
{B5899B32-FAC2-477E-99AA-86736B97F2FC}.Release|x86.ActiveCfg = Release|Win32
|
||||
{B5899B32-FAC2-477E-99AA-86736B97F2FC}.Release|x86.Build.0 = Release|Win32
|
||||
{0BE55595-4080-4265-82AF-51108EC956B2}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{0BE55595-4080-4265-82AF-51108EC956B2}.Debug|x64.Build.0 = Debug|x64
|
||||
{0BE55595-4080-4265-82AF-51108EC956B2}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{0BE55595-4080-4265-82AF-51108EC956B2}.Debug|x86.Build.0 = Debug|Win32
|
||||
{0BE55595-4080-4265-82AF-51108EC956B2}.Release|x64.ActiveCfg = Release|x64
|
||||
{0BE55595-4080-4265-82AF-51108EC956B2}.Release|x64.Build.0 = Release|x64
|
||||
{0BE55595-4080-4265-82AF-51108EC956B2}.Release|x86.ActiveCfg = Release|Win32
|
||||
{0BE55595-4080-4265-82AF-51108EC956B2}.Release|x86.Build.0 = Release|Win32
|
||||
{E09D1615-1036-4F43-909A-2E751FC947F6}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E09D1615-1036-4F43-909A-2E751FC947F6}.Debug|x64.Build.0 = Debug|x64
|
||||
{E09D1615-1036-4F43-909A-2E751FC947F6}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{E09D1615-1036-4F43-909A-2E751FC947F6}.Debug|x86.Build.0 = Debug|Win32
|
||||
{E09D1615-1036-4F43-909A-2E751FC947F6}.Release|x64.ActiveCfg = Release|x64
|
||||
{E09D1615-1036-4F43-909A-2E751FC947F6}.Release|x64.Build.0 = Release|x64
|
||||
{E09D1615-1036-4F43-909A-2E751FC947F6}.Release|x86.ActiveCfg = Release|Win32
|
||||
{E09D1615-1036-4F43-909A-2E751FC947F6}.Release|x86.Build.0 = Release|Win32
|
||||
{3B94F9AD-35E8-4E1E-B176-AAA091E4C3CC}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{3B94F9AD-35E8-4E1E-B176-AAA091E4C3CC}.Debug|x64.Build.0 = Debug|x64
|
||||
{3B94F9AD-35E8-4E1E-B176-AAA091E4C3CC}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{3B94F9AD-35E8-4E1E-B176-AAA091E4C3CC}.Debug|x86.Build.0 = Debug|Win32
|
||||
{3B94F9AD-35E8-4E1E-B176-AAA091E4C3CC}.Release|x64.ActiveCfg = Release|x64
|
||||
{3B94F9AD-35E8-4E1E-B176-AAA091E4C3CC}.Release|x64.Build.0 = Release|x64
|
||||
{3B94F9AD-35E8-4E1E-B176-AAA091E4C3CC}.Release|x64.Deploy.0 = Release|x64
|
||||
{3B94F9AD-35E8-4E1E-B176-AAA091E4C3CC}.Release|x86.ActiveCfg = Release|Win32
|
||||
{3B94F9AD-35E8-4E1E-B176-AAA091E4C3CC}.Release|x86.Build.0 = Release|Win32
|
||||
{99BEAFED-8DB9-4B7D-A0BE-5186158193FE}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{99BEAFED-8DB9-4B7D-A0BE-5186158193FE}.Debug|x64.Build.0 = Debug|x64
|
||||
{99BEAFED-8DB9-4B7D-A0BE-5186158193FE}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{99BEAFED-8DB9-4B7D-A0BE-5186158193FE}.Debug|x86.Build.0 = Debug|Win32
|
||||
{99BEAFED-8DB9-4B7D-A0BE-5186158193FE}.Release|x64.ActiveCfg = Release|x64
|
||||
{99BEAFED-8DB9-4B7D-A0BE-5186158193FE}.Release|x64.Build.0 = Release|x64
|
||||
{99BEAFED-8DB9-4B7D-A0BE-5186158193FE}.Release|x86.ActiveCfg = Release|Win32
|
||||
{99BEAFED-8DB9-4B7D-A0BE-5186158193FE}.Release|x86.Build.0 = Release|Win32
|
||||
{46F87D0E-C53A-4F95-AB48-A5DBA8014340}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{46F87D0E-C53A-4F95-AB48-A5DBA8014340}.Debug|x64.Build.0 = Debug|x64
|
||||
{46F87D0E-C53A-4F95-AB48-A5DBA8014340}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{46F87D0E-C53A-4F95-AB48-A5DBA8014340}.Debug|x86.Build.0 = Debug|Win32
|
||||
{46F87D0E-C53A-4F95-AB48-A5DBA8014340}.Release|x64.ActiveCfg = Release|x64
|
||||
{46F87D0E-C53A-4F95-AB48-A5DBA8014340}.Release|x64.Build.0 = Release|x64
|
||||
{46F87D0E-C53A-4F95-AB48-A5DBA8014340}.Release|x86.ActiveCfg = Release|Win32
|
||||
{46F87D0E-C53A-4F95-AB48-A5DBA8014340}.Release|x86.Build.0 = Release|Win32
|
||||
{742064B3-CEBB-4AF8-B43C-D213EB1C6D7A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{742064B3-CEBB-4AF8-B43C-D213EB1C6D7A}.Debug|x64.Build.0 = Debug|x64
|
||||
{742064B3-CEBB-4AF8-B43C-D213EB1C6D7A}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{742064B3-CEBB-4AF8-B43C-D213EB1C6D7A}.Debug|x86.Build.0 = Debug|Win32
|
||||
{742064B3-CEBB-4AF8-B43C-D213EB1C6D7A}.Release|x64.ActiveCfg = Release|x64
|
||||
{742064B3-CEBB-4AF8-B43C-D213EB1C6D7A}.Release|x64.Build.0 = Release|x64
|
||||
{742064B3-CEBB-4AF8-B43C-D213EB1C6D7A}.Release|x86.ActiveCfg = Release|Win32
|
||||
{742064B3-CEBB-4AF8-B43C-D213EB1C6D7A}.Release|x86.Build.0 = Release|Win32
|
||||
{95B998F8-A73B-40AB-AF35-C38F2CB89480}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{95B998F8-A73B-40AB-AF35-C38F2CB89480}.Debug|x64.Build.0 = Debug|x64
|
||||
{95B998F8-A73B-40AB-AF35-C38F2CB89480}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{95B998F8-A73B-40AB-AF35-C38F2CB89480}.Debug|x86.Build.0 = Debug|Win32
|
||||
{95B998F8-A73B-40AB-AF35-C38F2CB89480}.Release|x64.ActiveCfg = Release|x64
|
||||
{95B998F8-A73B-40AB-AF35-C38F2CB89480}.Release|x64.Build.0 = Release|x64
|
||||
{95B998F8-A73B-40AB-AF35-C38F2CB89480}.Release|x86.ActiveCfg = Release|Win32
|
||||
{95B998F8-A73B-40AB-AF35-C38F2CB89480}.Release|x86.Build.0 = Release|Win32
|
||||
{D5516BBE-9613-4AE3-BE4D-E754995F944C}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D5516BBE-9613-4AE3-BE4D-E754995F944C}.Debug|x64.Build.0 = Debug|x64
|
||||
{D5516BBE-9613-4AE3-BE4D-E754995F944C}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{D5516BBE-9613-4AE3-BE4D-E754995F944C}.Debug|x86.Build.0 = Debug|Win32
|
||||
{D5516BBE-9613-4AE3-BE4D-E754995F944C}.Release|x64.ActiveCfg = Release|x64
|
||||
{D5516BBE-9613-4AE3-BE4D-E754995F944C}.Release|x64.Build.0 = Release|x64
|
||||
{D5516BBE-9613-4AE3-BE4D-E754995F944C}.Release|x86.ActiveCfg = Release|Win32
|
||||
{D5516BBE-9613-4AE3-BE4D-E754995F944C}.Release|x86.Build.0 = Release|Win32
|
||||
{D9DFEEF0-7F6E-4381-9098-1363F385DEC3}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D9DFEEF0-7F6E-4381-9098-1363F385DEC3}.Debug|x64.Build.0 = Debug|x64
|
||||
{D9DFEEF0-7F6E-4381-9098-1363F385DEC3}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{D9DFEEF0-7F6E-4381-9098-1363F385DEC3}.Debug|x86.Build.0 = Debug|Win32
|
||||
{D9DFEEF0-7F6E-4381-9098-1363F385DEC3}.Release|x64.ActiveCfg = Release|x64
|
||||
{D9DFEEF0-7F6E-4381-9098-1363F385DEC3}.Release|x64.Build.0 = Release|x64
|
||||
{D9DFEEF0-7F6E-4381-9098-1363F385DEC3}.Release|x86.ActiveCfg = Release|Win32
|
||||
{D9DFEEF0-7F6E-4381-9098-1363F385DEC3}.Release|x86.Build.0 = Release|Win32
|
||||
{649D8C83-6BE2-4419-B0A8-66F65CD4D4CB}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{649D8C83-6BE2-4419-B0A8-66F65CD4D4CB}.Debug|x64.Build.0 = Debug|x64
|
||||
{649D8C83-6BE2-4419-B0A8-66F65CD4D4CB}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{649D8C83-6BE2-4419-B0A8-66F65CD4D4CB}.Debug|x86.Build.0 = Debug|Win32
|
||||
{649D8C83-6BE2-4419-B0A8-66F65CD4D4CB}.Release|x64.ActiveCfg = Release|x64
|
||||
{649D8C83-6BE2-4419-B0A8-66F65CD4D4CB}.Release|x64.Build.0 = Release|x64
|
||||
{649D8C83-6BE2-4419-B0A8-66F65CD4D4CB}.Release|x86.ActiveCfg = Release|Win32
|
||||
{649D8C83-6BE2-4419-B0A8-66F65CD4D4CB}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
PR_TARGET=PoissonRecon
|
||||
PRC_TARGET=PoissonReconClient
|
||||
PRS_TARGET=PoissonReconServer
|
||||
SR_TARGET=SSDRecon
|
||||
PI_TARGET=PointInterpolant
|
||||
ST_TARGET=SurfaceTrimmer
|
||||
@@ -7,6 +9,8 @@ IS_TARGET=ImageStitching
|
||||
AV_TARGET=AdaptiveTreeVisualization
|
||||
CP_TARGET=ChunkPLY
|
||||
PR_SOURCE=PoissonRecon.cpp
|
||||
PRC_SOURCE=PoissonReconClient.cpp
|
||||
PRS_SOURCE=PoissonReconServer.cpp
|
||||
SR_SOURCE=SSDRecon.cpp
|
||||
PI_SOURCE=PointInterpolant.cpp
|
||||
ST_SOURCE=SurfaceTrimmer.cpp
|
||||
@@ -30,7 +34,7 @@ else
|
||||
CFLAGS += -Wno-deprecated -std=c++17 -pthread -Wno-invalid-offsetof -Wno-dangling-else
|
||||
LFLAGS += -lstdc++
|
||||
endif
|
||||
LFLAGS += -lz -lpng -ljpeg
|
||||
LFLAGS_IMG += -lz -lpng -ljpeg
|
||||
#LFLAGS += -ljpeg -lmypng -lz
|
||||
|
||||
CFLAGS_DEBUG = -DDEBUG -g3
|
||||
@@ -60,6 +64,8 @@ endif
|
||||
MD=mkdir
|
||||
|
||||
PR_OBJECTS=$(addprefix $(BIN), $(addsuffix .o, $(basename $(PR_SOURCE))))
|
||||
PRC_OBJECTS=$(addprefix $(BIN), $(addsuffix .o, $(basename $(PRC_SOURCE))))
|
||||
PRS_OBJECTS=$(addprefix $(BIN), $(addsuffix .o, $(basename $(PRS_SOURCE))))
|
||||
SR_OBJECTS=$(addprefix $(BIN), $(addsuffix .o, $(basename $(SR_SOURCE))))
|
||||
PI_OBJECTS=$(addprefix $(BIN), $(addsuffix .o, $(basename $(PI_SOURCE))))
|
||||
ST_OBJECTS=$(addprefix $(BIN), $(addsuffix .o, $(basename $(ST_SOURCE))))
|
||||
@@ -73,6 +79,8 @@ all: CFLAGS += $(CFLAGS_RELEASE)
|
||||
all: LFLAGS += $(LFLAGS_RELEASE)
|
||||
all: make_dir
|
||||
all: $(BIN)$(PR_TARGET)
|
||||
all: $(BIN)$(PRC_TARGET)
|
||||
all: $(BIN)$(PRS_TARGET)
|
||||
all: $(BIN)$(SR_TARGET)
|
||||
all: $(BIN)$(PI_TARGET)
|
||||
all: $(BIN)$(ST_TARGET)
|
||||
@@ -85,6 +93,8 @@ debug: CFLAGS += $(CFLAGS_DEBUG)
|
||||
debug: LFLAGS += $(LFLAGS_DEBUG)
|
||||
debug: make_dir
|
||||
debug: $(BIN)$(PR_TARGET)
|
||||
debug: $(BIN)$(PRC_TARGET)
|
||||
debug: $(BIN)$(PRS_TARGET)
|
||||
debug: $(BIN)$(SR_TARGET)
|
||||
debug: $(BIN)$(PI_TARGET)
|
||||
debug: $(BIN)$(ST_TARGET)
|
||||
@@ -98,6 +108,16 @@ poissonrecon: LFLAGS += $(LFLAGS_RELEASE)
|
||||
poissonrecon: make_dir
|
||||
poissonrecon: $(BIN)$(PR_TARGET)
|
||||
|
||||
poissonreconclient: CFLAGS += $(CFLAGS_RELEASE)
|
||||
poissonreconclient: LFLAGS += $(LFLAGS_RELEASE)
|
||||
poissonreconclient: make_dir
|
||||
poissonreconclient: $(BIN)$(PRC_TARGET)
|
||||
|
||||
poissonreconserver: CFLAGS += $(CFLAGS_RELEASE)
|
||||
poissonreconserver: LFLAGS += $(LFLAGS_RELEASE)
|
||||
poissonreconserver: make_dir
|
||||
poissonreconserver: $(BIN)$(PRS_TARGET)
|
||||
|
||||
ssdrecon: CFLAGS += $(CFLAGS_RELEASE)
|
||||
ssdrecon: LFLAGS += $(LFLAGS_RELEASE)
|
||||
ssdrecon: make_dir
|
||||
@@ -135,6 +155,8 @@ chunkply: $(BIN)$(CP_TARGET)
|
||||
|
||||
clean:
|
||||
rm -rf $(BIN)$(PR_TARGET)
|
||||
rm -rf $(BIN)$(PRC_TARGET)
|
||||
rm -rf $(BIN)$(PRS_TARGET)
|
||||
rm -rf $(BIN)$(SR_TARGET)
|
||||
rm -rf $(BIN)$(PI_TARGET)
|
||||
rm -rf $(BIN)$(ST_TARGET)
|
||||
@@ -143,6 +165,8 @@ clean:
|
||||
rm -rf $(BIN)$(AV_TARGET)
|
||||
rm -rf $(BIN)$(CP_TARGET)
|
||||
rm -rf $(PR_OBJECTS)
|
||||
rm -rf $(PRC_OBJECTS)
|
||||
rm -rf $(PRS_OBJECTS)
|
||||
rm -rf $(SR_OBJECTS)
|
||||
rm -rf $(PI_OBJECTS)
|
||||
rm -rf $(ST_OBJECTS)
|
||||
@@ -158,15 +182,21 @@ make_dir:
|
||||
|
||||
$(BIN)$(PR_TARGET): $(PR_OBJECTS)
|
||||
cd PNG && make COMPILER=$(COMPILER)
|
||||
$(CXX) -pthread -o $@ $(PR_OBJECTS) -L$(BIN) $(LFLAGS)
|
||||
$(CXX) -pthread -o $@ $(PR_OBJECTS) -L$(BIN) $(LFLAGS) $(LFLAGS_IMG)
|
||||
|
||||
$(BIN)$(PRC_TARGET): $(PRC_OBJECTS)
|
||||
$(CXX) -pthread -o $@ $(PRC_OBJECTS) -L$(BIN) -lboost_system $(LFLAGS)
|
||||
|
||||
$(BIN)$(PRS_TARGET): $(PRS_OBJECTS)
|
||||
$(CXX) -pthread -o $@ $(PRS_OBJECTS) -L$(BIN) -lboost_system $(LFLAGS)
|
||||
|
||||
$(BIN)$(SR_TARGET): $(SR_OBJECTS)
|
||||
cd PNG && make COMPILER=$(COMPILER)
|
||||
$(CXX) -pthread -o $@ $(SR_OBJECTS) -L$(BIN) $(LFLAGS)
|
||||
$(CXX) -pthread -o $@ $(SR_OBJECTS) -L$(BIN) $(LFLAGS) $(LFLAGS_IMG)
|
||||
|
||||
$(BIN)$(PI_TARGET): $(PI_OBJECTS)
|
||||
cd PNG && make COMPILER=$(COMPILER)
|
||||
$(CXX) -pthread -o $@ $(PI_OBJECTS) -L$(BIN) $(LFLAGS)
|
||||
$(CXX) -pthread -o $@ $(PI_OBJECTS) -L$(BIN) $(LFLAGS) $(LFLAGS_IMG)
|
||||
|
||||
$(BIN)$(ST_TARGET): $(ST_OBJECTS)
|
||||
$(CXX) -pthread -o $@ $(ST_OBJECTS) $(LFLAGS)
|
||||
@@ -176,15 +206,15 @@ $(BIN)$(EH_TARGET): $(EH_OBJECTS)
|
||||
|
||||
$(BIN)$(IS_TARGET): $(IS_OBJECTS)
|
||||
cd PNG && make COMPILER=$(COMPILER)
|
||||
$(CXX) -pthread -o $@ $(IS_OBJECTS) -L$(BIN) $(LFLAGS)
|
||||
$(CXX) -pthread -o $@ $(IS_OBJECTS) -L$(BIN) $(LFLAGS) $(LFLAGS_IMG)
|
||||
|
||||
$(BIN)$(AV_TARGET): $(AV_OBJECTS)
|
||||
cd PNG && make COMPILER=$(COMPILER)
|
||||
$(CXX) -pthread -o $@ $(AV_OBJECTS) -L$(BIN) $(LFLAGS)
|
||||
$(CXX) -pthread -o $@ $(AV_OBJECTS) -L$(BIN) $(LFLAGS) $(LFLAGS_IMG)
|
||||
|
||||
$(BIN)$(CP_TARGET): $(CP_OBJECTS)
|
||||
cd PNG && make COMPILER=$(COMPILER)
|
||||
$(CXX) -pthread -o $@ $(CP_OBJECTS) -L$(BIN) $(LFLAGS)
|
||||
$(CXX) -pthread -o $@ $(CP_OBJECTS) -L$(BIN) $(LFLAGS) $(LFLAGS_IMG)
|
||||
|
||||
$(BIN)%.o: $(SRC)%.c
|
||||
$(CC) -c -o $@ -I$(INCLUDE) $<
|
||||
|
||||
-176
@@ -1,176 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="png.c" />
|
||||
<ClCompile Include="pngerror.c" />
|
||||
<ClCompile Include="pnggccrd.c" />
|
||||
<ClCompile Include="pngget.c" />
|
||||
<ClCompile Include="pngmem.c" />
|
||||
<ClCompile Include="pngpread.c" />
|
||||
<ClCompile Include="pngread.c" />
|
||||
<ClCompile Include="pngrio.c" />
|
||||
<ClCompile Include="pngrtran.c" />
|
||||
<ClCompile Include="pngrutil.c" />
|
||||
<ClCompile Include="pngset.c" />
|
||||
<ClCompile Include="pngtest.c" />
|
||||
<ClCompile Include="pngtrans.c" />
|
||||
<ClCompile Include="pngvcrd.c" />
|
||||
<ClCompile Include="pngwio.c" />
|
||||
<ClCompile Include="pngwrite.c" />
|
||||
<ClCompile Include="pngwtran.c" />
|
||||
<ClCompile Include="pngwutil.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="png.h" />
|
||||
<ClInclude Include="pngasmrd.h" />
|
||||
<ClInclude Include="pngconf.h" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{B5899B32-FAC2-477E-99AA-86736B97F2FC}</ProjectGuid>
|
||||
<RootNamespace>PNG</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)Intermediate\$(ProjectName)\$(Configuration)\</IntDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)\Bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)\Obj\$(TargetName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)\Bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)\Obj\$(TargetName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,84 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="png.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pngerror.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pnggccrd.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pngget.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pngmem.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pngpread.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pngread.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pngrio.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pngrtran.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pngrutil.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pngset.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pngtest.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pngtrans.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pngvcrd.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pngwio.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pngwrite.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pngwtran.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pngwutil.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="png.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="pngasmrd.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="pngconf.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,171 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Src\PoissonReconClient.cpp" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{D9DFEEF0-7F6E-4381-9098-1363F385DEC3}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>MultiPoissonRecon</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)\Bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)\Obj\$(TargetName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NOMINMAX;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>false</ConformanceMode>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
|
||||
<OpenMPSupport>true</OpenMPSupport>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>C:\Research\Libraries\</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(OutDir)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>ZLIB.lib;JPEG.lib;PNG.lib;psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NOMINMAX;WIN32;_CRT_SECURE_NO_DEPRECATE;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<AdditionalIncludeDirectories>C:\Research\Libraries\</AdditionalIncludeDirectories>
|
||||
<OpenMPSupport>true</OpenMPSupport>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,171 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Src\PoissonReconServer.cpp" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{649D8C83-6BE2-4419-B0A8-66F65CD4D4CB}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>MultiPoissonRecon</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)\Bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)\Obj\$(TargetName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NOMINMAX;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>false</ConformanceMode>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
|
||||
<OpenMPSupport>true</OpenMPSupport>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>C:\Research\Libraries\</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(OutDir)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>ZLIB.lib;JPEG.lib;PNG.lib;psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<OpenMPSupport>true</OpenMPSupport>
|
||||
<AdditionalIncludeDirectories>C:\Research\Libraries\</AdditionalIncludeDirectories>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
|
||||
Copyright (c) 2022, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
|
||||
Copyright (c) 2022, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -1838,7 +1838,9 @@ public:
|
||||
unsigned int maxDepth = std::max< unsigned int >( tree._maxDepth , slabDepth );
|
||||
unsigned int slabStartAtMaxDepth = slabStart << ( maxDepth - slabDepth );
|
||||
unsigned int slabEndAtMaxDepth = slabEnd << ( maxDepth - slabDepth );
|
||||
#ifdef SHOW_WARNINGS
|
||||
if( slabDepth>(unsigned int)fullDepth && ( ( slabStart!=0 && !backBoundary ) || ( slabEnd+1!=1<<(slabDepth) && !frontBoundary ) ) ) WARN( "Slab depth exceeds full depth, reconstruction may not be water-tight: " , slabDepth , " <= " , fullDepth , " [ " , slabStart , " , " , slabEnd , " )" );
|
||||
#endif // SHOW_WARNINGS
|
||||
|
||||
_BadRootCount = 0u;
|
||||
Stats stats;
|
||||
|
||||
@@ -26,7 +26,6 @@ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF S
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
#include "PreProcessor.h"
|
||||
#include "MarchingCubes.h"
|
||||
|
||||
// Level-set extraction data
|
||||
|
||||
@@ -256,7 +256,9 @@ void FEMTree< Dim , Real >::slice( const FEMTree< Dim+1 , Real > &tree , unsigne
|
||||
#endif // __GNUC__
|
||||
{
|
||||
double eps = 1e-4/(1<<depth);
|
||||
#ifdef SHOW_WARNINGS
|
||||
WARN_ONCE( "Using discrete derivative: " , eps );
|
||||
#endif // SHOW_WARNINGS
|
||||
// If we are dealing with a degree-zero polynomial, we offset
|
||||
if( d==0 )
|
||||
{
|
||||
|
||||
+28
@@ -1,3 +1,31 @@
|
||||
/*
|
||||
Copyright (c) 2010, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer. Redistributions in binary form must reproduce
|
||||
the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Johns Hopkins University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_INCLUDED
|
||||
#define IMAGE_INCLUDED
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF S
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
#define BIG_DATA
|
||||
#include "PreProcessor.h"
|
||||
|
||||
#undef USE_DOUBLE
|
||||
|
||||
+28
@@ -1,3 +1,31 @@
|
||||
/*
|
||||
Copyright (c) 2010, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer. Redistributions in binary form must reproduce
|
||||
the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Johns Hopkins University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef JPEG_INCLUDED
|
||||
#define JPEG_INCLUDED
|
||||
#include "Image.h"
|
||||
|
||||
@@ -1,3 +1,31 @@
|
||||
/*
|
||||
Copyright (c) 2010, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer. Redistributions in binary form must reproduce
|
||||
the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Johns Hopkins University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
Copyright (c) 2023, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer. Redistributions in binary form must reproduce
|
||||
the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Johns Hopkins University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MERGE_PLY_CLIENT_SERVER_INCLUDED
|
||||
#define MERGE_PLY_CLIENT_SERVER_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include "Socket.h"
|
||||
#include "MyMiscellany.h"
|
||||
#include "CmdLineParser.h"
|
||||
|
||||
|
||||
namespace MergePlyClientServer
|
||||
{
|
||||
struct ClientMergePlyInfo
|
||||
{
|
||||
std::vector< PlyProperty > auxProperties;
|
||||
size_t bufferSize;
|
||||
bool verbose;
|
||||
|
||||
ClientMergePlyInfo( void );
|
||||
ClientMergePlyInfo( BinaryStream &stream );
|
||||
|
||||
void write( BinaryStream &stream ) const;
|
||||
};
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
void RunServer
|
||||
(
|
||||
std::string inDir ,
|
||||
std::string tempDir ,
|
||||
std::string header ,
|
||||
std::string out ,
|
||||
std::vector< Socket > &clientSockets ,
|
||||
const std::vector< unsigned int > &sharedVertexCounts ,
|
||||
ClientMergePlyInfo clientMergePlyInfo ,
|
||||
unsigned int sampleMS
|
||||
);
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
void RunClients( std::vector< Socket > &serverSockets , unsigned int sampleMS );
|
||||
|
||||
#include "MergePlyClientServer.inl"
|
||||
}
|
||||
|
||||
#endif // MERGE_PLY_CLIENT_SERVER_INCLUDED
|
||||
@@ -0,0 +1,530 @@
|
||||
/*
|
||||
Copyright (c) 2023, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer. Redistributions in binary form must reproduce
|
||||
the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Johns Hopkins University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
enum _IndexType{ INT , U_INT , LONG_LONG };
|
||||
|
||||
inline std::string _FullFileName( std::string dir , std::string fileName )
|
||||
{
|
||||
if( dir.back()!=FileSeparator ) dir += std::string(1,FileSeparator);
|
||||
return dir + fileName;
|
||||
}
|
||||
|
||||
inline void _Copy( FILE *target , FILE *source , size_t sz , size_t bufferSize=1<<20 )
|
||||
{
|
||||
Pointer( unsigned char ) buffer = NewPointer< unsigned char >( bufferSize );
|
||||
if( sz==-1 )
|
||||
{
|
||||
size_t ioBytes;
|
||||
while( ioBytes=fread( buffer , sizeof(unsigned char) , bufferSize , source ) ) fwrite( buffer , sizeof(unsigned char) , ioBytes , target );
|
||||
}
|
||||
else
|
||||
{
|
||||
while( sz )
|
||||
{
|
||||
size_t ioBytes = std::min< size_t >( bufferSize , sz );
|
||||
if( ioBytes!=fread( buffer , sizeof(unsigned char) , ioBytes , source ) ) ERROR_OUT( "Failed to read from source: " , ioBytes );
|
||||
if( ioBytes!=fwrite( buffer , sizeof(unsigned char) , ioBytes , target ) ) ERROR_OUT( "Failed to write to target: " , ioBytes );
|
||||
sz -= ioBytes;
|
||||
}
|
||||
}
|
||||
DeletePointer( buffer );
|
||||
}
|
||||
|
||||
template< typename Index , typename Factory >
|
||||
void _OffsetPolygons( const Factory &factory , std::string in , std::string out , size_t offset , Profiler &profiler )
|
||||
{
|
||||
#if 1
|
||||
// PlyProperty faceProperty( "vertex_indices" , PLY::DefaultFileType< Index >() , PLY::DefaultFileType< Index >() , sizeof(int) , 1 , PLY::DefaultFileType< int >() , PLY::DefaultFileType< int >() , 0 );
|
||||
|
||||
int ft;
|
||||
std::vector< std::string > comments;
|
||||
|
||||
std::vector< std::tuple< std::string , size_t , std::vector< PlyProperty > > > _elems;
|
||||
PlyFile *inPly = PLY::ReadHeader( in , ft , _elems );
|
||||
|
||||
size_t sizeOnDisk = 0;
|
||||
if( factory.isStaticallyAllocated() )
|
||||
for( unsigned int i=0 ; i<factory.plyWriteNum() ; i++ ) sizeOnDisk += ply_type_size[ factory.plyStaticWriteProperty(i).external_type ];
|
||||
else
|
||||
for( unsigned int i=0 ; i<factory.plyWriteNum() ; i++ ) sizeOnDisk += ply_type_size[ factory.plyWriteProperty(i).external_type ];
|
||||
|
||||
// Skip the vertices
|
||||
{
|
||||
#if defined( _WIN32 ) || defined( _WIN64 )
|
||||
_fseeki64( inPly->fp , sizeOnDisk * std::get<1>( _elems[0] ) , SEEK_CUR );
|
||||
#else // !_WIN32 && !_WIN64
|
||||
fseek( inPly->fp , sizeOnDisk * std::get<1>( _elems[0] ) , SEEK_CUR );
|
||||
#endif // _WIN32 || _WIN64
|
||||
}
|
||||
|
||||
std::vector< std::tuple< std::string , size_t , std::vector< PlyProperty > > > elems(1);
|
||||
std::get<0>( elems[0] ) = std::string( "face" );
|
||||
std::get<1>( elems[0] ) = std::get<1>( _elems[1] );
|
||||
std::get<2>( elems[0] ).resize(1);
|
||||
std::get<2>( elems[0] )[0] = PLY::Face< Index >::Properties[0];
|
||||
|
||||
PlyFile *outPly = PLY::WriteHeader( out , ft , elems , comments );
|
||||
|
||||
// Read and offset the polygons
|
||||
{
|
||||
int maxIndices = 64;
|
||||
Index *faceIndices = (Index*)malloc( sizeof(Index) * maxIndices );
|
||||
|
||||
auto ReadPolygon = [&]( FILE *fp )
|
||||
{
|
||||
int n;
|
||||
if( fread( &n , sizeof(int) , 1 , fp )!=1 ) ERROR_OUT( "Failed to read polygon size" );
|
||||
if( n>maxIndices )
|
||||
{
|
||||
maxIndices = n;
|
||||
faceIndices = (Index*)realloc( faceIndices , sizeof(Index) * maxIndices );
|
||||
}
|
||||
if( fread( faceIndices , sizeof(Index) , n , fp )!=n ) ERROR_OUT( "Failed to read polygon indices" );
|
||||
return n;
|
||||
};
|
||||
|
||||
auto WritePolygon = [&]( FILE *fp , int n )
|
||||
{
|
||||
fwrite( &n , sizeof(int) , 1 , fp );
|
||||
fwrite( faceIndices , sizeof(Index) , n , fp );
|
||||
};
|
||||
|
||||
for( unsigned int j=0 ; j<std::get<2>( _elems[1] ).size() ; j++ ) inPly->get_property( std::get<0>( _elems[1] ) , &std::get<2>( _elems[1] )[j] );
|
||||
outPly->put_element_setup( std::string( "face" ) );
|
||||
|
||||
for( size_t i=0 ; i<std::get<1>( _elems[1] ) ; i++ )
|
||||
{
|
||||
int n = ReadPolygon( inPly->fp );
|
||||
for( int j=0 ; j<n ; j++ ) faceIndices[j] += (Index)offset;
|
||||
WritePolygon( outPly->fp , n );
|
||||
}
|
||||
|
||||
profiler.update();
|
||||
|
||||
delete[] faceIndices;
|
||||
}
|
||||
delete inPly;
|
||||
delete outPly;
|
||||
#else
|
||||
typedef typename Factory::VertexType Vertex;
|
||||
std::vector< Vertex > vertices;
|
||||
std::vector< std::vector< Index > > polygons;
|
||||
|
||||
int ft;
|
||||
std::vector< std::string > comments;
|
||||
|
||||
PLY::ReadPolygons< Factory , Index >( in , factory , vertices , polygons , ft , comments );
|
||||
std::vector< std::tuple< std::string , size_t , std::vector< PlyProperty > > > elems(1);
|
||||
std::get<0>( elems[0] ) = std::string( "face" );
|
||||
std::get<1>( elems[0] ) = polygons.size();
|
||||
std::get<2>( elems[0] ).resize(1);
|
||||
std::get<2>( elems[0] )[0] = PLY::Face< Index >::Properties[0];
|
||||
|
||||
PlyFile *ply = PLY::WriteHeader( out , ft , elems , comments );
|
||||
|
||||
{
|
||||
PLY::Face< Index > face;
|
||||
unsigned int maxFaceVerts=3;
|
||||
face.nr_vertices = 3;
|
||||
face.vertices = new Index[ face.nr_vertices ];
|
||||
|
||||
ply->put_element_setup( std::string( "face" ) );
|
||||
for( size_t i=0 ; i<polygons.size() ; i++ )
|
||||
{
|
||||
if( polygons[i].size()>maxFaceVerts )
|
||||
{
|
||||
delete[] face.vertices;
|
||||
maxFaceVerts = (unsigned int)polygons[i].size();
|
||||
face.vertices=new Index[ maxFaceVerts ];
|
||||
}
|
||||
face.nr_vertices = (unsigned int)polygons[i].size();
|
||||
for( size_t j=0 ; j<face.nr_vertices ; j++ ) face.vertices[j] = (Index)(polygons[i][j] + offset);
|
||||
ply->put_element( (void *)&face );
|
||||
}
|
||||
|
||||
profiler.update();
|
||||
|
||||
delete[] face.vertices;
|
||||
}
|
||||
delete ply;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////
|
||||
// Server //
|
||||
////////////
|
||||
|
||||
template< typename Real , unsigned int Dim , typename Factory >
|
||||
void _RunServer
|
||||
(
|
||||
std::string inDir ,
|
||||
std::string tempDir ,
|
||||
std::string header ,
|
||||
std::string out ,
|
||||
std::vector< Socket > &clientSockets ,
|
||||
const std::vector< unsigned int > &sharedVertexCounts ,
|
||||
ClientMergePlyInfo clientMergePlyInfo ,
|
||||
const Factory &factory ,
|
||||
unsigned int sampleMS
|
||||
)
|
||||
{
|
||||
Profiler profiler(sampleMS);
|
||||
typedef typename Factory::VertexType Vertex;
|
||||
|
||||
auto ClientFile = []( std::string dir , std::string header , unsigned int idx )
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << _FullFileName( dir , header ) << "." << idx << ".ply";
|
||||
return ss.str();
|
||||
};
|
||||
|
||||
auto InFile = [&]( unsigned int idx ){ return ClientFile( inDir , header , idx ); };
|
||||
auto TempPolygonFile = [&]( unsigned int idx ){ return ClientFile( tempDir , header + std::string( ".polygons" ) , idx ); };
|
||||
|
||||
profiler.reset();
|
||||
|
||||
// Get the number of vertices and polygons per file
|
||||
std::vector< size_t > vNum( sharedVertexCounts.size()+1 ) , fNum( sharedVertexCounts.size()+1 ) , offsets( sharedVertexCounts.size()+1 );
|
||||
{
|
||||
for( unsigned int i=0 ; i<=sharedVertexCounts.size() ; i++ )
|
||||
{
|
||||
std::string inFile = InFile(i);
|
||||
int ft;
|
||||
std::vector< std::tuple< std::string , size_t , std::vector< PlyProperty > > > elems;
|
||||
PlyFile *ply = PLY::ReadHeader( inFile , ft , elems );
|
||||
delete ply;
|
||||
bool foundVertices = false , foundFaces = false;
|
||||
for( unsigned int j=0 ; j<elems.size() ; j++ )
|
||||
if ( std::get<0>( elems[j] )==std::string( "vertex" ) ) foundVertices = true , vNum[i] = std::get<1>( elems[j] );
|
||||
else if( std::get<0>( elems[j] )==std::string( "face" ) ) foundFaces = true , fNum[i] = std::get<1>( elems[j] );
|
||||
if( !foundVertices ) ERROR_OUT( "Could not find vertices" );
|
||||
if( !foundFaces ) ERROR_OUT( "Could not find faces" );
|
||||
profiler.update();
|
||||
}
|
||||
offsets[0] = 0;
|
||||
for( unsigned int i=1 ; i<=sharedVertexCounts.size() ; i++ ) offsets[i] = offsets[i-1] + vNum[i-1] - sharedVertexCounts[i-1];
|
||||
}
|
||||
|
||||
// Strip out the polygons (though perhaps we should just have the reconstruction code do this).
|
||||
#ifdef SHOW_WARNINGS
|
||||
WARN( "Should split the mesh during reconstruction" );
|
||||
#endif // SHOW_WARNINGS
|
||||
|
||||
_IndexType idxType;
|
||||
if( offsets.back()+vNum.back()>std::numeric_limits< int >::max() )
|
||||
{
|
||||
if( offsets.back()+vNum.back()>std::numeric_limits< unsigned int >::max () ) idxType = LONG_LONG;
|
||||
else idxType = U_INT;
|
||||
}
|
||||
else idxType = INT;
|
||||
|
||||
if( clientMergePlyInfo.verbose ) std::cout << "Got mesh info: " << profiler(true) << std::endl;
|
||||
|
||||
|
||||
for( unsigned int i=0 ; i<clientSockets.size() ; i++ )
|
||||
{
|
||||
SocketStream clientStream( clientSockets[i] );
|
||||
clientStream.write( InFile(i) );
|
||||
clientStream.write( TempPolygonFile(i) );
|
||||
clientStream.write( idxType );
|
||||
clientStream.write( offsets[i] );
|
||||
|
||||
}
|
||||
for( unsigned int i=0 ; i<clientSockets.size() ; i++ )
|
||||
{
|
||||
unsigned char done;
|
||||
SocketStream clientStream( clientSockets[i] );
|
||||
clientStream.read( done );
|
||||
}
|
||||
|
||||
profiler.reset();
|
||||
std::vector< std::tuple< std::string , size_t , std::vector< PlyProperty > > > elems(2);
|
||||
{
|
||||
std::get<0>( elems[0] ) = std::string( "vertex" );
|
||||
std::get<1>( elems[0] ) = 0;
|
||||
for( unsigned int i=0 ; i<vNum.size() ; i++ ) std::get<1>( elems[0] ) += vNum[i];
|
||||
for( unsigned int i=0 ; i<sharedVertexCounts.size() ; i++ ) std::get<1>( elems[0] ) -= sharedVertexCounts[i];
|
||||
std::get<2>( elems[0] ).resize( factory.plyWriteNum() );
|
||||
for( unsigned int i=0 ; i<factory.plyWriteNum() ; i++ ) std::get<2>( elems[0] )[i] = factory.isStaticallyAllocated() ? factory.plyStaticWriteProperty(i) : factory.plyWriteProperty(i);
|
||||
|
||||
std::get<0>( elems[1] ) = std::string( "face" );
|
||||
std::get<1>( elems[1] ) = 0;
|
||||
for( unsigned int i=0 ; i<fNum.size() ; i++ ) std::get<1>( elems[1] ) += fNum[i];
|
||||
std::get<2>( elems[1] ).resize(1);
|
||||
switch( idxType )
|
||||
{
|
||||
case INT: std::get<2>( elems[1] )[0] = PLY::Face< int >::Properties[0] ; break;
|
||||
case U_INT: std::get<2>( elems[1] )[0] = PLY::Face< unsigned int >::Properties[0] ; break;
|
||||
case LONG_LONG: std::get<2>( elems[1] )[0] = PLY::Face< long long >::Properties[0] ; break;
|
||||
default: ERROR_OUT( "Unrecognized output type" );
|
||||
}
|
||||
}
|
||||
PlyFile *outPly = PLY::WriteHeader( out , PLY_BINARY_NATIVE , elems );
|
||||
|
||||
// Write out the (merged) vertices
|
||||
{
|
||||
Pointer( char ) vBuffer = NewPointer< char >( factory.bufferSize() );
|
||||
|
||||
outPly->put_element_setup( std::string( "vertex" ) );
|
||||
|
||||
size_t sizeOnDisk = 0;
|
||||
if( factory.isStaticallyAllocated() )
|
||||
for( unsigned int i=0 ; i<factory.plyWriteNum() ; i++ ) sizeOnDisk += ply_type_size[ factory.plyStaticWriteProperty(i).external_type ];
|
||||
else
|
||||
for( unsigned int i=0 ; i<factory.plyWriteNum() ; i++ ) sizeOnDisk += ply_type_size[ factory.plyWriteProperty(i).external_type ];
|
||||
|
||||
std::vector< Vertex > sharedVertices;
|
||||
for( unsigned int i=0 ; i<=sharedVertexCounts.size() ; i++ )
|
||||
{
|
||||
std::vector< std::tuple< std::string , size_t , std::vector< PlyProperty > > > _elems;
|
||||
int ft;
|
||||
PlyFile *inPly = PLY::ReadHeader( InFile(i) , ft , _elems );
|
||||
|
||||
for( unsigned int j=0 ; j<std::get<2>( elems[0] ).size() ; j++ ) inPly->get_property( std::get<0>( elems[0] ) , &std::get<2>( elems[0] )[j] );
|
||||
|
||||
// Merge the start vertices
|
||||
Vertex v = factory();
|
||||
for( unsigned int j=0 ; j<sharedVertices.size() ; j++ )
|
||||
{
|
||||
if( factory.isStaticallyAllocated() )
|
||||
{
|
||||
inPly->get_element( &v );
|
||||
sharedVertices[j] = ( sharedVertices[j] + v ) / (Real)2.;
|
||||
outPly->put_element( (void*)&sharedVertices[j] );
|
||||
}
|
||||
else
|
||||
{
|
||||
inPly->get_element( PointerAddress( vBuffer ) );
|
||||
factory.fromBuffer( vBuffer , v );
|
||||
sharedVertices[j] = ( sharedVertices[j] + v ) / (Real)2.;
|
||||
factory.toBuffer( sharedVertices[j] , vBuffer );
|
||||
outPly->put_element( PointerAddress( vBuffer ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the interior vertices
|
||||
{
|
||||
size_t vNum = std::get<1>( _elems[0] ) - sharedVertices.size();
|
||||
if( i<sharedVertexCounts.size() ) vNum -= sharedVertexCounts[i];
|
||||
_Copy( outPly->fp , inPly->fp , vNum*sizeOnDisk , clientMergePlyInfo.bufferSize );
|
||||
}
|
||||
|
||||
// Buffer the end vertices
|
||||
if( i<sharedVertexCounts.size() )
|
||||
{
|
||||
sharedVertices.resize( sharedVertexCounts[i] , factory() );
|
||||
|
||||
for( unsigned int j=0 ; j<sharedVertices.size() ; j++ )
|
||||
{
|
||||
if( factory.isStaticallyAllocated() ) inPly->get_element( (void*)&sharedVertices[j] );
|
||||
else
|
||||
{
|
||||
inPly->get_element( PointerAddress( vBuffer ) );
|
||||
factory.fromBuffer( vBuffer , sharedVertices[j] );
|
||||
}
|
||||
}
|
||||
}
|
||||
profiler.update();
|
||||
|
||||
delete inPly;
|
||||
}
|
||||
DeletePointer( vBuffer );
|
||||
if( clientMergePlyInfo.verbose ) std::cout << "Merged vertices: " << profiler(true) << std::endl;
|
||||
}
|
||||
|
||||
profiler.reset();
|
||||
// Write out the polygons
|
||||
{
|
||||
outPly->put_element_setup( std::string( "face" ) );
|
||||
for( unsigned int i=0 ; i<=sharedVertexCounts.size() ; i++ )
|
||||
{
|
||||
std::vector< std::tuple< std::string , size_t , std::vector< PlyProperty > > > _elems;
|
||||
int ft;
|
||||
PlyFile *inPly = PLY::ReadHeader( TempPolygonFile(i) , ft , _elems );
|
||||
|
||||
_Copy( outPly->fp , inPly->fp , -1 , clientMergePlyInfo.bufferSize );
|
||||
profiler.update();
|
||||
delete inPly;
|
||||
}
|
||||
if( clientMergePlyInfo.verbose ) std::cout << "Merged polygons: " << profiler(true) << std::endl;
|
||||
}
|
||||
delete outPly;
|
||||
|
||||
for( unsigned int i=0 ; i<=sharedVertexCounts.size() ; i++ )
|
||||
{
|
||||
std::string fileName = TempPolygonFile(i);
|
||||
std::remove( fileName.c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
void RunServer
|
||||
(
|
||||
std::string inDir ,
|
||||
std::string tempDir ,
|
||||
std::string header ,
|
||||
std::string out ,
|
||||
std::vector< Socket > &clientSockets ,
|
||||
const std::vector< unsigned int > &sharedVertexCounts ,
|
||||
ClientMergePlyInfo clientMergePlyInfo ,
|
||||
unsigned int sampleMS
|
||||
)
|
||||
{
|
||||
if( clientSockets.size()!=sharedVertexCounts.size()+1 ) ERROR_OUT( "Socket num and shared vertex count don't match: " , clientSockets.size() , " / " , sharedVertexCounts.size() );
|
||||
|
||||
for( unsigned int i=0 ; i<clientSockets.size() ; i++ )
|
||||
{
|
||||
SocketStream clientStream( clientSockets[i] );
|
||||
clientMergePlyInfo.write( clientStream );
|
||||
}
|
||||
|
||||
if( clientMergePlyInfo.auxProperties.size() )
|
||||
{
|
||||
typedef VertexFactory::Factory< Real , VertexFactory::PositionFactory< Real , Dim > , VertexFactory::DynamicFactory< Real > > Factory;
|
||||
VertexFactory::PositionFactory< Real , Dim > vFactory;
|
||||
VertexFactory::DynamicFactory< Real > dFactory( clientMergePlyInfo.auxProperties );
|
||||
Factory factory( vFactory , dFactory );
|
||||
_RunServer< Real , Dim >( inDir , tempDir , header , out , clientSockets , sharedVertexCounts , clientMergePlyInfo , factory , sampleMS );
|
||||
}
|
||||
else
|
||||
{
|
||||
typedef VertexFactory::Factory< Real , VertexFactory::PositionFactory< Real , Dim > > Factory;
|
||||
Factory factory;
|
||||
_RunServer< Real , Dim >( inDir , tempDir , header , out , clientSockets , sharedVertexCounts , clientMergePlyInfo , factory , sampleMS );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
////////////
|
||||
// Client //
|
||||
////////////
|
||||
template< typename Real , unsigned int Dim , typename Factory >
|
||||
void _RunClients
|
||||
(
|
||||
ClientMergePlyInfo clientMergePlyInfo ,
|
||||
const Factory &factory ,
|
||||
std::vector< Socket > &serverSockets ,
|
||||
unsigned int sampleMS
|
||||
)
|
||||
{
|
||||
Profiler profiler( sampleMS );
|
||||
|
||||
for( unsigned int c=0 ; c<serverSockets.size() ; c++ )
|
||||
{
|
||||
SocketStream socketStream( serverSockets[c] );
|
||||
std::string in , out;
|
||||
_IndexType idxType;
|
||||
size_t offset;
|
||||
socketStream.read( in );
|
||||
socketStream.read( out );
|
||||
socketStream.read( idxType );
|
||||
socketStream.read( offset );
|
||||
|
||||
switch( idxType )
|
||||
{
|
||||
case INT: _OffsetPolygons< int >( factory , in , out , offset , profiler ) ; break;
|
||||
case U_INT: _OffsetPolygons< unsigned int >( factory , in , out , offset , profiler ) ; break;
|
||||
case LONG_LONG: _OffsetPolygons< long long >( factory , in , out , offset , profiler ) ; break;
|
||||
default: ERROR_OUT( "Unrecognized output index type" );
|
||||
}
|
||||
char done = 1;
|
||||
socketStream.write( done );
|
||||
}
|
||||
if( clientMergePlyInfo.verbose ) std::cout << "Offset polygons: " << profiler(true) << std::endl;
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
void RunClients( std::vector< Socket > &serverSockets , unsigned int sampleMS )
|
||||
{
|
||||
|
||||
ClientMergePlyInfo clientMergePlyInfo;
|
||||
|
||||
for( unsigned int i=0 ; i<serverSockets.size() ; i++ )
|
||||
{
|
||||
SocketStream serverStream( serverSockets[i] );
|
||||
clientMergePlyInfo = ClientMergePlyInfo( serverStream );
|
||||
}
|
||||
|
||||
if( clientMergePlyInfo.auxProperties.size() )
|
||||
{
|
||||
typedef VertexFactory::Factory< Real , VertexFactory::PositionFactory< Real , Dim > , VertexFactory::DynamicFactory< Real > > Factory;
|
||||
VertexFactory::PositionFactory< Real , Dim > vFactory;
|
||||
VertexFactory::DynamicFactory< Real > dFactory( clientMergePlyInfo.auxProperties );
|
||||
Factory factory( vFactory , dFactory );
|
||||
_RunClients< Real , Dim >( clientMergePlyInfo , factory , serverSockets , sampleMS );
|
||||
}
|
||||
else
|
||||
{
|
||||
typedef VertexFactory::Factory< Real , VertexFactory::PositionFactory< Real , Dim > > Factory;
|
||||
Factory factory;
|
||||
_RunClients< Real , Dim >( clientMergePlyInfo , factory , serverSockets , sampleMS );
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
// ClientPartitionInfo //
|
||||
/////////////////////////
|
||||
ClientMergePlyInfo::ClientMergePlyInfo( void ){}
|
||||
|
||||
ClientMergePlyInfo::ClientMergePlyInfo( BinaryStream &stream )
|
||||
{
|
||||
auto ReadBool = [&]( bool &b )
|
||||
{
|
||||
char _b;
|
||||
if( !stream.read( _b ) ) return false;
|
||||
b = _b!=0;
|
||||
return true;
|
||||
};
|
||||
|
||||
if( !stream.read( bufferSize ) ) ERROR_OUT( "Failed to read buffer size" );
|
||||
{
|
||||
size_t sz;
|
||||
if( !stream.read( sz ) ) ERROR_OUT( "Failed to read number of auxiliary properties" );
|
||||
auxProperties.resize(sz);
|
||||
for( size_t i=0 ; i<sz ; i++ ) auxProperties[i].read( stream );
|
||||
}
|
||||
if( !ReadBool( verbose ) ) ERROR_OUT( "Failed to read verbose flag" );
|
||||
}
|
||||
|
||||
void ClientMergePlyInfo::write( BinaryStream &stream ) const
|
||||
{
|
||||
auto WriteBool = [&]( bool b )
|
||||
{
|
||||
char _b = b ? 1 : 0;
|
||||
stream.write( _b );
|
||||
};
|
||||
|
||||
stream.write( bufferSize );
|
||||
{
|
||||
size_t sz = auxProperties.size();
|
||||
stream.write( sz );
|
||||
for( size_t j=0 ; j<sz ; j++ ) auxProperties[j].write( stream );
|
||||
}
|
||||
WriteBool( verbose );
|
||||
}
|
||||
+13
-4
@@ -89,7 +89,16 @@ struct Timer
|
||||
{
|
||||
Timer( void ){ _startCPUClock = std::clock() , _startWallClock = std::chrono::system_clock::now(); }
|
||||
double cpuTime( void ) const{ return (std::clock() - _startCPUClock) / (double)CLOCKS_PER_SEC; };
|
||||
double wallTime( void ) const{ std::chrono::duration<double> diff = (std::chrono::system_clock::now() - _startWallClock) ; return diff.count(); }
|
||||
double wallTime( void ) const{ std::chrono::duration<double> diff = (std::chrono::system_clock::now() - _startWallClock) ; return diff.count(); }
|
||||
std::string operator()( bool showCpuTime , unsigned int precision=1 ) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
StreamFloatPrecision sfp( ss , precision );
|
||||
ss << wallTime() << " (s)";
|
||||
if( showCpuTime ) ss << " / " << cpuTime() << " (s)";
|
||||
return ss.str();
|
||||
}
|
||||
friend std::ostream &operator << ( std::ostream &os , const Timer &timer ){ return os << timer(false); }
|
||||
protected:
|
||||
std::clock_t _startCPUClock;
|
||||
std::chrono::time_point< std::chrono::system_clock > _startWallClock;
|
||||
@@ -787,7 +796,7 @@ struct Profiler
|
||||
else if( currentPeak>_currentPeak ) _currentPeak = currentPeak;
|
||||
}
|
||||
|
||||
std::string operator()( std::string header="" ) const
|
||||
std::string operator()( bool showTime=true ) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
double dt = Time()-_t;
|
||||
@@ -795,8 +804,8 @@ struct Profiler
|
||||
double globalPeakMB = ( (double)getPeakRSS() )/(1<<20);
|
||||
{
|
||||
StreamFloatPrecision sfp( ss , 1 );
|
||||
if( header.length() ) ss << header << " ";
|
||||
ss << dt << " (s), " << localPeakMB << " (MB) / " << globalPeakMB << " (MB)";
|
||||
if( showTime ) ss << dt << " (s), ";
|
||||
ss << localPeakMB << " (MB) / " << globalPeakMB << " (MB)";
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,31 @@
|
||||
/*
|
||||
Copyright (c) 2010, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer. Redistributions in binary form must reproduce
|
||||
the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Johns Hopkins University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef PNG_INCLUDED
|
||||
#define PNG_INCLUDED
|
||||
|
||||
|
||||
+28
@@ -1,3 +1,31 @@
|
||||
/*
|
||||
Copyright (c) 2010, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer. Redistributions in binary form must reproduce
|
||||
the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Johns Hopkins University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
+58
-1
@@ -64,7 +64,64 @@ namespace PLY
|
||||
PlyProperty Face< long long , true >::Properties[] = { PlyProperty( "vertex_indices" , PLY_LONGLONG , PLY_LONGLONG , offsetof( Face , vertices ) , 1 , PLY_CHAR , PLY_CHAR , offsetof( Face , nr_vertices ) ) };
|
||||
template<>
|
||||
PlyProperty Face< unsigned long long , true >::Properties[] = { PlyProperty( "vertex_indices" , PLY_ULONGLONG , PLY_ULONGLONG , offsetof( Face , vertices ) , 1 , PLY_CHAR , PLY_CHAR , offsetof( Face , nr_vertices ) ) };
|
||||
|
||||
// Read
|
||||
inline PlyFile *ReadHeader( std::string fileName , int &fileType , std::vector< std::tuple< std::string , size_t , std::vector< PlyProperty > > > &elems , std::vector< std::string > &comments )
|
||||
{
|
||||
std::vector< std::string > elist;
|
||||
float version;
|
||||
|
||||
PlyFile *ply = PlyFile::Read( fileName , elist , fileType , version );
|
||||
if( !ply ) ERROR_OUT( "Could not open ply file for reading: " , fileName );
|
||||
|
||||
elems.resize( elist.size() );
|
||||
for( unsigned int i=0 ; i<elist.size() ; i++ )
|
||||
{
|
||||
std::get<0>( elems[i] ) = elist[i];
|
||||
std::get<2>( elems[i] ) = ply->get_element_description( std::get<0>( elems[i] ) , std::get<1>( elems[i] ) );
|
||||
}
|
||||
|
||||
comments.resize( ply->comments.size() );
|
||||
for( int i=0 ; i<ply->comments.size() ; i++ ) comments[i] = ply->comments[i];
|
||||
|
||||
return ply;
|
||||
}
|
||||
|
||||
inline PlyFile *WriteHeader( std::string fileName , int fileType , const std::vector< std::tuple< std::string , size_t , std::vector< PlyProperty > > > &elems , const std::vector< std::string > &comments )
|
||||
{
|
||||
PlyFile *ply = NULL;
|
||||
{
|
||||
float version;
|
||||
std::vector< std::string > elist( elems.size() );
|
||||
for( unsigned int i=0 ; i<elems.size() ; i++ ) elist[i] = std::get<0>( elems[i] );
|
||||
ply = PlyFile::Write( fileName , elist , fileType , version );
|
||||
}
|
||||
if( !ply ) ERROR_OUT( "Could not open ply for writing: " , fileName );
|
||||
for( unsigned int i=0 ; i<elems.size() ; i++ )
|
||||
{
|
||||
ply->element_count( std::get<0>( elems[i] ) , std::get<1>( elems[i] ) );
|
||||
const std::vector< PlyProperty > &props = std::get<2>( elems[i] );
|
||||
for( unsigned int j=0 ; j<props.size() ; j++ ) ply->describe_property( std::get<0>( elems[i] ) , &props[j] );
|
||||
}
|
||||
|
||||
for( int i=0 ; i<comments.size() ; i++ ) ply->put_comment( comments[i] );
|
||||
ply->header_complete();
|
||||
|
||||
return ply;
|
||||
}
|
||||
|
||||
inline PlyFile *ReadHeader( std::string fileName , int &fileType , std::vector< std::tuple< std::string , size_t , std::vector< PlyProperty > > > &elems )
|
||||
{
|
||||
std::vector< std::string > comments;
|
||||
return ReadHeader( fileName , fileType , elems , comments );
|
||||
}
|
||||
|
||||
inline PlyFile *WriteHeader( std::string fileName , int fileType , const std::vector< std::tuple< std::string , size_t , std::vector< PlyProperty > > > &elems )
|
||||
{
|
||||
std::vector< std::string > comments;
|
||||
return WriteHeader( fileName , fileType , elems , comments );
|
||||
}
|
||||
|
||||
template< typename VertexFactory >
|
||||
inline int ReadVertexHeader( std::string fileName , const VertexFactory &vFactory , bool *readFlags )
|
||||
{
|
||||
@@ -143,7 +200,7 @@ namespace PLY
|
||||
template< typename VertexFactory , typename Index >
|
||||
void ReadPolygons( std::string fileName , const VertexFactory &vFactory , std::vector< typename VertexFactory::VertexType > &vertices , std::vector< std::vector< Index > > &polygons , int &file_type , std::vector< std::string > &comments , bool *readFlags )
|
||||
{
|
||||
std::vector< std::string > elist = { std::string( "vertex" ) , std::string( "face" ) };
|
||||
std::vector< std::string > elist;
|
||||
float version;
|
||||
|
||||
PlyFile *ply = PlyFile::Read( fileName , elist , file_type , version );
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
|
||||
Copyright (c) 2014, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -383,7 +383,8 @@ void ExtractMesh
|
||||
|
||||
std::vector< std::string > noComments;
|
||||
typename VertexFactory::Transform unitCubeToModelTransform( unitCubeToModel );
|
||||
PLY::WritePolygons< VertexFactory , node_index_type , Real , Dim >( Out.value , vertexFactory , mesh , ASCII.set ? PLY_ASCII : PLY_BINARY_NATIVE , NoComments.set ? noComments : comments , unitCubeToModelTransform );
|
||||
auto xForm = [&]( typename VertexFactory::VertexType &v ){ unitCubeToModelTransform.inPlace(v); };
|
||||
PLY::WritePolygons< VertexFactory , node_index_type , Real , Dim >( Out.value , vertexFactory , mesh , ASCII.set ? PLY_ASCII : PLY_BINARY_NATIVE , NoComments.set ? noComments : comments , xForm );
|
||||
delete mesh;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
Copyright (c) 2023, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer. Redistributions in binary form must reproduce
|
||||
the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Johns Hopkins University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef POINT_PARTITION_INCLUDED
|
||||
#define POINT_PARTITION_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <filesystem>
|
||||
#include "Streams.h"
|
||||
#include "MyMiscellany.h"
|
||||
#include "Ply.h"
|
||||
#include "VertexStream.h"
|
||||
|
||||
#define ADAPTIVE_PADDING // Only pushes padding points deep enough so that they are "close" to the slab in terms of units at that depth
|
||||
#define BUFFER_IO (1<<14) // Buffer the points before reading/writing
|
||||
//#define AXIS_ONLY_ALIGNMENT // Only align to the three coordinate axes (should be disabled)
|
||||
|
||||
|
||||
namespace PointPartition
|
||||
{
|
||||
template< typename Real , unsigned int Dim >
|
||||
struct PointSetInfo
|
||||
{
|
||||
std::string header;
|
||||
unsigned filesPerDir;
|
||||
XForm< Real , Dim+1 > modelToUnitCube;
|
||||
std::vector< size_t > pointsPerSlab;
|
||||
std::vector< PlyProperty > auxiliaryProperties;
|
||||
|
||||
PointSetInfo( void );
|
||||
PointSetInfo( unsigned int slabs );
|
||||
PointSetInfo( BinaryStream &stream );
|
||||
|
||||
void write( BinaryStream &stream ) const;
|
||||
};
|
||||
|
||||
template< typename Real >
|
||||
struct Extent
|
||||
{
|
||||
#ifdef AXIS_ONLY_ALIGNMENT
|
||||
static const unsigned int DirectionN = 3;
|
||||
#else // !AXIS_ONLY_ALIGNMENT
|
||||
static const unsigned int DirectionN = 9;
|
||||
#endif // AXIS_ONLY_ALIGNMENT
|
||||
static const Point< Real , 3 > Directions[ DirectionN ];
|
||||
static const unsigned int Frames[DirectionN][3];
|
||||
std::pair< Real , Real > extents[DirectionN];
|
||||
|
||||
Extent( void );
|
||||
void add( Point< Real , 3 > p );
|
||||
Extent operator + ( const Extent &e ) const;
|
||||
};
|
||||
|
||||
struct Partition
|
||||
{
|
||||
Partition( void );
|
||||
Partition( unsigned int dCount , const std::vector< size_t > &slabSizes );
|
||||
|
||||
#ifdef ADAPTIVE_PADDING
|
||||
void optimize( bool useMax );
|
||||
std::pair< unsigned int , unsigned int > range( unsigned int i ) const;
|
||||
size_t size( unsigned int i ) const;
|
||||
void printDistribution( void ) const;
|
||||
double l2Energy( void ) const;
|
||||
double maxEnergy( void ) const;
|
||||
#else // !ADAPTIVE_PADDING
|
||||
void optimize( bool useMax , unsigned int padSize );
|
||||
std::pair< unsigned int , unsigned int > range( unsigned int i , unsigned int padSize ) const;
|
||||
size_t size( unsigned int i , unsigned int padSize ) const;
|
||||
void printDistribution( unsigned int padSize ) const;
|
||||
double l2Energy( unsigned int padSize ) const;
|
||||
double maxEnergy( unsigned int padSize ) const;
|
||||
#endif // ADAPTIVE_PADDING
|
||||
size_t size( void ) const;
|
||||
unsigned int slabs( void ) const;
|
||||
|
||||
protected:
|
||||
std::vector< unsigned int > _starts;
|
||||
std::vector< size_t > _slabSizes;
|
||||
};
|
||||
|
||||
long ReadPLYProperties( FILE *fp , std::vector< PlyProperty > &properties );
|
||||
long ReadPLYProperties( const char *fileName , std::vector< PlyProperty > &properties );
|
||||
long WritePLYProperties( FILE *fp , const std::vector< PlyProperty > &properties );
|
||||
long WritePLYProperties( const char *fileName , const std::vector< PlyProperty > &properties );
|
||||
|
||||
template< typename InputFactory >
|
||||
struct BufferedBinaryInputDataStream : public InputDataStream< typename InputFactory::VertexType >
|
||||
{
|
||||
|
||||
typedef typename InputFactory::VertexType Data;
|
||||
BufferedBinaryInputDataStream( const char *fileName , const InputFactory &factory , size_t bufferSize );
|
||||
~BufferedBinaryInputDataStream( void );
|
||||
void reset( void );
|
||||
bool next( Data &d );
|
||||
protected:
|
||||
size_t _bufferSize , _current , _inBuffer , _elementSize;
|
||||
Pointer( char ) _buffer;
|
||||
FILE *_fp;
|
||||
const InputFactory &_factory;
|
||||
long _inset;
|
||||
};
|
||||
|
||||
template< typename OutputFactory >
|
||||
struct BufferedBinaryOutputDataStream : public OutputDataStream< typename OutputFactory::VertexType >
|
||||
{
|
||||
typedef typename OutputFactory::VertexType Data;
|
||||
BufferedBinaryOutputDataStream( const char *fileName , const OutputFactory &factory , size_t bufferSize );
|
||||
~BufferedBinaryOutputDataStream( void );
|
||||
void reset( void );
|
||||
void next( const Data &d );
|
||||
protected:
|
||||
size_t _bufferSize , _current , _elementSize;
|
||||
Pointer( char ) _buffer;
|
||||
FILE *_fp;
|
||||
const OutputFactory &_factory;
|
||||
long _inset;
|
||||
};
|
||||
|
||||
void RemovePointSlabDirs( std::string dir );
|
||||
static void CreatePointSlabDirs( std::string dir , unsigned int count , unsigned int filesPerDir );
|
||||
|
||||
std::string FileDir( std::string dir , std::string header );
|
||||
std::string FileDir( std::string dir , std::string header , unsigned int clientIndex );
|
||||
|
||||
std::string FileName( std::string dir , unsigned int slab , unsigned int slabs , unsigned int filesPerDir );
|
||||
std::string FileName( std::string dir , std::string header , unsigned int slab , unsigned int slabs , unsigned int filesPerDir );
|
||||
std::string FileName( std::string dir , std::string header , unsigned int clientIndex , unsigned int slab , unsigned int slabs , unsigned int filesPerDir );
|
||||
|
||||
std::string PointSetInfoName( std::string dir , std::string header );
|
||||
|
||||
#include "PointPartition.inl"
|
||||
}
|
||||
|
||||
#endif // POINT_PARTITION_INCLUDED
|
||||
@@ -0,0 +1,659 @@
|
||||
/*
|
||||
Copyright (c) 2023, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer. Redistributions in binary form must reproduce
|
||||
the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Johns Hopkins University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
std::string FileDir( std::string dir , std::string header )
|
||||
{
|
||||
if( dir.back()!=FileSeparator ) dir += std::string(1,FileSeparator);
|
||||
return dir + header;
|
||||
}
|
||||
|
||||
std::string FileDir( std::string dir , std::string header , unsigned int clientIndex )
|
||||
{
|
||||
std::stringstream sStream;
|
||||
sStream << header << "_" << clientIndex;
|
||||
return FileDir( dir , sStream.str() );
|
||||
}
|
||||
|
||||
std::string FileName( std::string dir , unsigned int slab , unsigned int slabs , unsigned int filesPerDir )
|
||||
{
|
||||
if( filesPerDir<=1 ) ERROR_OUT( "Need at least two files per directory" );
|
||||
|
||||
if( !dir.length() ) dir = std::string( "." );
|
||||
if( dir.back()!=FileSeparator ) dir.push_back( FileSeparator );
|
||||
|
||||
std::vector< unsigned int > factors;
|
||||
factors.push_back(slab);
|
||||
while( slabs>filesPerDir )
|
||||
{
|
||||
factors.push_back( (slab / filesPerDir) % filesPerDir );
|
||||
slab /= filesPerDir;
|
||||
slabs /= filesPerDir;
|
||||
}
|
||||
|
||||
std::stringstream sStream;
|
||||
sStream << dir;
|
||||
|
||||
for( unsigned int i=(unsigned int)factors.size()-1 ; i!=0 ; i-- ) sStream << factors[i] << std::string(1,FileSeparator);
|
||||
sStream << factors[0] << ".points";
|
||||
return sStream.str();
|
||||
}
|
||||
|
||||
std::string FileName( std::string dir , std::string header , unsigned int slab , unsigned int slabs , unsigned int filesPerDir )
|
||||
{
|
||||
return FileName( FileDir( dir , header ) , slab , slabs , filesPerDir );
|
||||
}
|
||||
|
||||
std::string FileName( std::string dir , std::string header , unsigned int clientIndex , unsigned int slab , unsigned int slabs , unsigned int filesPerDir )
|
||||
{
|
||||
return FileName( FileDir( dir , header , clientIndex ) , slab , slabs , filesPerDir );
|
||||
}
|
||||
|
||||
std::string PointSetInfoName( std::string dir , std::string header )
|
||||
{
|
||||
if( dir.back()==FileSeparator ) return dir + header + std::string( ".psi" );
|
||||
else return dir + std::string(1,FileSeparator) + header + std::string( ".psi" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////
|
||||
// Extent //
|
||||
////////////
|
||||
template< typename Real >
|
||||
Extent< Real >::Extent( void )
|
||||
{
|
||||
Real inf = std::numeric_limits< Real >::infinity();
|
||||
for( unsigned int d=0 ; d<DirectionN ; d++ ) extents[d].first = inf , extents[d].second = -inf;
|
||||
}
|
||||
|
||||
template< typename Real >
|
||||
void Extent< Real >::add( Point< Real , 3 > p )
|
||||
{
|
||||
for( unsigned int d=0 ; d<DirectionN ; d++ )
|
||||
{
|
||||
extents[d].first = std::min< Real >( extents[d].first , Point< Real , 3 >::Dot( p , Directions[d] ) );
|
||||
extents[d].second = std::max< Real >( extents[d].second , Point< Real , 3 >::Dot( p , Directions[d] ) );
|
||||
}
|
||||
}
|
||||
|
||||
template< typename Real >
|
||||
Extent< Real > Extent< Real >::operator + ( const Extent< Real > &e ) const
|
||||
{
|
||||
Extent _e;
|
||||
for( unsigned int d=0 ; d<DirectionN ; d++ )
|
||||
{
|
||||
_e.extents[d].first = std::min< Real >( extents[d].first , e.extents[d].first );
|
||||
_e.extents[d].second = std::max< Real >( extents[d].second , e.extents[d].second );
|
||||
}
|
||||
return _e;
|
||||
}
|
||||
|
||||
template< typename Real >
|
||||
const Point< Real , 3 > Extent< Real >::Directions[] =
|
||||
{
|
||||
Point< Real , 3 >( 1 , 0 , 0 ) , // 0
|
||||
Point< Real , 3 >( 0 , 1 , 0 ) , // 1
|
||||
Point< Real , 3 >( 0 , 0 , 1 ) , // 2
|
||||
#ifdef AXIS_ONLY_ALIGNMENT
|
||||
#else // !AXIS_ONLY_ALIGNMENT
|
||||
Point< Real , 3 >( 1 , 1 , 0 )/(Real)sqrt(2.) , // 3
|
||||
Point< Real , 3 >( 1 , 0 , 1 )/(Real)sqrt(2.) , // 4
|
||||
Point< Real , 3 >( 0 , 1 , 1 )/(Real)sqrt(2.) , // 5
|
||||
Point< Real , 3 >( 1 ,-1 , 0 )/(Real)sqrt(2.) , // 6
|
||||
Point< Real , 3 >( 1 , 0 ,-1 )/(Real)sqrt(2.) , // 7
|
||||
Point< Real , 3 >( 0 , 1 ,-1 )/(Real)sqrt(2.) // 8
|
||||
#endif
|
||||
};
|
||||
|
||||
template< typename Real >
|
||||
const unsigned int Extent< Real >::Frames[ DirectionN ][3] =
|
||||
{
|
||||
{1,2,0} ,
|
||||
{2,0,1} ,
|
||||
{0,1,2} ,
|
||||
#ifdef AXIS_ONLY_ALIGNMENT
|
||||
#else // !AXIS_ONLY_ALIGNMENT
|
||||
{2,6,3} ,
|
||||
{7,1,4} ,
|
||||
{0,8,5} ,
|
||||
{3,2,6} ,
|
||||
{1,4,7} ,
|
||||
{5,0,8}
|
||||
#endif // AXIS_ONLY_ALIGNMENT
|
||||
};
|
||||
|
||||
template< typename Real >
|
||||
std::ostream &operator << ( std::ostream &os , const Extent< Real > &e )
|
||||
{
|
||||
for( unsigned int d=0 ; d<Extent< Real >::DirectionN ; d++ )
|
||||
{
|
||||
os << Extent< Real >::Directions[d] << " : [ " << e.extents[d].first << " , " << e.extents[d].second << " ]";
|
||||
os << "\t(" << e.extents[d].second - e.extents[d].first << " )" << std::endl;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
//////////////////
|
||||
// PointSetInfo //
|
||||
//////////////////
|
||||
template< typename Real , unsigned int Dim >
|
||||
PointSetInfo< Real , Dim >::PointSetInfo( void ) : modelToUnitCube( XForm< Real , Dim+1 >::Identity() ) , filesPerDir(-1) {}
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
PointSetInfo< Real , Dim >::PointSetInfo( unsigned int slabs ) : modelToUnitCube( XForm< Real , Dim+1 >::Identity() ) , filesPerDir(-1)
|
||||
{
|
||||
pointsPerSlab.resize( slabs , 0 );
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
PointSetInfo< Real , Dim >::PointSetInfo( BinaryStream &stream )
|
||||
{
|
||||
if( !stream.read( header ) ) ERROR_OUT( "Failed to read header" );
|
||||
if( !stream.read( modelToUnitCube ) ) ERROR_OUT( "Failed to read model-to-unit-cube transform" );
|
||||
if( !stream.read( pointsPerSlab ) ) ERROR_OUT( "Failed to read points-per-slab" );
|
||||
{
|
||||
size_t sz;
|
||||
if( !stream.read( sz ) ) ERROR_OUT( "Failed to read number of auxiliary properties" );
|
||||
auxiliaryProperties.resize(sz);
|
||||
for( size_t i=0 ; i<sz ; i++ ) auxiliaryProperties[i].read( stream );
|
||||
}
|
||||
if( !stream.read( filesPerDir ) ) ERROR_OUT( "Failed to read files-per-directory" );
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
void PointSetInfo< Real , Dim >::write( BinaryStream &stream ) const
|
||||
{
|
||||
stream.write( header );
|
||||
stream.write( modelToUnitCube );
|
||||
stream.write( pointsPerSlab );
|
||||
{
|
||||
size_t sz = auxiliaryProperties.size();
|
||||
stream.write( sz );
|
||||
for( size_t i=0 ; i<sz ; i++ ) auxiliaryProperties[i].write( stream );
|
||||
}
|
||||
stream.write( filesPerDir );
|
||||
}
|
||||
|
||||
void RemovePointSlabDirs( std::string dir ){ std::filesystem::remove_all( dir ); }
|
||||
void CreatePointSlabDirs( std::string dir , unsigned int count , unsigned int filesPerDir )
|
||||
{
|
||||
if( filesPerDir<=1 ) ERROR_OUT( "Need at least two files per directory" );
|
||||
if( !dir.length() ) dir = std::string( "." );
|
||||
if( dir.back()!=FileSeparator ) dir += std::string(1,FileSeparator);
|
||||
|
||||
try{ std::filesystem::create_directories( dir ); }
|
||||
catch( ... ){ ERROR_OUT( "Failed to create directory: " , dir ); }
|
||||
|
||||
unsigned int depth = 0;
|
||||
{
|
||||
size_t _filesPerDir = filesPerDir;
|
||||
while( count>_filesPerDir ) _filesPerDir *= filesPerDir , depth++;
|
||||
}
|
||||
|
||||
auto _exp = []( unsigned int filesPerDir , unsigned int depth )
|
||||
{
|
||||
unsigned int e = 1;
|
||||
for( unsigned int d=0 ; d<depth ; d++ ) e *= filesPerDir;
|
||||
return e;
|
||||
};
|
||||
|
||||
std::function< void ( std::string , unsigned int , unsigned int , unsigned int ) > MakeDirs = [&]( std::string dir , unsigned int count , unsigned int depth , unsigned int filesPerDir )
|
||||
{
|
||||
if( depth )
|
||||
{
|
||||
unsigned int _filesPerDir = _exp( filesPerDir , depth );
|
||||
for( unsigned int i=0 ; i*_filesPerDir<count ; i++ )
|
||||
{
|
||||
std::stringstream sStream;
|
||||
sStream << dir << i << FileSeparator;
|
||||
std::string _dir = sStream.str();
|
||||
try{ std::filesystem::create_directories( _dir ); }
|
||||
catch( ... ){ ERROR_OUT( "Failed to create directory: " , _dir ); }
|
||||
MakeDirs( _dir , std::min< unsigned int >( count-(i*_filesPerDir) , _filesPerDir ) , depth-1 , filesPerDir );
|
||||
}
|
||||
}
|
||||
};
|
||||
MakeDirs( dir , count , depth , filesPerDir );
|
||||
}
|
||||
///////////////
|
||||
// Partition //
|
||||
///////////////
|
||||
// Energy:
|
||||
// An object supporting bool operator < ( const Energy & ) const;
|
||||
template< typename Energy >
|
||||
struct _DynamicProgrammingPartition
|
||||
{
|
||||
// EnergyFunctor:
|
||||
// A functor that that takes the start and end of the range and returns the associated energy
|
||||
// MergeFunctor:
|
||||
// A functor that takes two energies and turns them into one
|
||||
template< typename EnergyFunctor , typename MergeFunctor >
|
||||
_DynamicProgrammingPartition( const EnergyFunctor &energy , const MergeFunctor &merge , unsigned int slabs , unsigned int interiorBoundaries )
|
||||
{
|
||||
_solutions.resize( slabs+1 );
|
||||
for( unsigned int start=0 ; start<_solutions.size() ; start++ )
|
||||
{
|
||||
_solutions[start].resize( slabs+1 );
|
||||
for( unsigned int end=start+1 ; end<_solutions[start].size() ; end++ ) _solutions[start][end].resize( interiorBoundaries+1 );
|
||||
}
|
||||
_energies.resize( slabs+1 );
|
||||
for( unsigned int i=0 ; i<=slabs ; i++ )
|
||||
{
|
||||
_energies[i].resize( slabs+1 );
|
||||
for( unsigned int j=i ; j<=slabs ; j++ ) _energies[i][j] = energy( i , j );
|
||||
}
|
||||
_getSolution( merge , 0 , slabs , interiorBoundaries , Energy() );
|
||||
}
|
||||
|
||||
std::pair< Energy , std::vector< unsigned int > > solution( void ) const
|
||||
{
|
||||
std::pair< Energy , std::vector< unsigned int > > sol;
|
||||
unsigned int start = 0 , end = (unsigned int)_solutions[0].size()-1;
|
||||
unsigned int interiorBoundaries = (unsigned int)_solutions[start][end].size()-1;
|
||||
sol.first = _solutions[0].back().back().e;
|
||||
while( _solutions[start][end][interiorBoundaries].idx!=-1 )
|
||||
{
|
||||
sol.second.push_back( _solutions[start][end][interiorBoundaries].idx );
|
||||
start = _solutions[start][end][interiorBoundaries].idx;
|
||||
interiorBoundaries--;
|
||||
}
|
||||
return sol;
|
||||
}
|
||||
|
||||
template< typename EnergyFunctor , typename MergeFunctor >
|
||||
static std::pair< Energy , std::vector< unsigned int > > Partition( const EnergyFunctor &energy , const MergeFunctor &merge , unsigned int slabs , unsigned int interiorBoundaries )
|
||||
{
|
||||
return _DynamicProgrammingPartition( energy , merge , slabs , interiorBoundaries ).solution();
|
||||
}
|
||||
|
||||
protected:
|
||||
struct _Solution
|
||||
{
|
||||
unsigned int idx;
|
||||
Energy e;
|
||||
_Solution( void ) : idx(-1){}
|
||||
};
|
||||
|
||||
|
||||
// A solution is indexed by the start index, end index, and the number of interior boundaries
|
||||
// The extent is defined by [start,end)
|
||||
std::vector< std::vector< std::vector< _Solution > > > _solutions;
|
||||
std::vector< std::vector< Energy > > _energies;
|
||||
template< typename MergeFunctor >
|
||||
Energy _getSolution( const MergeFunctor &merge , unsigned int start , unsigned int end , unsigned int interiorBoundaries , Energy minEnergy )
|
||||
{
|
||||
// Assuming that:
|
||||
// start<end
|
||||
// interiorBoundaries+1<(end-start)
|
||||
|
||||
// If we have a solution for this range, return it
|
||||
if( _solutions[start][end][interiorBoundaries].idx!=-1 ) return _solutions[start][end][interiorBoundaries].e;
|
||||
|
||||
// If the range does not need to be partitioned
|
||||
else if( interiorBoundaries==0 ) return ( _solutions[start][end][interiorBoundaries].e = _energies[start][end] );
|
||||
|
||||
// Otherwise
|
||||
else
|
||||
{
|
||||
// 1. Split [start,end) into [start,_start) and [_start,end)
|
||||
// 2. Find interiorBoundaries-1 interior boundaries for [_start,end)
|
||||
// 3. Merge
|
||||
unsigned int minIndex = -1;
|
||||
unsigned int _interiorBoundaries = interiorBoundaries-1;
|
||||
for( unsigned int _start=start+1 ; _start<end ; _start++ )
|
||||
{
|
||||
if( _interiorBoundaries<(end-_start) )
|
||||
{
|
||||
if( !(minEnergy<_energies[start][_start]) )
|
||||
{
|
||||
Energy e = merge( _energies[start][_start] , _getSolution( merge , _start , end , _interiorBoundaries , minEnergy ) );
|
||||
if( minIndex==-1 || e<minEnergy ) minEnergy = e , minIndex = _start;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( minIndex==-1 ) ERROR_OUT( "Could not find a solution: [ " , start , " , " , end , " ) " , interiorBoundaries );
|
||||
_solutions[start][end][interiorBoundaries].e = minEnergy;
|
||||
_solutions[start][end][interiorBoundaries].idx = minIndex;
|
||||
return minEnergy;
|
||||
}
|
||||
}
|
||||
};
|
||||
Partition::Partition( void ) : _slabSizes(1,0) , _starts(0) {}
|
||||
|
||||
Partition::Partition( unsigned int dCount , const std::vector< size_t > &slabSizes ) : _slabSizes( slabSizes )
|
||||
{
|
||||
unsigned int sCount = (unsigned int)_slabSizes.size();
|
||||
_starts.resize( dCount-1 );
|
||||
for( unsigned int i=1 ; i<dCount ; i++ ) _starts[i-1] = ( sCount * i ) / dCount;
|
||||
}
|
||||
|
||||
#ifdef ADAPTIVE_PADDING
|
||||
void Partition::optimize( bool useMax )
|
||||
#else // !ADAPTIVE_PADDING
|
||||
void Partition::optimize( bool useMax , unsigned int padSize )
|
||||
#endif // ADAPTIVE_PADDING
|
||||
{
|
||||
#ifdef ADAPTIVE_PADDING
|
||||
#else // !ADAPTIVE_PADDING
|
||||
auto paddedStart = [&]( unsigned int start ){ return start>padSize ? (start-padSize) : 0; };
|
||||
auto paddedEnd = [&]( unsigned int end ){ return ( end+padSize<=_slabSizes.size() ) ? (end+padSize) : (unsigned int)_slabSizes.size(); };
|
||||
#endif // ADAPTIVE_PADDING
|
||||
|
||||
struct L2Energy
|
||||
{
|
||||
double e;
|
||||
L2Energy( void ) : e( std::numeric_limits<double>::infinity() ) {}
|
||||
L2Energy( double e ) : e(e) {}
|
||||
bool operator < ( const L2Energy &energy ) const { return e<energy.e; }
|
||||
};
|
||||
struct MaxEnergy
|
||||
{
|
||||
std::vector< double > e;
|
||||
MaxEnergy( void ){}
|
||||
MaxEnergy( double e ) { this->e.resize(1,e); }
|
||||
bool operator < ( const MaxEnergy &energy ) const
|
||||
{
|
||||
for( unsigned int i=0 ; i<e.size() && i<energy.e.size() ; i++ )
|
||||
{
|
||||
if ( e[i]<energy.e[i] ) return true;
|
||||
else if( e[i]>energy.e[i] ) return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
auto energy = [&]( unsigned int start , unsigned int end )
|
||||
{
|
||||
double e = 0;
|
||||
#ifdef ADAPTIVE_PADDING
|
||||
for( unsigned int i=start ; i<end ; i++ ) e += _slabSizes[i];
|
||||
#else // !ADAPTIVE_PADDING
|
||||
for( unsigned int i=paddedStart(start) ; i<paddedEnd(end) ; i++ ) e += _slabSizes[i];
|
||||
#endif // ADAPTIVE_PADDING
|
||||
return e*e;
|
||||
};
|
||||
auto l2Energy = [&]( unsigned int start , unsigned int end ){ return L2Energy( energy(start,end) ); };
|
||||
auto maxEnergy = [&]( unsigned int start , unsigned int end ){ return MaxEnergy( energy(start,end) ); };
|
||||
|
||||
auto l2Merge = []( L2Energy e1 , L2Energy e2 ){ return L2Energy( e1.e + e2.e ); };
|
||||
auto maxMerge = []( MaxEnergy e1 , MaxEnergy e2 )
|
||||
{
|
||||
MaxEnergy e;
|
||||
e.e.reserve( e1.e.size() + e2.e.size() );
|
||||
for( unsigned int i=0 ; i<e1.e.size() ; i++ ) e.e.push_back( e1.e[i] );
|
||||
for( unsigned int i=0 ; i<e2.e.size() ; i++ ) e.e.push_back( e2.e[i] );
|
||||
std::sort( e.e.begin() , e.e.end() , []( double e1 , double e2 ){ return e1>e2; } );
|
||||
return e;
|
||||
};
|
||||
|
||||
if( useMax ) _starts = _DynamicProgrammingPartition< MaxEnergy >::Partition( maxEnergy , maxMerge , (unsigned)_slabSizes.size() , (unsigned int)_starts.size() ).second;
|
||||
else _starts = _DynamicProgrammingPartition< L2Energy >::Partition( l2Energy , l2Merge , (unsigned)_slabSizes.size() , (unsigned int)_starts.size() ).second;
|
||||
}
|
||||
|
||||
#ifdef ADAPTIVE_PADDING
|
||||
std::pair< unsigned int , unsigned int > Partition::range( unsigned int i ) const
|
||||
#else // !ADAPTIVE_PADDING
|
||||
std::pair< unsigned int , unsigned int > Partition::range( unsigned int i , unsigned int padSize ) const
|
||||
#endif // ADAPTIVE_PADDING
|
||||
{
|
||||
unsigned int begin = i==0 ? 0 : _starts[i-1];
|
||||
unsigned int end = i==_starts.size() ? (unsigned int)_slabSizes.size() : _starts[i];
|
||||
#ifdef ADAPTIVE_PADDING
|
||||
#else // !ADAPTIVE_PADDING
|
||||
if( begin<padSize ) begin = 0;
|
||||
else begin -= padSize;
|
||||
if( end+padSize>_slabSizes.size() ) end = (unsigned int)_slabSizes.size();
|
||||
else end += padSize;
|
||||
#endif // ADAPTIVE_PADDING
|
||||
return std::pair< unsigned int , unsigned int >( begin , end );
|
||||
}
|
||||
|
||||
#ifdef ADAPTIVE_PADDING
|
||||
size_t Partition::size( unsigned int i ) const
|
||||
#else // !ADAPTIVE_PADDING
|
||||
size_t Partition::size( unsigned int i , unsigned int padSize ) const
|
||||
#endif // ADAPTIVE_PADDING
|
||||
{
|
||||
if( i>_starts.size() ) ERROR_OUT( "Index out of bounds: 0 <= " , i , " <= " , _starts.size() );
|
||||
#ifdef ADAPTIVE_PADDING
|
||||
std::pair< unsigned int , unsigned int > r = range( i );
|
||||
#else // !ADAPTIVE_PADDING
|
||||
std::pair< unsigned int , unsigned int > r = range( i , padSize );
|
||||
#endif // ADAPTIVE_PADDING
|
||||
size_t count = 0;
|
||||
for( unsigned int j=r.first ; j<r.second ; j++ ) count += _slabSizes[j];
|
||||
return count;
|
||||
}
|
||||
|
||||
size_t Partition::size( void ) const
|
||||
{
|
||||
size_t count = 0;
|
||||
#ifdef ADAPTIVE_PADDING
|
||||
for( unsigned int i=0 ; i<=_starts.size() ; i++ ) count += size(i);
|
||||
#else // !ADAPTIVE_PADDING
|
||||
for( unsigned int i=0 ; i<=_starts.size() ; i++ ) count += size(i,0);
|
||||
#endif // ADAPTIVE_PADDING
|
||||
return count;
|
||||
}
|
||||
|
||||
#ifdef ADAPTIVE_PADDING
|
||||
void Partition::printDistribution( void ) const
|
||||
#else // !ADAPTIVE_PADDING
|
||||
void Partition::printDistribution( unsigned int padSize ) const
|
||||
#endif // ADAPTIVE_PADDING
|
||||
{
|
||||
for( unsigned int i=0 ; i<=_starts.size() ; i++ )
|
||||
{
|
||||
#ifdef ADAPTIVE_PADDING
|
||||
std::pair< unsigned int , unsigned int > r = range(i);
|
||||
std::cout << "Slab[ " << i << " ] [ " << r.first << " , " << r.second << " ) " << size(i) << std::endl;
|
||||
#else // !ADAPTIVE_PADDING
|
||||
std::pair< unsigned int , unsigned int > r = range(i,0) , _r = range( i , padSize );
|
||||
if( padSize )
|
||||
std::cout << "Slab[ " << i << " ] [ " << r.first << " , " << r.second << " ) [ " << _r.first << " , " << _r.second << " ) " << size(i,0) << " " << size(i,padSize) << std::endl;
|
||||
else
|
||||
std::cout << "Slab[ " << i << " ] [ " << r.first << " , " << r.second << " ) " << size(i,0) << std::endl;
|
||||
#endif // ADAPTIVE_PADDING
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ADAPTIVE_PADDING
|
||||
double Partition::l2Energy( void ) const
|
||||
#else // !ADAPTIVE_PADDING
|
||||
double Partition::l2Energy( unsigned int padSize ) const
|
||||
#endif // ADAPTIVE_PADDING
|
||||
{
|
||||
double e = 0;
|
||||
for( unsigned int i=0 ; i<=_starts.size() ; i++ )
|
||||
{
|
||||
#ifdef ADAPTIVE_PADDING
|
||||
double d = (double)size(i);
|
||||
#else // !ADAPTIVE_PADDING
|
||||
double d = (double)size(i,padSize);
|
||||
#endif // ADAPTIVE_PADDING
|
||||
e += d*d;
|
||||
}
|
||||
return sqrt(e);
|
||||
}
|
||||
|
||||
#ifdef ADAPTIVE_PADDING
|
||||
double Partition::maxEnergy( void ) const
|
||||
#else // !ADAPTIVE_PADDING
|
||||
double Partition::maxEnergy( unsigned int padSize ) const
|
||||
#endif // ADAPTIVE_PADDING
|
||||
{
|
||||
double e = 0;
|
||||
#ifdef ADAPTIVE_PADDING
|
||||
for( unsigned int i=0 ; i<=_starts.size() ; i++ ) e = std::max< double >( e , (double)size(i) );
|
||||
#else // !ADAPTIVE_PADDING
|
||||
for( unsigned int i=0 ; i<=_starts.size() ; i++ ) e = std::max< double >( e , (double)size(i,padSize) );
|
||||
#endif // ADAPTIVE_PADDING
|
||||
return e;
|
||||
}
|
||||
|
||||
unsigned int Partition::slabs( void ) const { return (unsigned int)_slabSizes.size(); }
|
||||
|
||||
///////////////////////////////
|
||||
// Read/Write Ply Properties //
|
||||
///////////////////////////////
|
||||
long ReadPLYProperties( FILE *fp , std::vector< PlyProperty > &properties )
|
||||
{
|
||||
size_t sz;
|
||||
if( fread( &sz , sizeof( size_t ) , 1 , fp )!=1 ) ERROR_OUT( "Failed to read property size" );
|
||||
properties.resize( sz );
|
||||
FileStream fs(fp);
|
||||
for( size_t i=0 ; i<sz ; i++ ) properties[i].read( fs );
|
||||
return ftell( fp );
|
||||
}
|
||||
|
||||
long ReadPLYProperties( const char *fileName , std::vector< PlyProperty > &properties )
|
||||
{
|
||||
FILE *fp = fopen( fileName , "rb" );
|
||||
if( !fp ) ERROR_OUT( "Could not open file for reading: " , fileName );
|
||||
long pos = ReadPLYProperties( fp , properties );
|
||||
fclose( fp );
|
||||
return pos;
|
||||
}
|
||||
|
||||
long WritePLYProperties( FILE *fp , const std::vector< PlyProperty > &properties )
|
||||
{
|
||||
size_t sz = properties.size();
|
||||
fwrite( &sz , sizeof( size_t ) , 1 , fp );
|
||||
FileStream fs(fp);
|
||||
for( size_t i=0 ; i<sz ; i++ ) properties[i].write( fs );
|
||||
return ftell( fp );
|
||||
}
|
||||
|
||||
long WritePLYProperties( const char *fileName , const std::vector< PlyProperty > &properties )
|
||||
{
|
||||
FILE *fp = fopen( fileName , "wb" );
|
||||
if( !fp ) ERROR_OUT( "Could not open file for writing: " , fileName );
|
||||
long pos = WritePLYProperties( fp , properties );
|
||||
fclose( fp );
|
||||
return pos;
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
// BufferedBinaryInputDataStream //
|
||||
///////////////////////////////////
|
||||
template< typename InputFactory >
|
||||
BufferedBinaryInputDataStream< InputFactory >::BufferedBinaryInputDataStream( const char *fileName , const InputFactory &factory , size_t bufferSize ) : _factory(factory) , _bufferSize(bufferSize) , _current(0) , _inBuffer(0)
|
||||
{
|
||||
|
||||
if( !_bufferSize )
|
||||
{
|
||||
WARN_ONCE( "BufferSize cannot be zero , setting to one" );
|
||||
_bufferSize = 1;
|
||||
}
|
||||
_elementSize = _factory.bufferSize();
|
||||
_buffer = AllocPointer< char >( _elementSize*_bufferSize );
|
||||
_fp = fopen( fileName , "rb" );
|
||||
if( !_fp ) ERROR_OUT( "Could not open file for reading: " , fileName );
|
||||
std::vector< PlyProperty > properties;
|
||||
_inset = ReadPLYProperties( _fp , properties );
|
||||
}
|
||||
|
||||
template< typename InputFactory >
|
||||
BufferedBinaryInputDataStream< InputFactory >::~BufferedBinaryInputDataStream( void )
|
||||
{
|
||||
FreePointer( _buffer );
|
||||
fclose( _fp );
|
||||
}
|
||||
|
||||
template< typename InputFactory >
|
||||
void BufferedBinaryInputDataStream< InputFactory >::reset( void )
|
||||
{
|
||||
fseek( _fp , _inset , SEEK_SET );
|
||||
_current = 0;
|
||||
_inBuffer = 0;
|
||||
}
|
||||
|
||||
template< typename InputFactory >
|
||||
bool BufferedBinaryInputDataStream< InputFactory >::next( Data &d )
|
||||
{
|
||||
if( _current==_inBuffer )
|
||||
{
|
||||
_inBuffer = fread( _buffer , _elementSize , _bufferSize , _fp );
|
||||
_current = 0;
|
||||
}
|
||||
if( !_inBuffer ) return false;
|
||||
|
||||
_factory.fromBuffer( _buffer + _elementSize*_current , d );
|
||||
_current++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// BufferedBinaryOutputDataStream //
|
||||
////////////////////////////////////
|
||||
|
||||
template< typename OutputFactory >
|
||||
BufferedBinaryOutputDataStream< OutputFactory >::BufferedBinaryOutputDataStream( const char *fileName , const OutputFactory &factory , size_t bufferSize ) : _factory(factory) , _bufferSize(bufferSize) , _current(0)
|
||||
{
|
||||
if( !_bufferSize )
|
||||
{
|
||||
WARN_ONCE( "BufferSize cannot be zero , setting to one" );
|
||||
_bufferSize = 1;
|
||||
}
|
||||
_elementSize = _factory.bufferSize();
|
||||
_buffer = AllocPointer< char >( _elementSize*_bufferSize );
|
||||
_fp = fopen( fileName , "wb" );
|
||||
if( !_fp ) ERROR_OUT( "Could not open file for writing: " , fileName );
|
||||
std::vector< PlyProperty > properties( factory.plyWriteNum() );
|
||||
for( unsigned int i=0 ; i<factory.plyWriteNum() ; i++ ) properties[i] = factory.plyWriteProperty(i);
|
||||
_inset = WritePLYProperties( _fp , properties );
|
||||
}
|
||||
|
||||
template< typename OutputFactory >
|
||||
BufferedBinaryOutputDataStream< OutputFactory >::~BufferedBinaryOutputDataStream( void )
|
||||
{
|
||||
if( _current ) fwrite( _buffer , _elementSize , _current , _fp );
|
||||
FreePointer( _buffer );
|
||||
fclose( _fp );
|
||||
}
|
||||
|
||||
template< typename OutputFactory >
|
||||
void BufferedBinaryOutputDataStream< OutputFactory >::reset( void )
|
||||
{
|
||||
fseek( _fp , _inset , SEEK_SET );
|
||||
_current = 0;
|
||||
}
|
||||
|
||||
template< typename OutputFactory >
|
||||
void BufferedBinaryOutputDataStream< OutputFactory >::next( const Data &d )
|
||||
{
|
||||
if( _current==_bufferSize )
|
||||
{
|
||||
fwrite( _buffer , _elementSize , _bufferSize , _fp );
|
||||
_current = 0;
|
||||
}
|
||||
_factory.toBuffer( d , _buffer + _elementSize*_current );
|
||||
_current++;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright (c) 2023, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer. Redistributions in binary form must reproduce
|
||||
the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Johns Hopkins University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef POINT_PARTITION_CLIENT_SERVER_INCLUDED
|
||||
#define POINT_PARTITION_CLIENT_SERVER_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include "PointPartition.h"
|
||||
#include "Socket.h"
|
||||
#include "MyMiscellany.h"
|
||||
#include "CmdLineParser.h"
|
||||
|
||||
|
||||
namespace PointPartitionClientServer
|
||||
{
|
||||
template< typename Real >
|
||||
struct ClientPartitionInfo
|
||||
{
|
||||
std::string in , tempDir , outDir , outHeader;
|
||||
unsigned int slabs , filesPerDir , bufferSize , clientCount;
|
||||
Real scale;
|
||||
bool verbose;
|
||||
|
||||
ClientPartitionInfo( void );
|
||||
ClientPartitionInfo( BinaryStream &stream );
|
||||
|
||||
void write( BinaryStream &stream ) const;
|
||||
};
|
||||
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
std::pair< PointPartition::PointSetInfo< Real , Dim > , PointPartition::Partition > RunServer
|
||||
(
|
||||
std::vector< Socket > &clientSockets ,
|
||||
ClientPartitionInfo< Real > clientPartitionInfo ,
|
||||
bool loadBalance
|
||||
);
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
void RunClients( std::vector< Socket > &serverSockets );
|
||||
|
||||
#include "PointPartitionClientServer.inl"
|
||||
}
|
||||
|
||||
#endif // POINT_PARTITION_CLIENT_SERVER_INCLUDED
|
||||
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
Copyright (c) 2023, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer. Redistributions in binary form must reproduce
|
||||
the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Johns Hopkins University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
size_t _SampleCount( std::string in , std::vector< PlyProperty > &auxProperties )
|
||||
{
|
||||
char *ext = GetFileExtension( in.c_str() );
|
||||
if( strcasecmp( ext , "ply" ) ) ERROR_OUT( "Only .ply files supported: " , in );
|
||||
delete[] ext;
|
||||
|
||||
size_t vNum;
|
||||
typedef VertexFactory::Factory< Real , typename VertexFactory::PositionFactory< Real , Dim > , typename VertexFactory::NormalFactory< Real , Dim > > Factory;
|
||||
Factory factory;
|
||||
bool *readFlags = new bool[ factory.plyReadNum() ];
|
||||
int fileType = PLY::ReadVertexHeader( in , factory , readFlags , auxProperties , vNum );
|
||||
if( fileType==PLY_ASCII ) ERROR_OUT( "Point set must be in binary format" );
|
||||
if( !factory.template plyValidReadProperties<0>( readFlags ) ) ERROR_OUT( "Ply file does not contain positions" );
|
||||
if( !factory.template plyValidReadProperties<1>( readFlags ) ) ERROR_OUT( "Ply file does not contain normals" );
|
||||
delete[] readFlags;
|
||||
return vNum;
|
||||
}
|
||||
|
||||
template< typename Factory , typename VertexFunctor /* = std::function< void ( Factory::VertexType ) > */ >
|
||||
void _ProcessPLY( std::string in , std::pair< size_t , size_t > range , const Factory &factory , VertexFunctor vf )
|
||||
{
|
||||
using Vertex = typename Factory::VertexType;
|
||||
std::vector< std::string > elist = { std::string( "vertex" ) };
|
||||
|
||||
float version;
|
||||
int file_type;
|
||||
|
||||
PlyFile *ply = PlyFile::Read( in , elist , file_type , version );
|
||||
if( !ply ) ERROR_OUT( "Could not create ply file for reading: " , in );
|
||||
if( file_type==PLY_ASCII ) ERROR_OUT( "Only binary file type supported" );
|
||||
|
||||
size_t vCount;
|
||||
std::vector< PlyProperty > plist = ply->get_element_description( std::string( "vertex" ) , vCount );
|
||||
if( !plist.size() ) ERROR_OUT( "Could not read element properties: vertex" );
|
||||
if( range.second==-1 ) range.second = vCount;
|
||||
if( range.first>=range.second ) ERROR_OUT( "Bad Range: [ " , range.first , " , " , range.second , " )" );
|
||||
if( range.second>vCount )
|
||||
{
|
||||
WARN( "Max range too large, resetting" );
|
||||
range.second = vCount;
|
||||
}
|
||||
|
||||
size_t leftToReadCount = range.second - range.first;
|
||||
size_t vSize = factory.isStaticallyAllocated() ? sizeof( Vertex ) : factory.bufferSize();
|
||||
|
||||
for( unsigned int i=0 ; i<factory.plyReadNum() ; i++)
|
||||
{
|
||||
PlyProperty prop = factory.isStaticallyAllocated() ? factory.plyStaticReadProperty(i) : factory.plyReadProperty(i);
|
||||
ply->get_property( std::string( "vertex" ) , &prop );
|
||||
}
|
||||
|
||||
size_t sizeOnDisk = 0;
|
||||
for( unsigned int i=0 ; i<plist.size() ; i++ ) sizeOnDisk += ply_type_size[ plist[i].external_type ];
|
||||
|
||||
#if defined( _WIN32 ) || defined( _WIN64 )
|
||||
_fseeki64( ply->fp , sizeOnDisk * range.first , SEEK_CUR );
|
||||
#else // !_WIN32 && !_WIN64
|
||||
fseek( ply->fp , sizeOnDisk * range.first , SEEK_CUR );
|
||||
#endif // _WIN32 || _WIN64
|
||||
|
||||
Vertex vertex = factory();
|
||||
Pointer( char ) buffer = NewPointer< char >( factory.bufferSize() );
|
||||
for( size_t i=range.first ; i<range.second ; i++ )
|
||||
{
|
||||
if( factory.isStaticallyAllocated() ) ply->get_element( (void *)&vertex );
|
||||
else
|
||||
{
|
||||
ply->get_element( PointerAddress( buffer ) );
|
||||
factory.fromBuffer( buffer , vertex );
|
||||
}
|
||||
vf( vertex );
|
||||
}
|
||||
DeletePointer( buffer );
|
||||
|
||||
delete ply;
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim , typename Factory >
|
||||
void _MergeSlabs( std::string inDir , std::string outDir , std::string header , unsigned int clientCount , std::pair< unsigned int , unsigned int > slabRange , unsigned int slabs , unsigned int filesPerDir , const Factory &factory , size_t bufferSize )
|
||||
{
|
||||
using Vertex = typename Factory::VertexType;
|
||||
|
||||
Vertex v = factory();
|
||||
|
||||
for( unsigned int s=slabRange.first ; s<slabRange.second ; s++ )
|
||||
{
|
||||
std::string outFileName = PointPartition::FileName( outDir , header , s , slabs , filesPerDir );
|
||||
PointPartition::BufferedBinaryOutputDataStream< Factory > outStream( outFileName.c_str() , factory , bufferSize );
|
||||
for( unsigned int c=0 ; c<clientCount ; c++ )
|
||||
{
|
||||
std::string inFileName = PointPartition::FileName( inDir , header , c , s , slabs , filesPerDir );
|
||||
PointPartition::BufferedBinaryInputDataStream< Factory > inStream( inFileName.c_str() , factory , bufferSize );
|
||||
while( inStream.next( v ) ) outStream.next( v );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim , typename Factory >
|
||||
std::vector< size_t > _PartitionIntoSlabs( std::string in , std::string dir , std::string header , unsigned int clientIndex , std::pair< size_t , size_t > range , unsigned int slabs , unsigned int filesPerDir , XForm< Real , Dim+1 > xForm , const Factory &factory , size_t bufferSize )
|
||||
{
|
||||
using Vertex = typename Factory::VertexType;
|
||||
using _XForm = typename Factory::Transform;
|
||||
|
||||
_XForm _xForm(xForm);
|
||||
std::vector< size_t > slabSizes( slabs , 0 );
|
||||
|
||||
using OutputPointStream = OutputDataStream< Vertex >;
|
||||
|
||||
std::vector< OutputPointStream * > outStreams( slabs );
|
||||
for( unsigned int s=0 ; s<slabs ; s++ )
|
||||
{
|
||||
std::string fileName = PointPartition::FileName( dir , header , clientIndex , s , slabs , filesPerDir );
|
||||
outStreams[s] = new PointPartition::BufferedBinaryOutputDataStream< Factory >( fileName.c_str() , factory , bufferSize );
|
||||
}
|
||||
|
||||
size_t outOfRangeCount = 0;
|
||||
auto vertexFunctor = [&]( Vertex v )
|
||||
{
|
||||
_xForm.inPlace( v );
|
||||
Point< Real , Dim > p = v.template get<0>();
|
||||
int slab = (int)floor( p[Dim-1] * slabs );
|
||||
if( slab>=0 && slab<(int)slabs )
|
||||
{
|
||||
outStreams[slab]->next( v );
|
||||
slabSizes[slab]++;
|
||||
}
|
||||
else outOfRangeCount++;
|
||||
};
|
||||
_ProcessPLY( in , range , factory , vertexFunctor );
|
||||
for( unsigned int i=0 ; i<slabs ; i++ ) delete outStreams[i];
|
||||
if( outOfRangeCount ) WARN( "Out of range count: " , outOfRangeCount );
|
||||
return slabSizes;
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim , typename Factory >
|
||||
PointPartition::Extent< Real > _GetExtent( std::string in , std::pair< size_t , size_t > range , const Factory &factory )
|
||||
{
|
||||
using Vertex = typename Factory::VertexType;
|
||||
PointPartition::Extent< Real > extent;
|
||||
_ProcessPLY( in , range , factory , [&]( const Vertex &vertex ){ extent.add( vertex.template get<0>() ); } );
|
||||
return extent;
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
std::vector< PlyProperty > _GetUnprocessedProperties( std::string in )
|
||||
{
|
||||
char *ext = GetFileExtension( in.c_str() );
|
||||
if( strcasecmp( ext , "ply" ) ) ERROR_OUT( "Expected .ply file" );
|
||||
delete[] ext;
|
||||
|
||||
std::vector< PlyProperty > unprocessedProperties;
|
||||
{
|
||||
typedef VertexFactory::Factory< Real , typename VertexFactory::PositionFactory< Real , Dim > , typename VertexFactory::NormalFactory< Real , Dim > > Factory;
|
||||
Factory factory;
|
||||
bool *readFlags = new bool[ factory.plyReadNum() ];
|
||||
PLY::ReadVertexHeader( in , factory , readFlags , unprocessedProperties );
|
||||
if( !factory.template plyValidReadProperties<0>( readFlags ) ) ERROR_OUT( "Ply file does not contain positions" );
|
||||
if( !factory.template plyValidReadProperties<1>( readFlags ) ) ERROR_OUT( "Ply file does not contain normals" );
|
||||
delete[] readFlags;
|
||||
}
|
||||
return unprocessedProperties;
|
||||
}
|
||||
|
||||
////////////
|
||||
// Server //
|
||||
////////////
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
std::pair< PointPartition::PointSetInfo< Real , Dim > , PointPartition::Partition > RunServer
|
||||
(
|
||||
std::vector< Socket > &clientSockets ,
|
||||
ClientPartitionInfo< Real > clientPartitionInfo ,
|
||||
bool loadBalance
|
||||
)
|
||||
{
|
||||
Timer timer;
|
||||
clientPartitionInfo.clientCount = ( unsigned int )clientSockets.size();
|
||||
for( unsigned int c=0 ; c<clientSockets.size() ; c++ )
|
||||
{
|
||||
SocketStream clientSocketStream( clientSockets[c] );
|
||||
clientPartitionInfo.write( clientSocketStream );
|
||||
}
|
||||
for( unsigned int c=0 ; c<clientSockets.size() ; c++ ) SocketStream( clientSockets[c] ).write( c );
|
||||
|
||||
PointPartition::PointSetInfo< Real , Dim > pointSetInfo( clientPartitionInfo.slabs );
|
||||
pointSetInfo.header = clientPartitionInfo.outHeader;
|
||||
pointSetInfo.filesPerDir = clientPartitionInfo.filesPerDir;
|
||||
|
||||
// Create the directory for the slabs
|
||||
PointPartition::CreatePointSlabDirs( PointPartition::FileDir( clientPartitionInfo.outDir , clientPartitionInfo.outHeader ) , clientPartitionInfo.slabs , clientPartitionInfo.filesPerDir );
|
||||
|
||||
/////////////
|
||||
// Phase 1 //
|
||||
/////////////
|
||||
// Get the number of samples
|
||||
size_t sampleCount = _SampleCount< Real , Dim >( clientPartitionInfo.in , pointSetInfo.auxiliaryProperties );
|
||||
if( clientPartitionInfo.verbose ) std::cout << "Samples: " << sampleCount << std::endl;
|
||||
|
||||
// Send the partitions to the clients
|
||||
for( unsigned int c=0 ; c<clientSockets.size() ; c++ )
|
||||
{
|
||||
size_t start = ( sampleCount * c )/clientSockets.size();
|
||||
size_t end = ( sampleCount * (c+1) )/clientSockets.size();
|
||||
if( clientPartitionInfo.verbose ) std::cout << "[ " << start << " , " << end << " )" << std::endl;
|
||||
SocketStream( clientSockets[c] ).write( std::make_pair( start , end ) );
|
||||
}
|
||||
|
||||
/////////////
|
||||
// Phase 2 //
|
||||
/////////////
|
||||
// Merge the clients' extents and get the direction of maximal extent
|
||||
PointPartition::Extent< Real > e;
|
||||
unsigned int idx;
|
||||
{
|
||||
for( unsigned int c=0 ; c<clientSockets.size() ; c++ )
|
||||
{
|
||||
PointPartition::Extent< Real > _e;
|
||||
SocketStream( clientSockets[c] ).read( _e );
|
||||
e = e + _e;
|
||||
}
|
||||
idx = 0;
|
||||
for( unsigned int d=1 ; d<PointPartition::Extent< Real >::DirectionN ; d++ ) if( e.extents[d].second - e.extents[d].first > e.extents[idx].second - e.extents[idx].first ) idx = d;
|
||||
}
|
||||
|
||||
// Compute the transformation taking the points to the unit cube
|
||||
{
|
||||
XForm< Real , Dim+1 > R = XForm< Real , Dim+1 >::Identity();
|
||||
for( unsigned int c=0 ; c<Dim ; c++ ) for( unsigned int r=0 ; r<Dim ; r++ ) R(r,c) = PointPartition::Extent< Real >::Directions[ PointPartition::Extent< Real >::Frames[idx][c] ][r];
|
||||
|
||||
Point< Real , Dim > bBox[2];
|
||||
for( unsigned int d=0 ; d<3 ; d++ ) bBox[0][d] = e.extents[ PointPartition::Extent< Real >::Frames[idx][d] ].first , bBox[1][d] = e.extents[ PointPartition::Extent< Real >::Frames[idx][d] ].second;
|
||||
|
||||
pointSetInfo.modelToUnitCube = GetBoundingBoxXForm( bBox[0] , bBox[1] , clientPartitionInfo.scale ) * R;
|
||||
}
|
||||
|
||||
// Send the transformation to the clients
|
||||
for( unsigned int c=0 ; c<clientSockets.size() ; c++ ) SocketStream( clientSockets[c] ).write( pointSetInfo.modelToUnitCube );
|
||||
|
||||
/////////////
|
||||
// Phase 3 //
|
||||
/////////////
|
||||
pointSetInfo.pointsPerSlab.resize( clientPartitionInfo.slabs , 0 );
|
||||
for( unsigned int c=0 ; c<clientSockets.size() ; c++ )
|
||||
{
|
||||
std::vector< size_t > slabSizes;
|
||||
SocketStream( clientSockets[c] ).read( slabSizes );
|
||||
if( slabSizes.size()!=clientPartitionInfo.slabs ) ERROR_OUT( "Unexpected number of slabs: " , slabSizes.size() , " != " , clientPartitionInfo.slabs );
|
||||
for( unsigned int i=0 ; i<clientPartitionInfo.slabs ; i++ ) pointSetInfo.pointsPerSlab[i] += slabSizes[i];
|
||||
}
|
||||
if( clientPartitionInfo.verbose )
|
||||
{
|
||||
std::cout << "Partitions:" << std::endl;
|
||||
for( unsigned int i=0 ; i<pointSetInfo.pointsPerSlab.size() ; i++ ) std::cout << "\t" << i << "] " << pointSetInfo.pointsPerSlab[i] << std::endl;
|
||||
}
|
||||
|
||||
// Compute the assignment of slabs to clients
|
||||
PointPartition::Partition pointPartition( (unsigned int)clientSockets.size() , pointSetInfo.pointsPerSlab );
|
||||
if( loadBalance ) pointPartition.optimize( true );
|
||||
for( unsigned int c=0 ; c<clientSockets.size() ; c++ )
|
||||
{
|
||||
std::pair< unsigned int , unsigned int > range = pointPartition.range( c );
|
||||
if( clientPartitionInfo.verbose ) std::cout << "Range[ " << c << " ]: [ " << range.first << " , " << range.second << " )" << std::endl;
|
||||
SocketStream( clientSockets[c] ).write( range );
|
||||
}
|
||||
|
||||
// Check that the clients are done
|
||||
for( unsigned int c=0 ; c<clientSockets.size() ; c++ )
|
||||
{
|
||||
unsigned int done;
|
||||
SocketStream( clientSockets[c] ).read( done );
|
||||
}
|
||||
|
||||
// Let the clients know that everybody else is done so they can clean up the temporary files
|
||||
for( unsigned int c=0 ; c<clientSockets.size() ; c++ )
|
||||
{
|
||||
unsigned int done = 1;
|
||||
SocketStream( clientSockets[c] ).write( done );
|
||||
}
|
||||
|
||||
return std::make_pair( pointSetInfo , pointPartition );
|
||||
}
|
||||
|
||||
|
||||
////////////
|
||||
// Client //
|
||||
////////////
|
||||
|
||||
template< typename Real , unsigned int Dim , typename Factory >
|
||||
void _RunClients
|
||||
(
|
||||
ClientPartitionInfo< Real > clientPartitionInfo ,
|
||||
const Factory &factory ,
|
||||
std::vector< Socket > &serverSockets
|
||||
)
|
||||
{
|
||||
std::vector< unsigned int > clientIndices( serverSockets.size() );
|
||||
|
||||
for( unsigned int c=0 ; c<serverSockets.size() ; c++ ) SocketStream( serverSockets[c] ).read( clientIndices[c] );
|
||||
|
||||
int maxFiles = 2*clientPartitionInfo.slabs;
|
||||
#ifdef _WIN32
|
||||
if( _setmaxstdio( maxFiles )!=maxFiles ) ERROR_OUT( "Could not set max file handles: " , maxFiles );
|
||||
#else // !_WIN32
|
||||
struct rlimit rl;
|
||||
getrlimit( RLIMIT_NOFILE , &rl );
|
||||
rl.rlim_cur = maxFiles+3;
|
||||
setrlimit( RLIMIT_NOFILE , &rl );
|
||||
#endif // _WIN32
|
||||
|
||||
for( unsigned int i=0 ; i<serverSockets.size() ; i++ ) PointPartition::CreatePointSlabDirs( PointPartition::FileDir( clientPartitionInfo.tempDir , clientPartitionInfo.outHeader , clientIndices[i] ) , clientPartitionInfo.slabs , clientPartitionInfo.filesPerDir );
|
||||
|
||||
/////////////
|
||||
// Phase 1 //
|
||||
/////////////
|
||||
std::vector< std::pair< size_t , size_t > > ranges( serverSockets.size() );
|
||||
for( unsigned int i=0 ; i<serverSockets.size() ; i++ )
|
||||
{
|
||||
// Get the client's range
|
||||
SocketStream( serverSockets[i] ).read( ranges[i] );
|
||||
if( clientPartitionInfo.verbose ) std::cout << "Got range: " << MemoryInfo::PeakMemoryUsageMB() << " (MB)" << std::endl;
|
||||
// Get the extent and send to the client
|
||||
PointPartition::Extent< Real > e = _GetExtent< Real , Dim >( clientPartitionInfo.in , ranges[i] , factory );
|
||||
SocketStream( serverSockets[i] ).write( e );
|
||||
if( clientPartitionInfo.verbose ) std::cout << "Sent extent: " << MemoryInfo::PeakMemoryUsageMB() << " (MB)" << std::endl;
|
||||
}
|
||||
|
||||
/////////////
|
||||
// Phase 2 //
|
||||
/////////////
|
||||
for( unsigned int i=0 ; i<serverSockets.size() ; i++ )
|
||||
{
|
||||
XForm< Real , Dim+1 > xForm;
|
||||
SocketStream( serverSockets[i] ).read( xForm );
|
||||
if( clientPartitionInfo.verbose ) std::cout << "Got transform: " << MemoryInfo::PeakMemoryUsageMB() << " (MB)" << std::endl;
|
||||
|
||||
PointPartition::CreatePointSlabDirs( PointPartition::FileDir( clientPartitionInfo.tempDir , clientPartitionInfo.outHeader , clientIndices[i] ) , clientPartitionInfo.slabs , clientPartitionInfo.filesPerDir );
|
||||
std::vector< size_t > slabSizes = _PartitionIntoSlabs< Real , Dim >( clientPartitionInfo.in , clientPartitionInfo.tempDir , clientPartitionInfo.outHeader , clientIndices[i] , ranges[i] , clientPartitionInfo.slabs , clientPartitionInfo.filesPerDir , xForm , factory , clientPartitionInfo.bufferSize );
|
||||
SocketStream( serverSockets[i] ).write( slabSizes );
|
||||
if( clientPartitionInfo.verbose ) std::cout << "Wrote slab sizes: " << MemoryInfo::PeakMemoryUsageMB() << " (MB)" << std::endl;
|
||||
}
|
||||
|
||||
/////////////
|
||||
// Phase 3 //
|
||||
/////////////
|
||||
for( unsigned int i=0 ; i<serverSockets.size() ; i++ )
|
||||
{
|
||||
std::pair< unsigned int , unsigned int > slabRange;
|
||||
SocketStream( serverSockets[i] ).read( slabRange );
|
||||
if( clientPartitionInfo.verbose ) std::cout << "Slab range: [ " << slabRange.first << " , " << slabRange.second << " )" << std::endl;
|
||||
_MergeSlabs< Real , Dim >( clientPartitionInfo.tempDir , clientPartitionInfo.outDir , clientPartitionInfo.outHeader , clientPartitionInfo.clientCount , slabRange , clientPartitionInfo.slabs , clientPartitionInfo.filesPerDir , factory , clientPartitionInfo.bufferSize );
|
||||
if( clientPartitionInfo.verbose ) std::cout << "Merged slabs: " << MemoryInfo::PeakMemoryUsageMB() << " (MB)" << std::endl;
|
||||
|
||||
// Notify the server that you're done
|
||||
unsigned int done = 1;
|
||||
SocketStream( serverSockets[i] ).write( done );
|
||||
}
|
||||
|
||||
for( unsigned int i=0 ; i<serverSockets.size() ; i++ )
|
||||
{
|
||||
// Confirm that all the other clients are done and clean up
|
||||
unsigned int done = 1;
|
||||
SocketStream( serverSockets[i] ).read( done );
|
||||
|
||||
PointPartition::RemovePointSlabDirs( PointPartition::FileDir( clientPartitionInfo.tempDir , clientPartitionInfo.outHeader , clientIndices[i] ) );
|
||||
}
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
void RunClients( std::vector< Socket > &serverSockets )
|
||||
{
|
||||
ClientPartitionInfo< Real > clientPartitionInfo;
|
||||
for( unsigned int i=0 ; i<serverSockets.size() ; i++ )
|
||||
{
|
||||
SocketStream serverSocketStream( serverSockets[i] );
|
||||
clientPartitionInfo = ClientPartitionInfo< Real >( serverSocketStream );
|
||||
}
|
||||
std::vector< PlyProperty > unprocessedProperties = _GetUnprocessedProperties< Real , Dim >( clientPartitionInfo.in );
|
||||
|
||||
if( unprocessedProperties.size() )
|
||||
{
|
||||
typedef VertexFactory::Factory< Real , VertexFactory::PositionFactory< Real , Dim > , VertexFactory::NormalFactory< Real , Dim > , VertexFactory::DynamicFactory< Real > > Factory;
|
||||
VertexFactory::PositionFactory< Real , Dim > vFactory;
|
||||
VertexFactory::NormalFactory< Real , Dim > nFactory;
|
||||
VertexFactory::DynamicFactory< Real > dFactory( unprocessedProperties );
|
||||
Factory factory( vFactory , nFactory , dFactory );
|
||||
_RunClients< Real , Dim >( clientPartitionInfo , factory , serverSockets );
|
||||
}
|
||||
else
|
||||
{
|
||||
typedef VertexFactory::Factory< Real , VertexFactory::PositionFactory< Real , Dim > , VertexFactory::NormalFactory< Real , Dim > > Factory;
|
||||
Factory factory;
|
||||
_RunClients< Real , Dim >( clientPartitionInfo , factory , serverSockets );
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
// ClientPartitionInfo //
|
||||
/////////////////////////
|
||||
template< typename Real >
|
||||
ClientPartitionInfo< Real >::ClientPartitionInfo( void ) : scale((Real)1.1) , verbose(false) , slabs(0) , filesPerDir(-1) , bufferSize(BUFFER_IO) , clientCount(0) {}
|
||||
|
||||
template< typename Real >
|
||||
ClientPartitionInfo< Real >::ClientPartitionInfo( BinaryStream &stream )
|
||||
{
|
||||
auto ReadBool = [&]( bool &b )
|
||||
{
|
||||
char _b;
|
||||
if( !stream.read( _b ) ) return false;
|
||||
b = _b!=0;
|
||||
return true;
|
||||
};
|
||||
if( !stream.read( in ) ) ERROR_OUT( "Failed to read in" );
|
||||
if( !stream.read( tempDir ) ) ERROR_OUT( "Failed to read temp dir" );
|
||||
if( !stream.read( outDir ) ) ERROR_OUT( "Failed to read out dir" );
|
||||
if( !stream.read( outHeader ) ) ERROR_OUT( "Failed to read out header" );
|
||||
if( !stream.read( slabs ) ) ERROR_OUT( "Failed to read slabs" );
|
||||
if( !stream.read( filesPerDir ) ) ERROR_OUT( "Failed to read files per dir" );
|
||||
if( !stream.read( bufferSize ) ) ERROR_OUT( "Failed to read buffer size" );
|
||||
if( !stream.read( scale ) ) ERROR_OUT( "Failed to read scale" );
|
||||
if( !stream.read( clientCount ) ) ERROR_OUT( "Failed to read client count" );
|
||||
if( !ReadBool( verbose ) ) ERROR_OUT( "Failed to read verbose flag" );
|
||||
}
|
||||
|
||||
template< typename Real >
|
||||
void ClientPartitionInfo< Real >::write( BinaryStream &stream ) const
|
||||
{
|
||||
auto WriteBool = [&]( bool b )
|
||||
{
|
||||
char _b = b ? 1 : 0;
|
||||
stream.write( _b );
|
||||
};
|
||||
stream.write( in );
|
||||
stream.write( tempDir );
|
||||
stream.write( outDir );
|
||||
stream.write( outHeader );
|
||||
stream.write( slabs );
|
||||
stream.write( filesPerDir );
|
||||
stream.write( bufferSize );
|
||||
stream.write( scale );
|
||||
stream.write( clientCount );
|
||||
WriteBool( verbose );
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2022, Michael Kazhdan and Matthew Bolitho
|
||||
Copyright (c) 2023, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -38,7 +38,7 @@ DAMAGE.
|
||||
#define WEIGHT_DEGREE 2 // The order of the B-Spline used to splat in the weights for density estimation
|
||||
#define NORMAL_DEGREE 2 // The order of the B-Spline used to splat in the normals for constructing the Laplacian constraints
|
||||
#define DEFAULT_FEM_DEGREE 1 // The default finite-element degree
|
||||
#define DEFAULT_FEM_BOUNDARY BOUNDARY_NEUMANN // The default finite-element boundary type
|
||||
#define DEFAULT_FEM_BOUNDARY BOUNDARY_NEUMANN // The default finite-element boundary type {BOUNDARY_FREE, BOUNDARY_DIRICHLET, BOUNDARY_NEUMANN}
|
||||
#define DEFAULT_DIMENSION 3 // The dimension of the system
|
||||
|
||||
const float DefaultPointWeightMultiplier = 2.f;
|
||||
|
||||
@@ -0,0 +1,744 @@
|
||||
/*
|
||||
Copyright (c) 2023, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer. Redistributions in binary form must reproduce
|
||||
the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Johns Hopkins University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
template< typename Real , unsigned int Dim , BoundaryType BType , unsigned int Degree >
|
||||
struct Server
|
||||
{
|
||||
typedef typename FEMTree< Dim , Real >::template DensityEstimator< WEIGHT_DEGREE > DensityEstimator;
|
||||
typedef typename FEMTree< Dim , Real >::template ApproximatePointInterpolationInfo< Real , 0 , ConstraintDual< Dim , Real > , SystemDual< Dim , Real > > ApproximatePointInterpolationInfo;
|
||||
typedef IsotropicUIntPack< Dim , FEMDegreeAndBType< Degree , BType >::Signature > Sigs;
|
||||
typedef IsotropicUIntPack< Dim , Degree > Degrees;
|
||||
typedef IsotropicUIntPack< Dim , FEMDegreeAndBType< NORMAL_DEGREE , DerivativeBoundary< BType , 1 >::BType >::Signature > NormalSigs;
|
||||
static const unsigned int DataSig = FEMDegreeAndBType< DATA_DEGREE , BOUNDARY_FREE >::Signature;
|
||||
typedef VertexFactory::DynamicFactory< Real > AuxDataFactory;
|
||||
typedef VertexFactory::Factory< Real , VertexFactory::PositionFactory< Real , Dim > , VertexFactory::Factory< Real , VertexFactory::NormalFactory< Real , Dim > , AuxDataFactory > > InputSampleFactory;
|
||||
typedef VertexFactory::Factory< Real , VertexFactory::NormalFactory< Real , Dim > , AuxDataFactory > InputSampleDataFactory;
|
||||
typedef InputOrientedPointStreamInfo< Real , Dim , typename AuxDataFactory::VertexType > InputPointStreamInfo;
|
||||
typedef typename InputPointStreamInfo::PointAndDataType InputSampleType;
|
||||
typedef typename InputPointStreamInfo::DataType InputSampleDataType;
|
||||
typedef InputDataStream< InputSampleType > InputPointStream;
|
||||
typedef RegularTreeNode< Dim , FEMTreeNodeData , depth_and_offset_type > FEMTreeNode;
|
||||
|
||||
protected:
|
||||
std::vector< SocketStream > _clientSockets;
|
||||
PointPartition::PointSetInfo< Real , Dim > _pointSetInfo;
|
||||
PointPartition::Partition _pointPartition;
|
||||
|
||||
struct _State4
|
||||
{
|
||||
FEMTree< Dim , Real > tree;
|
||||
DenseNodeData< Real , Sigs > constraints , solution;
|
||||
ApproximatePointInterpolationInfo *iInfo;
|
||||
SparseNodeData< ProjectiveData< InputSampleDataType , Real > , IsotropicUIntPack< Dim , DataSig > > *dataField;
|
||||
|
||||
_State4( void ) : tree( MEMORY_ALLOCATOR_BLOCK_SIZE ) , iInfo(NULL) , dataField(NULL) {}
|
||||
~_State4( void ){ delete iInfo ; delete dataField; }
|
||||
};
|
||||
struct _State6
|
||||
{
|
||||
using SliceSigs = typename Sigs::Reverse::Rest::Reverse;
|
||||
using Vertex = typename VertexFactory::PositionFactory< Real , Dim-1 >::VertexType;
|
||||
FEMTree< Dim-1 , Real > *sliceTree;
|
||||
XForm< Real , Dim > xForm;
|
||||
DenseNodeData< Real , SliceSigs > solution , dSolution;
|
||||
std::vector< typename LevelSetExtractor< Dim-1 , Real , Vertex >::SliceValues > sliceValues , dSliceValues;
|
||||
std::vector< Point< Real , Dim-1 > > vertices;
|
||||
|
||||
_State6( void ) : sliceTree(NULL) {}
|
||||
~_State6( void ){ delete sliceTree; }
|
||||
};
|
||||
|
||||
PhaseInfo _phase0( const ClientReconstructionInfo< Real , Dim > &clientReconInfo , Profiler &profiler );
|
||||
PhaseInfo _phase2( const ClientReconstructionInfo< Real , Dim > &clientReconInfo , ProjectiveData< Real , Real > &cumulativePointWeight , Profiler &profiler );
|
||||
PhaseInfo _phase4( const ClientReconstructionInfo< Real , Dim > &clientReconInfo , ProjectiveData< Real , Real > cumulativePointWeight , unsigned int baseVCycles , Real &isoValue , Profiler &profiler );
|
||||
PhaseInfo _phase6( const ClientReconstructionInfo< Real , Dim > &clientReconInfo , Real isoValue , bool showDiscontinuity , bool outputBoundarySlices , std::vector< unsigned int > &sharedVertexCounts , Profiler &profiler );
|
||||
|
||||
template< typename _Real , unsigned int _Dim , BoundaryType _BType , unsigned int _Degree >
|
||||
friend std::vector< unsigned int > RunServer( PointPartition::PointSetInfo< _Real , _Dim > , PointPartition::Partition , std::vector< Socket > , ClientReconstructionInfo< _Real , _Dim > , unsigned int , unsigned int , bool , bool );
|
||||
};
|
||||
|
||||
|
||||
template< typename Real , unsigned int Dim , BoundaryType BType , unsigned int Degree >
|
||||
static std::vector< unsigned int > RunServer
|
||||
(
|
||||
PointPartition::PointSetInfo< Real , Dim > pointSetInfo ,
|
||||
PointPartition::Partition pointPartition ,
|
||||
std::vector< Socket > clientSockets ,
|
||||
ClientReconstructionInfo< Real , Dim > clientReconInfo ,
|
||||
unsigned int baseVCycles ,
|
||||
unsigned int sampleMS ,
|
||||
bool showDiscontinuity ,
|
||||
bool outputBoundarySlices
|
||||
)
|
||||
{
|
||||
std::vector< unsigned int > sharedVertexCounts;
|
||||
Server< Real , Dim , BType , Degree > server;
|
||||
Profiler profiler( sampleMS );
|
||||
|
||||
clientReconInfo.auxProperties = pointSetInfo.auxiliaryProperties;
|
||||
|
||||
// Initialization
|
||||
{
|
||||
server._pointSetInfo = pointSetInfo;
|
||||
server._pointPartition = pointPartition;
|
||||
server._clientSockets.resize( clientSockets.size() );
|
||||
|
||||
for( unsigned int i=0 ; i<clientSockets.size() ; i++ ) server._clientSockets[i] = SocketStream( clientSockets[i] );
|
||||
|
||||
for( unsigned int i=0 ; i<clientSockets.size() ; i++ ) clientReconInfo.write( server._clientSockets[i] );
|
||||
for( unsigned int i=0 ; i<clientSockets.size() ; i++ ) server._clientSockets[i].write( i );
|
||||
}
|
||||
|
||||
if( clientReconInfo.verbose>1 )
|
||||
{
|
||||
for( unsigned int i=0 ; i<clientSockets.size() ; i++ )
|
||||
{
|
||||
#ifdef ADAPTIVE_PADDING
|
||||
std::pair< unsigned int , unsigned int > range = pointPartition.range( i );
|
||||
if( range.first<clientReconInfo.padSize ) range.first = 0;
|
||||
else range.first -= clientReconInfo.padSize;
|
||||
if( range.second+clientReconInfo.padSize>pointPartition.slabs() ) range.second = pointPartition.slabs();
|
||||
else range.second += clientReconInfo.padSize;
|
||||
#else // !ADAPTIVE_PADDING
|
||||
std::pair< unsigned int , unsigned int > range = pointPartition.range( i , clientReconInfo.padSize );
|
||||
#endif // ADAPTIVE_PADDING
|
||||
std::cout << "Range[ " << i << " ]: [ " << range.first << " , " << range.second << " )" << std::endl;
|
||||
}
|
||||
std::cout << "Boundary-type = " << BoundaryNames[BType] << " ; Degree = " << Degree << std::endl;
|
||||
}
|
||||
|
||||
ProjectiveData< Real , Real > cumulativePointWeight;
|
||||
Real isoValue;
|
||||
|
||||
// [PHASE 0] Send the client initial information
|
||||
{
|
||||
profiler.reset();
|
||||
PhaseInfo phaseInfo = server._phase0( clientReconInfo , profiler );
|
||||
if( clientReconInfo.verbose>0 )
|
||||
{
|
||||
StreamFloatPrecision sfp( std::cout , 1 );
|
||||
std::cout << SendDataString( 0 , phaseInfo.writeBytes ) << phaseInfo.writeTime << " (s)" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// [PHASE 2] Accumulate/Send the point weight
|
||||
{
|
||||
profiler.reset();
|
||||
PhaseInfo phaseInfo = server._phase2( clientReconInfo , cumulativePointWeight , profiler );
|
||||
if( clientReconInfo.verbose>0 )
|
||||
{
|
||||
StreamFloatPrecision sfp( std::cout , 1 );
|
||||
std::cout << ReceiveDataString( 2 , phaseInfo.readBytes ) << phaseInfo.readTime << " (s)" << std::endl;
|
||||
std::cout << "[PROCESS 2] : " << phaseInfo.processTime << " (s), " << profiler(false) << std::endl;
|
||||
std::cout << SendDataString( 2 , phaseInfo.writeBytes ) << phaseInfo.writeTime << " (s)" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// [PHASE 4] Accumulate/solve/send coarse system
|
||||
{
|
||||
profiler.reset();
|
||||
PhaseInfo phaseInfo = server._phase4( clientReconInfo , cumulativePointWeight , baseVCycles , isoValue , profiler );
|
||||
if( clientReconInfo.verbose>0 )
|
||||
{
|
||||
StreamFloatPrecision sfp( std::cout , 1 );
|
||||
std::cout << ReceiveDataString( 4 , phaseInfo.readBytes ) << phaseInfo.readTime << " (s)" << std::endl;
|
||||
std::cout << "[PROCESS 4] : " << phaseInfo.processTime << " (s), " << profiler(false) << std::endl;
|
||||
std::cout << SendDataString( 4 , phaseInfo.writeBytes ) << phaseInfo.writeTime << " (s)" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// [PHASE 6] Accumulate/merge/send boundary tree info
|
||||
{
|
||||
profiler.reset();
|
||||
PhaseInfo phaseInfo = server._phase6( clientReconInfo , isoValue , showDiscontinuity , outputBoundarySlices , sharedVertexCounts , profiler );
|
||||
if( clientReconInfo.verbose>0 )
|
||||
{
|
||||
StreamFloatPrecision sfp( std::cout , 1 );
|
||||
std::cout << ReceiveDataString( 6 , phaseInfo.readBytes ) << phaseInfo.readTime << " (s)" << std::endl;
|
||||
std::cout << "[PROCESS 6] : " << phaseInfo.processTime << " (s), " << profiler(false) << std::endl;
|
||||
std::cout << SendDataString( 6 , phaseInfo.writeBytes ) << phaseInfo.writeTime << " (s)" << std::endl;
|
||||
}
|
||||
}
|
||||
return sharedVertexCounts;
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim , BoundaryType BType , unsigned int Degree >
|
||||
PhaseInfo Server< Real , Dim , BType , Degree >::_phase0( const ClientReconstructionInfo< Real , Dim > &clientReconInfo , Profiler &profiler )
|
||||
{
|
||||
PhaseInfo phaseInfo;
|
||||
|
||||
Timer timer;
|
||||
for( unsigned int i=0 ; i<_clientSockets.size() ; i++ )
|
||||
{
|
||||
ClientServerStream< false > clientStream( _clientSockets[i] , i , clientReconInfo );
|
||||
clientStream.ioBytes = 0;
|
||||
|
||||
// Send the information about the point-set
|
||||
clientStream.write( _pointSetInfo.modelToUnitCube );
|
||||
|
||||
// Send the client's range
|
||||
#ifdef ADAPTIVE_PADDING
|
||||
std::pair< unsigned int , unsigned int > range = _pointPartition.range( i );
|
||||
#else // !ADAPTIVE_PADDING
|
||||
std::pair< unsigned int , unsigned int > range = _pointPartition.range( i , 0 );
|
||||
#endif // ADAPTIVE_PADDING
|
||||
clientStream.write( range );
|
||||
|
||||
phaseInfo.writeBytes += clientStream.ioBytes;
|
||||
}
|
||||
phaseInfo.writeTime += timer.wallTime();
|
||||
profiler.update();
|
||||
return phaseInfo;
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim , BoundaryType BType , unsigned int Degree >
|
||||
PhaseInfo Server< Real , Dim , BType , Degree >::_phase2( const ClientReconstructionInfo< Real , Dim > &clientReconInfo , ProjectiveData< Real , Real > &cumulativePointWeight , Profiler &profiler )
|
||||
{
|
||||
PhaseInfo phaseInfo;
|
||||
std::pair< size_t , size_t > cumulativeNodeCounts;
|
||||
|
||||
|
||||
cumulativeNodeCounts = std::pair< size_t , size_t >(0,0);
|
||||
cumulativePointWeight = ProjectiveData< Real , Real >( (Real)0. );
|
||||
|
||||
for( unsigned int i=0 ; i<_clientSockets.size() ; i++ )
|
||||
{
|
||||
Timer timer;
|
||||
ProjectiveData< Real , Real > pointWeight;
|
||||
std::pair< size_t , size_t > nodeCounts;
|
||||
ClientServerStream< true > clientStream( _clientSockets[i] , i , clientReconInfo );
|
||||
clientStream.ioBytes = 0;
|
||||
clientStream.read( pointWeight );
|
||||
clientStream.read( nodeCounts );
|
||||
phaseInfo.readBytes += clientStream.ioBytes;
|
||||
phaseInfo.readTime += timer.wallTime();
|
||||
|
||||
timer = Timer();
|
||||
cumulativePointWeight += pointWeight;
|
||||
cumulativeNodeCounts.first += nodeCounts.first;
|
||||
cumulativeNodeCounts.second += nodeCounts.second;
|
||||
phaseInfo.processTime += timer.wallTime();
|
||||
}
|
||||
|
||||
Timer timer;
|
||||
for( unsigned int i=0 ; i<_clientSockets.size() ; i++ )
|
||||
{
|
||||
ClientServerStream< false > clientStream( _clientSockets[i] , i , clientReconInfo );
|
||||
clientStream.ioBytes = 0;
|
||||
clientStream.write( cumulativePointWeight );
|
||||
phaseInfo.writeBytes += clientStream.ioBytes;
|
||||
}
|
||||
phaseInfo.writeTime = timer.wallTime();
|
||||
|
||||
if( clientReconInfo.verbose>1 ) std::cout << "Redundancy: " << cumulativeNodeCounts.second << " / " << cumulativeNodeCounts.first << " = " << (double)cumulativeNodeCounts.second/cumulativeNodeCounts.first << std::endl;
|
||||
|
||||
profiler.update();
|
||||
|
||||
return phaseInfo;
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim , BoundaryType BType , unsigned int Degree >
|
||||
PhaseInfo Server< Real , Dim , BType , Degree >::_phase4( const ClientReconstructionInfo< Real , Dim > &clientReconInfo , ProjectiveData< Real , Real > cumulativePointWeight , unsigned int baseVCycles , Real &isoValue , Profiler &profiler )
|
||||
{
|
||||
constexpr int MAX_DEGREE = NORMAL_DEGREE > Degrees::Max() ? NORMAL_DEGREE : Degrees::Max();
|
||||
const int StartOffset = BSplineSupportSizes< MAX_DEGREE >::SupportStart;
|
||||
const int EndOffset = BSplineSupportSizes< MAX_DEGREE >::SupportEnd+1;
|
||||
PhaseInfo phaseInfo;
|
||||
|
||||
_State4 state4;
|
||||
|
||||
std::vector< std::vector< node_index_type > > clientsToServer( _clientSockets.size() );
|
||||
|
||||
// Initialize the tree
|
||||
{
|
||||
Timer timer;
|
||||
FEMTreeInitializer< Dim , Real >::Initialize( state4.tree.spaceRoot() , clientReconInfo.baseDepth , []( int , int[] ){ return true; } , state4.tree.nodeAllocators[0] , state4.tree.initializer() );
|
||||
|
||||
auto hasDataFunctor = []( const FEMTreeNode * ){ return false; };
|
||||
|
||||
// Set the root of the tree so we can copy constraints into it
|
||||
auto addNodeFunctor = [&]( int d , const int off[Dim] ){ return d<=(int)clientReconInfo.baseDepth; };
|
||||
state4.tree.template finalizeForMultigrid< MAX_DEGREE , Degrees::Max() >( clientReconInfo.baseDepth , addNodeFunctor , hasDataFunctor , std::make_tuple() , std::make_tuple() );
|
||||
phaseInfo.processTime += timer.wallTime();
|
||||
profiler.update();
|
||||
}
|
||||
|
||||
// Get/merge client data
|
||||
for( unsigned int i=0 ; i<_clientSockets.size() ; i++ )
|
||||
{
|
||||
Timer timer;
|
||||
|
||||
std::vector< node_index_type > &clientToServer = clientsToServer[i];
|
||||
ClientServerStream< true > clientStream( _clientSockets[i] , i , clientReconInfo , ClientReconstructionInfo< Real , Dim >::BACK );
|
||||
clientStream.ioBytes = 0;
|
||||
|
||||
// The number of nodes in the client's coarse sub-tree
|
||||
size_t subNodeCount;
|
||||
clientStream.read( subNodeCount );
|
||||
|
||||
// The nodes in the client's coarse sub-tree
|
||||
Pointer( FEMTreeNode ) subNodes = NewPointer< FEMTreeNode >( subNodeCount );
|
||||
clientStream.read( subNodes , subNodeCount );
|
||||
|
||||
phaseInfo.readBytes += clientStream.ioBytes;
|
||||
phaseInfo.readTime += timer.wallTime();
|
||||
|
||||
|
||||
timer = Timer();
|
||||
// Transform the nodes indices back to pointers
|
||||
TreeIndicesToAddresses( subNodes , subNodeCount );
|
||||
clientToServer.resize( subNodeCount , -1 );
|
||||
|
||||
// Find the map from client to index to server index and add client nodes as necessary
|
||||
std::function< void ( FEMTreeNode * , const FEMTreeNode * ) > ProcessIndices = [&]( FEMTreeNode *serverNode , const FEMTreeNode *clientNode )
|
||||
{
|
||||
if( clientNode->nodeData.nodeIndex!=-1 ) clientToServer[ clientNode->nodeData.nodeIndex ] = serverNode->nodeData.nodeIndex;
|
||||
if( clientNode->children )
|
||||
{
|
||||
if( !serverNode->children ) serverNode->template initChildren< false >( state4.tree.nodeAllocators[0] , state4.tree.initializer() );
|
||||
for( int c=0 ; c<(1<<Dim) ; c++ ) ProcessIndices( serverNode->children+c , clientNode->children+c );
|
||||
}
|
||||
};
|
||||
ProcessIndices( const_cast< FEMTreeNode * >( &state4.tree.tree() ) , &subNodes[0] );
|
||||
profiler.update();
|
||||
DeletePointer( subNodes );
|
||||
phaseInfo.processTime += timer.wallTime();
|
||||
}
|
||||
|
||||
{
|
||||
Timer timer;
|
||||
constexpr int MAX_DEGREE = NORMAL_DEGREE > Degrees::Max() ? NORMAL_DEGREE : Degrees::Max();
|
||||
auto hasDataFunctor = []( const FEMTreeNode * ){ return true; };
|
||||
auto addNodeFunctor = [&]( int d , const int off[Dim] ){ return d<=(int)clientReconInfo.baseDepth; };
|
||||
std::vector< node_index_type > newToOld = state4.tree.template finalizeForMultigrid< MAX_DEGREE , Degrees::Max() >( clientReconInfo.baseDepth , addNodeFunctor , hasDataFunctor , std::make_tuple() , std::make_tuple() );
|
||||
node_index_type idx = newToOld[0];
|
||||
for( unsigned int i=0 ; i<newToOld.size() ; i++ ) idx = std::max< node_index_type >( idx , newToOld[i] );
|
||||
idx++;
|
||||
std::vector< node_index_type > oldToNew( idx , -1 );
|
||||
for( unsigned int i=0 ; i<newToOld.size() ; i++ ) if( newToOld[i]!=-1 ) oldToNew[ newToOld[i] ] = i;
|
||||
for( unsigned int i=0 ; i<clientsToServer.size() ; i++ ) for( unsigned int j=0 ; j<clientsToServer[i].size() ; j++ ) clientsToServer[i][j] = oldToNew[ clientsToServer[i][j] ];
|
||||
phaseInfo.processTime += timer.wallTime();
|
||||
profiler.update();
|
||||
}
|
||||
|
||||
Timer timer;
|
||||
AuxDataFactory auxDataFactory( _pointSetInfo.auxiliaryProperties );
|
||||
bool needAuxData = clientReconInfo.dataX>0 && auxDataFactory.bufferSize();
|
||||
|
||||
state4.constraints = state4.tree.initDenseNodeData( Sigs() );
|
||||
|
||||
{
|
||||
Real targetValue = (Real)0.5;
|
||||
state4.iInfo = new ApproximatePointInterpolationInfo( ConstraintDual< Dim , Real >( targetValue , clientReconInfo.pointWeight * cumulativePointWeight.value() ) , SystemDual< Dim , Real >( clientReconInfo.pointWeight * cumulativePointWeight.value() ) , true );
|
||||
state4.iInfo->iData.reserve( state4.tree.nodesSize() );
|
||||
}
|
||||
|
||||
using InterpolationData = typename ApproximatePointInterpolationInfo::Data;
|
||||
auto preMergeFunctor = []( InterpolationData data ){ data.position *= data.weight ; return data; };
|
||||
auto postMergeFunctor = []( InterpolationData data ){ data.position /= data.weight ; return data; };
|
||||
|
||||
if( needAuxData )
|
||||
{
|
||||
state4.dataField = new SparseNodeData< ProjectiveData< InputSampleDataType , Real > , IsotropicUIntPack< Dim , DataSig > >();
|
||||
state4.dataField->reserve( state4.tree.nodesSize() );
|
||||
}
|
||||
phaseInfo.processTime += timer.wallTime();
|
||||
profiler.update();
|
||||
|
||||
for( unsigned int i=0 ; i<_clientSockets.size() ; i++ )
|
||||
{
|
||||
std::vector< node_index_type > &clientToServer = clientsToServer[i];
|
||||
ClientServerStream< true > clientStream( _clientSockets[i] , i , clientReconInfo , ClientReconstructionInfo< Real , Dim >::FRONT );
|
||||
clientStream.ioBytes = 0;
|
||||
|
||||
// The constraints
|
||||
{
|
||||
Timer timer;
|
||||
DenseNodeData< Real , Sigs > _constraints( clientStream );
|
||||
phaseInfo.readTime += timer.wallTime();
|
||||
|
||||
timer = Timer();
|
||||
for( unsigned int i=0 ; i<_constraints.size() ; i++ )
|
||||
if( clientToServer[i]==-1 || clientToServer[i]>=(node_index_type)state4.constraints.size() ){ WARN_ONCE( "Unmatched client node(s): " , clientToServer[i] ); }
|
||||
else state4.constraints[ clientToServer[i] ] += _constraints[i];
|
||||
phaseInfo.processTime += timer.wallTime();
|
||||
}
|
||||
|
||||
// The points
|
||||
{
|
||||
Timer timer;
|
||||
ApproximatePointInterpolationInfo _iInfo( clientStream );
|
||||
phaseInfo.readTime += timer.wallTime();
|
||||
|
||||
timer = Timer();
|
||||
state4.iInfo->iData.mergeFromTarget( _iInfo.iData , [&]( unsigned int idx ){ return clientToServer[idx]; } , preMergeFunctor );
|
||||
phaseInfo.processTime += timer.wallTime();
|
||||
}
|
||||
// The data field
|
||||
if( needAuxData )
|
||||
{
|
||||
Timer timer;
|
||||
SparseNodeData< ProjectiveData< InputSampleDataType , Real > , IsotropicUIntPack< Dim , DataSig > > *_dataField;
|
||||
if( !auxDataFactory.isStaticallyAllocated() )
|
||||
{
|
||||
ProjectiveSampleDataTypeSerializer< Real , Dim > serializer( clientReconInfo.auxProperties );
|
||||
_dataField = new SparseNodeData< ProjectiveData< InputSampleDataType , Real > , IsotropicUIntPack< Dim , DataSig > >( clientStream , serializer );
|
||||
}
|
||||
else _dataField = new SparseNodeData< ProjectiveData< InputSampleDataType , Real > , IsotropicUIntPack< Dim , DataSig > >( clientStream );
|
||||
phaseInfo.readTime += timer.wallTime();
|
||||
|
||||
timer = Timer();
|
||||
state4.dataField->mergeFromTarget( *_dataField , [&]( unsigned int idx ){ return clientToServer[idx]; } );
|
||||
phaseInfo.processTime += timer.wallTime();
|
||||
|
||||
profiler.update();
|
||||
delete _dataField;
|
||||
}
|
||||
else profiler.update();
|
||||
phaseInfo.readBytes += clientStream.ioBytes;
|
||||
}
|
||||
|
||||
if( needAuxData )
|
||||
{
|
||||
Timer timer;
|
||||
auto nodeFunctor = [&]( const RegularTreeNode< Dim , FEMTreeNodeData , depth_and_offset_type >* n )
|
||||
{
|
||||
ProjectiveData< InputSampleDataType , Real >* clr = state4.dataField->operator()( n );
|
||||
if( clr ) (*clr) *= (Real)pow( clientReconInfo.dataX , state4.tree.depth( n ) );
|
||||
};
|
||||
state4.tree.tree().processNodes( nodeFunctor );
|
||||
phaseInfo.processTime += timer.wallTime();
|
||||
}
|
||||
{
|
||||
Timer timer;
|
||||
for( unsigned int i=0 ; i<state4.iInfo->iData.size() ; i++ ) state4.iInfo->iData[i] = postMergeFunctor( state4.iInfo->iData[i] );
|
||||
phaseInfo.processTime += timer.wallTime();
|
||||
}
|
||||
|
||||
{
|
||||
Timer timer;
|
||||
|
||||
typename FEMTree< Dim , Real >::SolverInfo sInfo;
|
||||
sInfo.cgDepth = 0 , sInfo.cascadic = true , sInfo.vCycles = 1 , sInfo.iters = clientReconInfo.iters , sInfo.cgAccuracy = clientReconInfo.cgSolverAccuracy , sInfo.verbose = clientReconInfo.verbose>1 , sInfo.showResidual = clientReconInfo.verbose>2 , sInfo.showGlobalResidual = SHOW_GLOBAL_RESIDUAL_NONE , sInfo.sliceBlockSize = 1;
|
||||
sInfo.baseVCycles = baseVCycles;
|
||||
typename FEMIntegrator::template System< Sigs , IsotropicUIntPack< Dim , 1 > > F( { 0. , 1. } );
|
||||
state4.solution = state4.tree.solveSystem( Sigs() , F , state4.constraints , clientReconInfo.baseDepth , std::min< unsigned int >( clientReconInfo.sharedDepth , clientReconInfo.solveDepth ) , sInfo , std::make_tuple( state4.iInfo ) );
|
||||
phaseInfo.processTime += timer.wallTime();
|
||||
|
||||
profiler.update();
|
||||
}
|
||||
|
||||
for( unsigned int i=0 ; i<_clientSockets.size() ; i++ )
|
||||
{
|
||||
Timer timer;
|
||||
std::pair< unsigned int , unsigned int > range;
|
||||
#ifdef ADAPTIVE_PADDING
|
||||
// Compute the range of slices @ clientReconInfo.sharedDepth that can contribute to the client
|
||||
{
|
||||
range = _pointPartition.range( i );
|
||||
if( range.first<clientReconInfo.padSize ) range.first = 0;
|
||||
else range.first -= clientReconInfo.padSize;
|
||||
if( range.second+clientReconInfo.padSize>_pointPartition.slabs() ) range.second = _pointPartition.slabs();
|
||||
else range.second += clientReconInfo.padSize;
|
||||
}
|
||||
#else // !ADAPTIVE_PADDING
|
||||
range = _pointPartition.range( i , clientReconInfo.padSize );
|
||||
#endif // ADAPTIVE_PADDING
|
||||
|
||||
ClientServerStream< false > clientStream( _clientSockets[i] , i , clientReconInfo );
|
||||
clientStream.ioBytes = 0;
|
||||
auto keepNodeFunctor = [&]( const FEMTreeNode *node )
|
||||
{
|
||||
int d , off[Dim];
|
||||
state4.tree.depthAndOffset( node , d , off );
|
||||
|
||||
// Pre-tree nodes need to be shared and nodes finer than @ clientReconInfo.sharedDepth don't need to be
|
||||
if( d<0 ) return true;
|
||||
else if( d>(int)clientReconInfo.sharedDepth )
|
||||
{
|
||||
WARN( "Why does the client have fine nodes?" );
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Compute the space of the range of the support @ clientReconInfo.sharedDepth
|
||||
int start = ( off[Dim-1] + StartOffset )<<(clientReconInfo.sharedDepth-d);
|
||||
int end = ( off[Dim-1] + EndOffset )<<(clientReconInfo.sharedDepth-d);
|
||||
|
||||
// Keep the node if its support fall within the client's range
|
||||
return start<(int)range.second && end>(int)range.first;
|
||||
}
|
||||
};
|
||||
size_t subNodeCount;
|
||||
Pointer( FEMTreeNode ) subNodes = state4.tree.tree().serializeSubTree( keepNodeFunctor , subNodeCount );
|
||||
|
||||
node_index_type count = 0;
|
||||
subNodes[0].processNodes( [&]( const FEMTreeNode *node ){ if( node->nodeData.nodeIndex!=-1 ) count++; } );
|
||||
std::vector< node_index_type > newToOld( count );
|
||||
count = 0;
|
||||
for( size_t i=0 ; i<subNodeCount ; i++ ) if( subNodes[i].nodeData.nodeIndex!=-1 )
|
||||
{
|
||||
newToOld[ count ] = subNodes[i].nodeData.nodeIndex;
|
||||
subNodes[i].nodeData.nodeIndex = count++;
|
||||
}
|
||||
|
||||
TreeAddressesToIndices( subNodes , subNodeCount );
|
||||
phaseInfo.processTime += timer.wallTime();
|
||||
|
||||
timer = Timer();
|
||||
clientStream.write( subNodeCount );
|
||||
clientStream.write( subNodes , subNodeCount );
|
||||
phaseInfo.writeTime += timer.wallTime();
|
||||
|
||||
timer = Timer();
|
||||
DenseNodeData< Real , Sigs > _solution( count );
|
||||
for( unsigned int i=0 ; i<newToOld.size() ; i++ ) _solution[i] = state4.solution[ newToOld[i] ];
|
||||
phaseInfo.processTime += timer.wallTime();
|
||||
|
||||
timer = Timer();
|
||||
_solution.write( clientStream );
|
||||
phaseInfo.writeTime += timer.wallTime();
|
||||
|
||||
if( needAuxData )
|
||||
{
|
||||
Timer timer;
|
||||
SparseNodeData< ProjectiveData< InputSampleDataType , Real > , IsotropicUIntPack< Dim , DataSig > > _dataField;
|
||||
_dataField.reserve( count );
|
||||
for( size_t i=0 ; i<subNodeCount ; i++ ) if( subNodes[i].nodeData.nodeIndex!=-1 )
|
||||
{
|
||||
const FEMTreeNode *node = state4.tree.node( newToOld[ subNodes[i].nodeData.nodeIndex ] );
|
||||
ProjectiveData< InputSampleDataType , Real > *data = state4.dataField->operator()( node );
|
||||
if( data ) _dataField[ subNodes+i ] = *data;
|
||||
}
|
||||
phaseInfo.processTime += timer.wallTime();
|
||||
|
||||
timer = Timer();
|
||||
if( !auxDataFactory.isStaticallyAllocated() )
|
||||
{
|
||||
ProjectiveSampleDataTypeSerializer< Real , Dim > serializer( clientReconInfo.auxProperties );
|
||||
_dataField.write( clientStream , serializer );
|
||||
}
|
||||
else _dataField.write( clientStream );
|
||||
phaseInfo.writeTime += timer.wallTime();
|
||||
}
|
||||
profiler.update();
|
||||
DeletePointer( subNodes );
|
||||
phaseInfo.writeBytes += clientStream.ioBytes;
|
||||
}
|
||||
|
||||
{
|
||||
std::pair< double , double > isoInfo(0.,0.);
|
||||
for( unsigned int i=0 ; i<_clientSockets.size() ; i++ )
|
||||
{
|
||||
std::pair< double , double > _isoInfo(0.,0.);
|
||||
_clientSockets[i].read( _isoInfo );
|
||||
isoInfo.first += _isoInfo.first;
|
||||
isoInfo.second += _isoInfo.second;
|
||||
}
|
||||
if( clientReconInfo.verbose>1 ) std::cout << "Iso-value: " << ( isoInfo.first / isoInfo.second ) << std::endl;
|
||||
isoValue = (Real)( isoInfo.first / isoInfo.second );
|
||||
}
|
||||
|
||||
return phaseInfo;
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim , BoundaryType BType , unsigned int Degree >
|
||||
PhaseInfo Server< Real , Dim , BType , Degree >::_phase6( const ClientReconstructionInfo< Real , Dim > &clientReconInfo , Real isoValue , bool showDiscontinuity , bool outputBoundarySlices , std::vector< unsigned int > &sharedVertexCounts , Profiler &profiler )
|
||||
{
|
||||
using SliceSigs = typename _State6::SliceSigs;
|
||||
using Vertex = typename _State6::Vertex;
|
||||
PhaseInfo phaseInfo;
|
||||
|
||||
sharedVertexCounts.resize( _clientSockets.size()-1 );
|
||||
|
||||
for( unsigned int i=0 ; i<_clientSockets.size()-1 ; i++ )
|
||||
{
|
||||
_State6 state6;
|
||||
|
||||
auto ReadSlice = [&]( BinaryStream &clientStream , DenseNodeData< Real , SliceSigs > &solution , DenseNodeData< Real , SliceSigs > &dSolution , XForm< Real , Dim > &modelToUnitCube )
|
||||
{
|
||||
FEMTree< Dim-1 , Real > *sliceTree = new FEMTree< Dim-1 , Real >( clientStream , modelToUnitCube , MEMORY_ALLOCATOR_BLOCK_SIZE );
|
||||
solution.read( clientStream );
|
||||
if( !clientReconInfo.linearFit ) dSolution.read( clientStream );
|
||||
return sliceTree;
|
||||
};
|
||||
|
||||
|
||||
{
|
||||
ClientServerStream< true > clientStream0( _clientSockets[i+0] , i+0 , clientReconInfo , ClientReconstructionInfo< Real , Dim >::FRONT );
|
||||
ClientServerStream< true > clientStream1( _clientSockets[i+1] , i+1 , clientReconInfo , ClientReconstructionInfo< Real , Dim >::BACK );
|
||||
DenseNodeData< Real , SliceSigs > backSolution , frontSolution , backDSolution , frontDSolution;
|
||||
FEMTree< Dim-1 , Real > *backSliceTree , *frontSliceTree;
|
||||
XForm< Real , Dim > backXForm , frontXForm;
|
||||
|
||||
Timer timer;
|
||||
backSliceTree = ReadSlice( clientStream0 , backSolution , backDSolution , backXForm );
|
||||
frontSliceTree = ReadSlice( clientStream1 , frontSolution , frontDSolution , frontXForm );
|
||||
phaseInfo.readTime += timer.wallTime();
|
||||
|
||||
if( showDiscontinuity )
|
||||
{
|
||||
double discontinuityTime = 0;
|
||||
size_t discontinuityCount = 0;
|
||||
double l1 = 0 , l2 = 0 , d2 = 0 , dInf = 0;
|
||||
|
||||
double t = Time();
|
||||
|
||||
int res1 = 0 , res2 = 0;
|
||||
Pointer( Real ) values1 = backSliceTree->template regularGridEvaluate< true >( backSolution , res1 , -1 , false );
|
||||
Pointer( Real ) values2 = frontSliceTree->template regularGridEvaluate< true >( frontSolution , res2 , -1 , false );
|
||||
if( res1!=res2 ) ERROR_OUT( "Different resolutions: " , res1 , " != " , res2 );
|
||||
size_t count = 1;
|
||||
for( unsigned int d=0 ; d<(Dim-1) ; d++ ) count *= (unsigned int)res1;
|
||||
discontinuityCount += count;
|
||||
for( unsigned int i=0 ; i<count ; i++ ) l1 += values1[i] * values1[i] , l2 += values2[i] * values2[i] , d2 += ( values1[i] - values2[i] ) * ( values1[i] - values2[i] ) , dInf = std::max< double >( dInf , fabs( values1[i]-values2[i] ) );
|
||||
DeletePointer( values1 );
|
||||
DeletePointer( values2 );
|
||||
|
||||
discontinuityTime += Time()-t;
|
||||
|
||||
if( discontinuityCount )
|
||||
{
|
||||
d2 /= discontinuityCount;
|
||||
l1 /= discontinuityCount;
|
||||
l2 /= discontinuityCount;
|
||||
std::cout << "Discontinuity L2 / L-infinity: " << sqrt(d2) << " / " << dInf << " [ " << sqrt(l1) << " , " << sqrt(l2) << " ] " << discontinuityTime << " (s)" << std::endl;
|
||||
}
|
||||
profiler.update();
|
||||
}
|
||||
|
||||
timer = Timer();
|
||||
state6.sliceTree = FEMTree< Dim-1 , Real >::Merge( *backSliceTree , *frontSliceTree , MEMORY_ALLOCATOR_BLOCK_SIZE );
|
||||
state6.solution = state6.sliceTree->initDenseNodeData( SliceSigs() );
|
||||
state6.sliceTree->merge( * backSliceTree , backSolution , state6.solution );
|
||||
state6.sliceTree->merge( *frontSliceTree , frontSolution , state6.solution );
|
||||
for( unsigned int j=0 ; j<state6.solution.size() ; j++ ) state6.solution[j] /= (Real)2.;
|
||||
if( !clientReconInfo.linearFit )
|
||||
{
|
||||
state6.dSolution = state6.sliceTree->initDenseNodeData( SliceSigs() );
|
||||
state6.sliceTree->merge( * backSliceTree , backDSolution , state6.dSolution );
|
||||
state6.sliceTree->merge( *frontSliceTree , frontDSolution , state6.dSolution );
|
||||
for( unsigned int j=0 ; j<state6.dSolution.size() ; j++ ) state6.dSolution[j] /= (Real)2.;
|
||||
}
|
||||
state6.xForm = ( backXForm + frontXForm )/(Real)2.;
|
||||
phaseInfo.processTime += timer.wallTime();
|
||||
|
||||
profiler.update();
|
||||
|
||||
if( outputBoundarySlices )
|
||||
{
|
||||
auto WriteBoundary = [&]( std::string fileName , const FEMTree< Dim-1 , Real > *sliceTree , const DenseNodeData< Real , SliceSigs > &solution )
|
||||
{
|
||||
FILE* fp = fopen( fileName.c_str() , "wb" );
|
||||
if( !fp ) ERROR_OUT( "Failed to open file for writing: " , fileName );
|
||||
FileStream fs(fp);
|
||||
FEMTree< Dim-1 , Real >::WriteParameter( fs );
|
||||
DenseNodeData< Real , SliceSigs >::WriteSignatures( fs );
|
||||
sliceTree->write( fs , state6.xForm , false );
|
||||
solution.write( fs );
|
||||
fclose( fp );
|
||||
};
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "back." << i << ".tree";
|
||||
WriteBoundary( ss.str() , backSliceTree , backSolution );
|
||||
}
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "front." << i << ".tree";
|
||||
WriteBoundary( ss.str() , frontSliceTree , frontSolution );
|
||||
}
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "merged." << i << ".tree";
|
||||
WriteBoundary( ss.str() , state6.sliceTree , state6.solution );
|
||||
}
|
||||
}
|
||||
delete backSliceTree;
|
||||
delete frontSliceTree;
|
||||
|
||||
phaseInfo.readBytes += clientStream0.ioBytes + clientStream1.ioBytes;
|
||||
}
|
||||
|
||||
{
|
||||
Timer timer;
|
||||
using Factory = VertexFactory::EmptyFactory< Real >;
|
||||
using Data = typename Factory::VertexType;
|
||||
Factory factory;
|
||||
const typename FEMTree< Dim-1 , Real >::template DensityEstimator< WEIGHT_DEGREE > *density=NULL;
|
||||
const SparseNodeData< ProjectiveData< Data , Real > , IsotropicUIntPack< Dim-1 , DataSig > > *data=NULL;
|
||||
auto SetVertex = []( Vertex &v , Point< Real , Dim-1 > p , Point< Real , Dim-1 > g , Real w , Data d ){ v = p; };
|
||||
{
|
||||
VectorStreamingVertices< Point< Real , Dim-1 > , node_index_type > _vertices;
|
||||
LevelSetExtractor< Dim-1 , Real , Vertex >::template SetSliceValues< Data >( SliceSigs() , UIntPack< WEIGHT_DEGREE >() , UIntPack< DataSig >() , *state6.sliceTree , clientReconInfo.reconstructionDepth , density , data , state6.solution , isoValue , &_vertices , factory() , SetVertex , !clientReconInfo.linearFit , false , state6.sliceValues , LevelSetExtractor< Dim-1 , Real , Vertex >::SetIsoEdgesFlag() );
|
||||
if( !clientReconInfo.linearFit ) LevelSetExtractor< Dim-1 , Real , Vertex >::template SetSliceValues< Data >( SliceSigs() , UIntPack< WEIGHT_DEGREE >() , UIntPack< DataSig >() , *state6.sliceTree , clientReconInfo.reconstructionDepth , density , data , state6.dSolution , isoValue , &_vertices , factory() , SetVertex , false , false , state6.dSliceValues , LevelSetExtractor< Dim-1 , Real , Vertex >::SetCornerValuesFlag() );
|
||||
state6.vertices.resize( _vertices.vertexNum() );
|
||||
for( unsigned int j=0 ; j<_vertices.vertexNum() ; j++ ) state6.vertices[j] = _vertices.vertex(j);
|
||||
}
|
||||
sharedVertexCounts[i] = (unsigned int)state6.vertices.size();
|
||||
phaseInfo.processTime += timer.wallTime();
|
||||
}
|
||||
profiler.update();
|
||||
|
||||
{
|
||||
Timer timer;
|
||||
ClientServerStream< false > clientStream0( _clientSockets[i+0] , i+0 , clientReconInfo , ClientReconstructionInfo< Real , Dim >::FRONT );
|
||||
ClientServerStream< false > clientStream1( _clientSockets[i+1] , i+1 , clientReconInfo , ClientReconstructionInfo< Real , Dim >::BACK );
|
||||
clientStream0.ioBytes = 0;
|
||||
clientStream1.ioBytes = 0;
|
||||
clientStream0.write( isoValue );
|
||||
clientStream1.write( isoValue );
|
||||
if( clientReconInfo.mergeType!=ClientReconstructionInfo< Real , Dim >::MergeType::NONE )
|
||||
{
|
||||
LevelSetExtractor< Dim-1 , Real , Vertex >::TreeSliceValuesAndVertexPositions::Write( clientStream0 , state6.sliceTree , state6.xForm , state6.sliceValues , state6.vertices , true );
|
||||
if( !clientReconInfo.linearFit )
|
||||
{
|
||||
for( unsigned int i=0 ; i<state6.dSliceValues.size() ; i++ )
|
||||
{
|
||||
clientStream0.write( state6.dSliceValues[i].cellIndices.counts[0] );
|
||||
clientStream0.write( state6.dSliceValues[i].cornerValues , state6.dSliceValues[i].cellIndices.counts[0] );
|
||||
}
|
||||
}
|
||||
LevelSetExtractor< Dim-1 , Real , Vertex >::TreeSliceValuesAndVertexPositions::Write( clientStream1 , state6.sliceTree , state6.xForm , state6.sliceValues , state6.vertices , true );
|
||||
if( !clientReconInfo.linearFit )
|
||||
{
|
||||
for( unsigned int i=0 ; i<state6.dSliceValues.size() ; i++ )
|
||||
{
|
||||
clientStream1.write( state6.dSliceValues[i].cellIndices.counts[0] );
|
||||
clientStream1.write( state6.dSliceValues[i].cornerValues , state6.dSliceValues[i].cellIndices.counts[0] );
|
||||
}
|
||||
}
|
||||
}
|
||||
phaseInfo.writeBytes += clientStream0.ioBytes + clientStream1.ioBytes;
|
||||
phaseInfo.writeTime += timer.wallTime();
|
||||
}
|
||||
profiler.update();
|
||||
}
|
||||
|
||||
return phaseInfo;
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
Copyright (c) 2023, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer. Redistributions in binary form must reproduce
|
||||
the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Johns Hopkins University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
#define BIG_DATA
|
||||
#include "PreProcessor.h"
|
||||
|
||||
#include "Socket.h"
|
||||
#include "PoissonReconClientServer.h"
|
||||
#include "PointPartitionClientServer.h"
|
||||
#include "MergePlyClientServer.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <algorithm>
|
||||
#include "MyMiscellany.h"
|
||||
#include "PoissonRecon.h"
|
||||
#include "CmdLineParser.h"
|
||||
|
||||
cmdLineParameter< std::string >
|
||||
Address( "address" , "127.0.0.1" );
|
||||
|
||||
cmdLineParameter< int >
|
||||
MaxMemoryGB( "maxMemory" , 0 ) ,
|
||||
#ifdef _OPENMP
|
||||
ParallelType( "parallel" , (int)ThreadPool::OPEN_MP ) ,
|
||||
#else // !_OPENMP
|
||||
ParallelType( "parallel" , (int)ThreadPool::THREAD_POOL ) ,
|
||||
#endif // _OPENMP
|
||||
ScheduleType( "schedule" , (int)ThreadPool::DefaultSchedule ) ,
|
||||
ThreadChunkSize( "chunkSize" , (int)ThreadPool::DefaultChunkSize ) ,
|
||||
Threads( "threads" , (int)std::thread::hardware_concurrency() ) ,
|
||||
MultiClient( "multi" , 1 ) ,
|
||||
Port( "port" , 0 ) ,
|
||||
PeakMemorySampleMS( "sampleMS" , 10 );
|
||||
|
||||
cmdLineReadable
|
||||
Pause( "pause" );
|
||||
|
||||
|
||||
cmdLineReadable* params[] =
|
||||
{
|
||||
&Port , &MultiClient , &Address ,
|
||||
&MaxMemoryGB , &ParallelType , &ScheduleType , &ThreadChunkSize , &Threads ,
|
||||
&Pause ,
|
||||
&PeakMemorySampleMS ,
|
||||
NULL
|
||||
};
|
||||
|
||||
void ShowUsage( char* ex )
|
||||
{
|
||||
printf( "Usage: %s\n" , ex );
|
||||
printf( "\t --%s <server port>\n" , Port.name );
|
||||
printf( "\t[--%s <multiplicity of serial sub-clients>=%d]\n" , MultiClient.name , MultiClient.value );
|
||||
printf( "\t[--%s <server connection address>=%s]\n" , Address.name , Address.value.c_str() );
|
||||
printf( "\t[--%s <num threads>=%d]\n" , Threads.name , Threads.value );
|
||||
printf( "\t[--%s <parallel type>=%d]\n" , ParallelType.name , ParallelType.value );
|
||||
for( size_t i=0 ; i<ThreadPool::ParallelNames.size() ; i++ ) printf( "\t\t%d] %s\n" , (int)i , ThreadPool::ParallelNames[i].c_str() );
|
||||
printf( "\t[--%s <schedue type>=%d]\n" , ScheduleType.name , ScheduleType.value );
|
||||
for( size_t i=0 ; i<ThreadPool::ScheduleNames.size() ; i++ ) printf( "\t\t%d] %s\n" , (int)i , ThreadPool::ScheduleNames[i].c_str() );
|
||||
printf( "\t[--%s <thread chunk size>=%d]\n" , ThreadChunkSize.name , ThreadChunkSize.value );
|
||||
printf( "\t[--%s <peak memory sampling rate (ms)>=%d]\n" , PeakMemorySampleMS.name , PeakMemorySampleMS.value );
|
||||
printf( "\t[--%s <maximum memory (in GB)>=%d]\n" , MaxMemoryGB.name , MaxMemoryGB.value );
|
||||
printf( "\t[--%s]\n" , Pause.name );
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
void Partition( std::vector< Socket > &serverSockets )
|
||||
{
|
||||
PointPartitionClientServer::RunClients< Real , Dim >( serverSockets );
|
||||
unsigned int peakMem = MemoryInfo::PeakMemoryUsageMB();
|
||||
for( unsigned int i=0 ; i<serverSockets.size() ; i++ ) SocketStream( serverSockets[i] ).write( peakMem );
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim , BoundaryType BType , unsigned int Degree >
|
||||
void Reconstruct( std::vector< Socket > &serverSockets )
|
||||
{
|
||||
PoissonReconClientServer::RunClient< Real , Dim , BType , Degree >( serverSockets , PeakMemorySampleMS.value );
|
||||
unsigned int peakMem = MemoryInfo::PeakMemoryUsageMB();
|
||||
for( unsigned int i=0 ; i<serverSockets.size() ; i++ ) SocketStream( serverSockets[i] ).write( peakMem );
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
void Merge( std::vector< Socket > &serverSockets )
|
||||
{
|
||||
MergePlyClientServer::RunClients< Real , Dim >( serverSockets , PeakMemorySampleMS.value );
|
||||
unsigned int peakMem = MemoryInfo::PeakMemoryUsageMB();
|
||||
for( unsigned int i=0 ; i<serverSockets.size() ; i++ ) SocketStream( serverSockets[i] ).write( peakMem );
|
||||
}
|
||||
|
||||
#ifdef FAST_COMPILE
|
||||
#else // !FAST_COMPILE
|
||||
template< typename Real , unsigned int Dim , BoundaryType BType >
|
||||
void Reconstruct( unsigned int degree , std::vector< Socket > &serverSockets )
|
||||
{
|
||||
switch( degree )
|
||||
{
|
||||
case 1: return Reconstruct< Real , Dim , BType , 1 >( serverSockets );
|
||||
case 2: return Reconstruct< Real , Dim , BType , 2 >( serverSockets );
|
||||
default: ERROR_OUT( "Only B-Splines of degree 1 - 2 are supported" );
|
||||
}
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
void Reconstruct( BoundaryType bType , unsigned int degree , std::vector< Socket > &serverSockets )
|
||||
{
|
||||
switch( bType )
|
||||
{
|
||||
case BOUNDARY_FREE: return Reconstruct< Real , Dim , BOUNDARY_FREE >( degree , serverSockets );
|
||||
case BOUNDARY_NEUMANN: return Reconstruct< Real , Dim , BOUNDARY_NEUMANN >( degree , serverSockets );
|
||||
case BOUNDARY_DIRICHLET: return Reconstruct< Real , Dim , BOUNDARY_DIRICHLET >( degree , serverSockets );
|
||||
default: ERROR_OUT( "Not a valid boundary type: " , bType );
|
||||
}
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
void Reconstruct( std::vector< Socket > &serverSockets )
|
||||
{
|
||||
BoundaryType bType;
|
||||
unsigned int degree;
|
||||
for( unsigned int i=0 ; i<serverSockets.size() ; i++ )
|
||||
{
|
||||
if( !SocketStream( serverSockets[i] ).read( bType ) ) ERROR_OUT( "Failed to read boundary-type" );
|
||||
if( !SocketStream( serverSockets[i] ).read( degree ) ) ERROR_OUT( "Failed to read degree" );
|
||||
}
|
||||
Reconstruct< Real , Dim >( bType , degree , serverSockets );
|
||||
}
|
||||
|
||||
#endif // FAST_COMPILE
|
||||
|
||||
int main( int argc , char* argv[] )
|
||||
{
|
||||
#ifdef ARRAY_DEBUG
|
||||
WARN( "Array debugging enabled" );
|
||||
#endif // ARRAY_DEBUG
|
||||
#ifdef USE_DOUBLE
|
||||
typedef double Real;
|
||||
#else // !USE_DOUBLE
|
||||
typedef float Real;
|
||||
#endif // USE_DOUBLE
|
||||
static const unsigned int Dim = DEFAULT_DIMENSION;
|
||||
|
||||
Timer timer;
|
||||
cmdLineParse( argc-1 , &argv[1] , params );
|
||||
|
||||
if( !Port.set )
|
||||
{
|
||||
ShowUsage( argv[0] );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( MaxMemoryGB.value>0 ) SetPeakMemoryMB( MaxMemoryGB.value<<10 );
|
||||
ThreadPool::DefaultChunkSize = ThreadChunkSize.value;
|
||||
ThreadPool::DefaultSchedule = (ThreadPool::ScheduleType)ScheduleType.value;
|
||||
ThreadPool::Init( (ThreadPool::ParallelType)ParallelType.value , Threads.value );
|
||||
|
||||
std::vector< Socket > serverSockets( MultiClient.value , NULL );
|
||||
for( unsigned int i=0 ; i<(unsigned int)MultiClient.value ; i++ ) serverSockets[i] = GetConnectSocket( Address.value.c_str() , Port.value , SOCKET_CONNECT_WAIT , false );
|
||||
|
||||
{
|
||||
Partition< Real , Dim >( serverSockets );
|
||||
|
||||
#ifdef FAST_COMPILE
|
||||
Reconstruct< Real , Dim , DEFAULT_FEM_BOUNDARY , DEFAULT_FEM_DEGREE >( serverSockets );
|
||||
#else // !FAST_COMPILE
|
||||
Reconstruct< Real , Dim >( serverSockets );
|
||||
#endif // FAST_COMPILE
|
||||
|
||||
Merge< Real , Dim >( serverSockets );
|
||||
|
||||
for( unsigned int i=0 ; i<serverSockets.size() ; i++ ) CloseSocket( serverSockets[i] );
|
||||
}
|
||||
|
||||
ThreadPool::Terminate();
|
||||
|
||||
if( Pause.set )
|
||||
{
|
||||
std::cout << "Hit [ENTER] to terminate" << std::endl;
|
||||
std::string foo;
|
||||
std::getline( std::cin , foo );
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
Copyright (c) 2023, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer. Redistributions in binary form must reproduce
|
||||
the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Johns Hopkins University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef POISSON_RECON_CLIENT_SERVER_INCLUDED
|
||||
#define POISSON_RECON_CLIENT_SERVER_INCLUDED
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include "PointPartition.h"
|
||||
#include "FEMTree.h"
|
||||
#include "VertexFactory.h"
|
||||
#include "Socket.h"
|
||||
#include "PoissonRecon.h"
|
||||
|
||||
namespace PoissonReconClientServer
|
||||
{
|
||||
template< typename Real , unsigned int Dim >
|
||||
struct ClientReconstructionInfo
|
||||
{
|
||||
enum ShareType
|
||||
{
|
||||
BACK ,
|
||||
CENTER ,
|
||||
FRONT
|
||||
};
|
||||
enum MergeType
|
||||
{
|
||||
TOPOLOGY_AND_FUNCTION , // Identical topology across slice
|
||||
FUNCTION , // Identical function across slice
|
||||
NONE
|
||||
};
|
||||
|
||||
std::string header , inDir , tempDir , outDir;
|
||||
unsigned int solveDepth , reconstructionDepth , sharedDepth , distributionDepth , baseDepth , kernelDepth , iters , bufferSize , filesPerDir , padSize , verbose;
|
||||
Real pointWeight , confidence , confidenceBias , samplesPerNode , dataX , cgSolverAccuracy;
|
||||
MergeType mergeType;
|
||||
bool density , linearFit , ouputVoxelGrid;
|
||||
std::vector< PlyProperty > auxProperties;
|
||||
|
||||
ClientReconstructionInfo( void );
|
||||
ClientReconstructionInfo( BinaryStream &stream );
|
||||
|
||||
void write( BinaryStream &stream ) const;
|
||||
|
||||
std::string sharedFile( unsigned int idx , ShareType shareType=CENTER ) const;
|
||||
};
|
||||
|
||||
template< typename Real , unsigned int Dim , BoundaryType BType , unsigned int Degree >
|
||||
std::vector< unsigned int > RunServer
|
||||
(
|
||||
PointPartition::PointSetInfo< Real , Dim > pointSetInfo ,
|
||||
PointPartition::Partition pointPartition ,
|
||||
std::vector< Socket > clientSockets ,
|
||||
ClientReconstructionInfo< Real , Dim > clientReconInfo ,
|
||||
unsigned int baseVCycles ,
|
||||
unsigned int sampleMS ,
|
||||
bool showDiscontinuity=false ,
|
||||
bool outputBoundarySlices=false
|
||||
);
|
||||
|
||||
template< typename Real , unsigned int Dim , BoundaryType BType , unsigned int Degree >
|
||||
void RunClient( std::vector< Socket > &serverSockets , unsigned int sampleMS );
|
||||
|
||||
#include "PoissonReconClientServer.inl"
|
||||
#include "PoissonRecon.server.inl"
|
||||
#include "PoissonRecon.client.inl"
|
||||
}
|
||||
|
||||
#endif // POISSON_RECON_CLIENT_SERVER_INCLUDED
|
||||
@@ -0,0 +1,386 @@
|
||||
/*
|
||||
Copyright (c) 2023, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer. Redistributions in binary form must reproduce
|
||||
the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Johns Hopkins University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
using SampleDataType = VectorTypeUnion< Real , typename VertexFactory::NormalFactory< Real , Dim >::VertexType , typename VertexFactory::DynamicFactory< Real >::VertexType >;
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
struct SampleDataTypeSerializer : public Serializer< SampleDataType< Real , Dim > >
|
||||
{
|
||||
using Normal = typename VertexFactory::NormalFactory< Real , Dim >::VertexType;
|
||||
using AuxData = typename VertexFactory::DynamicFactory< Real >::VertexType;
|
||||
using Data = VectorTypeUnion< Real , Normal , AuxData >;
|
||||
|
||||
SampleDataTypeSerializer( const std::vector< PlyProperty > &properties ) : _factory( properties ){}
|
||||
|
||||
size_t size( void ) const { return sizeof(Normal) + _factory.bufferSize(); }
|
||||
|
||||
void serialize( const Data &data , Pointer( char )buffer ) const
|
||||
{
|
||||
memcpy( buffer , &data.template get<0>() , sizeof(Normal) );
|
||||
_factory.toBuffer( data.template get<1>() , buffer+sizeof(Normal) );
|
||||
}
|
||||
void deserialize( ConstPointer( char ) buffer , Data &data ) const
|
||||
{
|
||||
Point< Real > p = _factory();
|
||||
memcpy( &data.template get<0>() , buffer , sizeof(Normal) );
|
||||
_factory.fromBuffer( buffer+sizeof(Normal) , p );
|
||||
data.template get<1>() = p;
|
||||
}
|
||||
protected:
|
||||
VertexFactory::DynamicFactory< Real > _factory;
|
||||
};
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
struct ProjectiveSampleDataTypeSerializer : public Serializer< ProjectiveData< SampleDataType< Real , Dim > , Real > >
|
||||
{
|
||||
using Normal = typename VertexFactory::NormalFactory< Real , Dim >::VertexType;
|
||||
using AuxData = typename VertexFactory::DynamicFactory< Real >::VertexType;
|
||||
using Data = ProjectiveData< VectorTypeUnion< Real , Normal , AuxData > , Real >;
|
||||
|
||||
ProjectiveSampleDataTypeSerializer( const std::vector< PlyProperty > &properties ) : _factory( properties ){}
|
||||
|
||||
size_t size( void ) const { return sizeof( Real ) + sizeof(Normal) + _factory.bufferSize(); }
|
||||
|
||||
void serialize( const Data &data , Pointer( char )buffer ) const
|
||||
{
|
||||
memcpy( buffer , &data.weight , sizeof(Real) );
|
||||
memcpy( buffer + sizeof(Real) , &data.data.template get<0>() , sizeof(Normal) );
|
||||
_factory.toBuffer( data.data.template get<1>() , buffer+sizeof(Real)+sizeof(Normal) );
|
||||
}
|
||||
void deserialize( ConstPointer( char ) buffer , Data &data ) const
|
||||
{
|
||||
Point< Real > p = _factory();
|
||||
memcpy( &data.weight , buffer , sizeof(Real) );
|
||||
memcpy( &data.data.template get<0>() , buffer+sizeof(Real) , sizeof(Normal) );
|
||||
_factory.fromBuffer( buffer+sizeof(Real)+sizeof(Normal) , p );
|
||||
data.data.template get<1>() = p;
|
||||
}
|
||||
protected:
|
||||
VertexFactory::DynamicFactory< Real > _factory;
|
||||
};
|
||||
|
||||
std::string SendDataString( unsigned int phase , size_t ioBytes )
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "[SEND " << phase << "] ";
|
||||
size_t sz;
|
||||
std::string type;
|
||||
if ( ioBytes<(1<<10) ) sz = (ioBytes>> 0) , type = " B";
|
||||
else if( ioBytes<(1<<20) ) sz = (ioBytes>>10) , type = "KiB";
|
||||
else if( ioBytes<(1<<30) ) sz = (ioBytes>>20) , type = "MiB";
|
||||
else sz = (ioBytes>>30) , type = "GiB";
|
||||
if ( sz<10 ) ss << " ";
|
||||
else if( sz<100 ) ss << " ";
|
||||
else if( sz<1000 ) ss << " ";
|
||||
ss << sz << " " << type << ": ";
|
||||
return ss.str();
|
||||
}
|
||||
std::string ReceiveDataString( unsigned int phase , size_t ioBytes )
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "[RECEIVE " << phase << "] ";
|
||||
size_t sz;
|
||||
std::string type;
|
||||
if ( ioBytes<(1<<10) ) sz = (ioBytes>> 0) , type = " B";
|
||||
else if( ioBytes<(1<<20) ) sz = (ioBytes>>10) , type = "KiB";
|
||||
else if( ioBytes<(1<<30) ) sz = (ioBytes>>20) , type = "MiB";
|
||||
else sz = (ioBytes>>30) , type = "GiB";
|
||||
if ( sz<10 ) ss << " ";
|
||||
else if( sz<100 ) ss << " ";
|
||||
else if( sz<1000 ) ss << " ";
|
||||
ss << sz << " " << type << ": ";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template< unsigned int Dim >
|
||||
void TreeAddressesToIndices( Pointer( RegularTreeNode< Dim , FEMTreeNodeData , depth_and_offset_type > ) nodes , size_t nodeCount )
|
||||
{
|
||||
typedef RegularTreeNode< Dim , FEMTreeNodeData , depth_and_offset_type > FEMTreeNode;
|
||||
|
||||
for( size_t i=0 ; i<nodeCount ; i++ )
|
||||
{
|
||||
if( nodes[i].parent ) nodes[i].parent = (FEMTreeNode*)( nodes[i].parent - PointerAddress( nodes ) );
|
||||
else nodes[i].parent = (FEMTreeNode*)-1;
|
||||
if( nodes[i].children ) nodes[i].children = (FEMTreeNode*)( nodes[i].children - PointerAddress( nodes ) );
|
||||
else nodes[i].children = (FEMTreeNode*)-1;
|
||||
}
|
||||
}
|
||||
|
||||
template< unsigned int Dim >
|
||||
void TreeIndicesToAddresses( Pointer( RegularTreeNode< Dim , FEMTreeNodeData , depth_and_offset_type > ) nodes , size_t nodeCount )
|
||||
{
|
||||
typedef RegularTreeNode< Dim , FEMTreeNodeData , depth_and_offset_type > FEMTreeNode;
|
||||
|
||||
for( size_t i=0 ; i<nodeCount ; i++ )
|
||||
{
|
||||
if( (size_t)nodes[i].parent!=-1 ) nodes[i].parent = PointerAddress( nodes ) + (size_t)nodes[i].parent;
|
||||
else nodes[i].parent = NULL;
|
||||
if( (size_t)nodes[i].children!=-1 ) nodes[i].children = PointerAddress( nodes ) + (size_t)nodes[i].children;
|
||||
else nodes[i].children = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
template< bool ReadFromFile >
|
||||
struct ClientServerStream : BinaryStream
|
||||
{
|
||||
template< typename Real , unsigned int Dim >
|
||||
static void Reset( unsigned int idx , const ClientReconstructionInfo< Real , Dim > &clientReconInfo )
|
||||
{
|
||||
auto CleanUp =[]( std::string fileName )
|
||||
{
|
||||
std::ifstream fs;
|
||||
fs.open( fileName , std::ios::in | std::ios::binary );
|
||||
if( fs.is_open() )
|
||||
{
|
||||
fs.close();
|
||||
remove( fileName.c_str() );
|
||||
}
|
||||
};
|
||||
{
|
||||
CleanUp( clientReconInfo.sharedFile( idx , ClientReconstructionInfo< Real , Dim >::ShareType::BACK ) );
|
||||
CleanUp( clientReconInfo.sharedFile( idx , ClientReconstructionInfo< Real , Dim >::ShareType::CENTER ) );
|
||||
CleanUp( clientReconInfo.sharedFile( idx , ClientReconstructionInfo< Real , Dim >::ShareType::FRONT ) );
|
||||
}
|
||||
}
|
||||
|
||||
ClientServerStream( ClientServerStream &&css ) : _socket( std::move( css )._socket ) , _fs( std::move( css )._fs ) , _fileName( std::move( css )._fileName ) {}
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
ClientServerStream( SocketStream &socket , unsigned int idx , const ClientReconstructionInfo< Real , Dim > &clientReconInfo , typename ClientReconstructionInfo< Real , Dim >::ShareType shareType = ClientReconstructionInfo< Real , Dim >::CENTER , unsigned int maxTries=-1 )
|
||||
: _socket(socket)
|
||||
{
|
||||
_fileName = clientReconInfo.sharedFile( idx , shareType );
|
||||
if constexpr( ReadFromFile )
|
||||
{
|
||||
// Check that the file exists and is the right size
|
||||
auto validFile = []( std::string fileName , size_t sz )
|
||||
{
|
||||
std::ifstream fs;
|
||||
fs.open( fileName , std::ios::in | std::ios::binary );
|
||||
if( !fs.is_open() ) return false;
|
||||
|
||||
fs.seekg ( 0 , fs.end );
|
||||
if( fs.tellg()!=sz )
|
||||
{
|
||||
std::cout << fs.tellg() << " / " << sz << std::endl;
|
||||
return false;
|
||||
}
|
||||
else return true;
|
||||
};
|
||||
size_t sz;
|
||||
_socket.read( sz );
|
||||
unsigned int tries=0;
|
||||
while( !validFile( _fileName , sz ) && tries<maxTries )
|
||||
{
|
||||
std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
|
||||
tries++;
|
||||
}
|
||||
_fs.open( _fileName , std::ios::in | std::ios::binary );
|
||||
if( !_fs.is_open() ) ERROR_OUT( "Failed to open file for reading: " , _fileName );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check that the file does not exist
|
||||
auto validFile = []( std::string fileName )
|
||||
{
|
||||
std::ifstream fs;
|
||||
fs.open( fileName , std::ios::in | std::ios::binary );
|
||||
return !fs.is_open();
|
||||
};
|
||||
unsigned int tries=0;
|
||||
while( !validFile( _fileName ) && tries<maxTries )
|
||||
{
|
||||
std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
|
||||
tries++;
|
||||
}
|
||||
if( !validFile( _fileName ) ) ERROR_OUT( "File exists: " , _fileName , " , " , tries , " / " , maxTries );
|
||||
|
||||
_fs.open( _fileName , std::ios::out | std::ios::binary );
|
||||
if( !_fs.is_open() ) ERROR_OUT( "Failed to open file for writing: " , _fileName );
|
||||
}
|
||||
}
|
||||
~ClientServerStream( void )
|
||||
{
|
||||
_fs.close();
|
||||
if( ReadFromFile ) std::remove( _fileName.c_str() );
|
||||
else _socket.write( ioBytes );
|
||||
}
|
||||
|
||||
protected:
|
||||
typename std::conditional< ReadFromFile , std::ifstream , std::ofstream >::type _fs;
|
||||
SocketStream &_socket;
|
||||
std::string _fileName;
|
||||
|
||||
bool _read( Pointer( unsigned char ) ptr , size_t sz )
|
||||
{
|
||||
if constexpr( ReadFromFile ) return (bool)_fs.read ( ( char * )PointerAddress( ptr ) , sz );
|
||||
else return false;
|
||||
}
|
||||
bool _write( ConstPointer( unsigned char ) ptr , size_t sz )
|
||||
{
|
||||
if constexpr( !ReadFromFile ) return (bool)_fs.write( ( const char * )PointerAddress( ptr ) , sz );
|
||||
else return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct PhaseInfo
|
||||
{
|
||||
double processTime , readTime , writeTime;
|
||||
size_t readBytes , writeBytes;
|
||||
|
||||
PhaseInfo( void ) : processTime(0) , readTime(0) , writeTime(0) , readBytes(0) , writeBytes(0) {}
|
||||
|
||||
PhaseInfo &operator += ( const PhaseInfo &pi )
|
||||
{
|
||||
processTime += pi.processTime;
|
||||
readTime += pi.readTime;
|
||||
readBytes += pi.readBytes;
|
||||
writeBytes += pi.writeBytes;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////
|
||||
// ClientReconstructionInfo //
|
||||
//////////////////////////////
|
||||
template< typename Real , unsigned int Dim >
|
||||
ClientReconstructionInfo< Real , Dim >::ClientReconstructionInfo( void )
|
||||
{
|
||||
distributionDepth = 0;
|
||||
baseDepth = 5;
|
||||
iters = 8;
|
||||
confidence = (Real)0.;
|
||||
confidenceBias = (Real)0.;
|
||||
samplesPerNode = (Real)1.5;
|
||||
dataX = (Real)32.;
|
||||
density = false;
|
||||
linearFit = false;
|
||||
mergeType = MergeType::TOPOLOGY_AND_FUNCTION;
|
||||
bufferSize = BUFFER_IO;
|
||||
filesPerDir = -1;
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
ClientReconstructionInfo< Real , Dim >::ClientReconstructionInfo( BinaryStream &stream )
|
||||
{
|
||||
auto ReadBool = [&]( bool &b )
|
||||
{
|
||||
char _b;
|
||||
if( !stream.read( _b ) ) return false;
|
||||
b = _b!=0;
|
||||
return true;
|
||||
};
|
||||
if( !stream.read( inDir ) ) ERROR_OUT( "Failed to read in dir" );
|
||||
if( !stream.read( tempDir ) ) ERROR_OUT( "Failed to read temp dir" );
|
||||
if( !stream.read( outDir ) ) ERROR_OUT( "Failed to read out dir" );
|
||||
if( !stream.read( header ) ) ERROR_OUT( "Failed to read header" );
|
||||
if( !stream.read( bufferSize ) ) ERROR_OUT( "Failed to read buffer size" );
|
||||
if( !stream.read( filesPerDir ) ) ERROR_OUT( "Failed to read files per dir" );
|
||||
if( !stream.read( reconstructionDepth ) ) ERROR_OUT( "Failed to read reconstruction depth" );
|
||||
if( !stream.read( sharedDepth ) ) ERROR_OUT( "Failed to read shared depth" );
|
||||
if( !stream.read( distributionDepth ) ) ERROR_OUT( "Failed to read distribution depth" );
|
||||
if( !stream.read( baseDepth ) ) ERROR_OUT( "Failed to read base depth" );
|
||||
if( !stream.read( kernelDepth ) ) ERROR_OUT( "Failed to read kernel depth" );
|
||||
if( !stream.read( solveDepth ) ) ERROR_OUT( "Failed to read solveDepth depth" );
|
||||
if( !stream.read( iters ) ) ERROR_OUT( "Failed to read iters" );
|
||||
if( !stream.read( cgSolverAccuracy ) ) ERROR_OUT( "Failed to read CG-solver-accuracy" );
|
||||
if( !stream.read( pointWeight ) ) ERROR_OUT( "Failed to read point-weight" );
|
||||
if( !stream.read( confidence ) ) ERROR_OUT( "Failed to read confidence" );
|
||||
if( !stream.read( confidenceBias ) ) ERROR_OUT( "Failed to read confidence-bias" );
|
||||
if( !stream.read( samplesPerNode ) ) ERROR_OUT( "Failed to read samples-per-node" );
|
||||
if( !stream.read( dataX ) ) ERROR_OUT( "Failed to read data-multiplier" );
|
||||
if( !stream.read( padSize ) ) ERROR_OUT( "Failed to read padSize" );
|
||||
if( !stream.read( verbose ) ) ERROR_OUT( "Failed to read verbose" );
|
||||
if( !stream.read( mergeType ) ) ERROR_OUT( "Failed to read merge-type" );
|
||||
if( !ReadBool( density ) ) ERROR_OUT( "Failed to read density flag" );
|
||||
if( !ReadBool( linearFit ) ) ERROR_OUT( "Failed to read linear-fit flag" );
|
||||
if( !ReadBool( ouputVoxelGrid ) ) ERROR_OUT( "Failed to read output-voxel-grid flag" );
|
||||
{
|
||||
size_t sz;
|
||||
if( !stream.read( sz ) ) ERROR_OUT( "Failed to read number of auxiliary properties" );
|
||||
auxProperties.resize(sz);
|
||||
for( size_t i=0 ; i<sz ; i++ ) auxProperties[i].read( stream );
|
||||
}
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
void ClientReconstructionInfo< Real , Dim >::write( BinaryStream &stream ) const
|
||||
{
|
||||
auto WriteBool = [&]( bool b )
|
||||
{
|
||||
char _b = b ? 1 : 0;
|
||||
stream.write( _b );
|
||||
};
|
||||
stream.write( inDir );
|
||||
stream.write( tempDir );
|
||||
stream.write( outDir );
|
||||
stream.write( header );
|
||||
stream.write( bufferSize );
|
||||
stream.write( filesPerDir );
|
||||
stream.write( reconstructionDepth );
|
||||
stream.write( sharedDepth );
|
||||
stream.write( distributionDepth );
|
||||
stream.write( baseDepth );
|
||||
stream.write( kernelDepth );
|
||||
stream.write( solveDepth );
|
||||
stream.write( iters );
|
||||
stream.write( cgSolverAccuracy );
|
||||
stream.write( pointWeight );
|
||||
stream.write( confidence );
|
||||
stream.write( confidenceBias );
|
||||
stream.write( samplesPerNode );
|
||||
stream.write( dataX );
|
||||
stream.write( padSize );
|
||||
stream.write( verbose );
|
||||
stream.write( mergeType );
|
||||
WriteBool( density );
|
||||
WriteBool( linearFit );
|
||||
WriteBool( ouputVoxelGrid );
|
||||
{
|
||||
size_t sz = auxProperties.size();
|
||||
stream.write( sz );
|
||||
for( size_t j=0 ; j<sz ; j++ ) auxProperties[j].write( stream );
|
||||
}
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
std::string ClientReconstructionInfo< Real , Dim >::sharedFile( unsigned int idx , ShareType shareType ) const
|
||||
{
|
||||
std::stringstream sStream;
|
||||
switch( shareType )
|
||||
{
|
||||
case BACK: sStream << PointPartition::FileDir( tempDir , header ) << "." << idx << ".back.shared" ; break;
|
||||
case CENTER: sStream << PointPartition::FileDir( tempDir , header ) << "." << idx << ".shared" ; break;
|
||||
case FRONT: sStream << PointPartition::FileDir( tempDir , header ) << "." << idx << ".front.shared" ; break;
|
||||
default: ERROR_OUT( "Unrecognized share type: " , shareType );
|
||||
}
|
||||
return sStream.str();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,515 @@
|
||||
/*
|
||||
Copyright (c) 2023, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer. Redistributions in binary form must reproduce
|
||||
the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Johns Hopkins University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
#define BIG_DATA
|
||||
#include "PreProcessor.h"
|
||||
|
||||
#include "Socket.h"
|
||||
#include "PoissonReconClientServer.h"
|
||||
#include "PointPartitionClientServer.h"
|
||||
#include "MergePlyClientServer.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <algorithm>
|
||||
#include "MyMiscellany.h"
|
||||
#include "CmdLineParser.h"
|
||||
#include "PoissonRecon.h"
|
||||
|
||||
|
||||
cmdLineParameter< std::string >
|
||||
AddressPrefix( "prefix" ) ,
|
||||
In( "in" ) ,
|
||||
TempDir( "tempDir" ) ,
|
||||
Out( "out" );
|
||||
|
||||
cmdLineParameter< int >
|
||||
ClientCount( "count" ) ,
|
||||
Port( "port" , 0 ) ,
|
||||
Verbose( "verbose" , 0 ) ,
|
||||
#ifdef FAST_COMPILE
|
||||
#else // !FAST_COMPILE
|
||||
Degree( "degree" , DEFAULT_FEM_DEGREE ) ,
|
||||
BType( "bType" , DEFAULT_FEM_BOUNDARY ) ,
|
||||
#endif // FAST_COMPILE
|
||||
Iters( "iters" , 8 ) ,
|
||||
BaseVCycles( "vCycles" , 1 ) ,
|
||||
KernelDepth( "kernelDepth" ) ,
|
||||
BaseDepth( "baseDepth" , 5 ) ,
|
||||
SolveDepth( "solveDepth" ) ,
|
||||
PadSize( "pad" , 4 ) ,
|
||||
BufferSize( "buffer" , BUFFER_IO ) ,
|
||||
Depth( "depth" , 8 ) ,
|
||||
PartitionDepth( "pDepth" , 5 ) ,
|
||||
FilesPerDir( "filesPerDir" , -1 ) ,
|
||||
MaxMemoryGB( "maxMemory" , 0 ) ,
|
||||
PeakMemorySampleMS( "sampleMS" , 10 ) ,
|
||||
#ifdef _OPENMP
|
||||
ParallelType( "parallel" , (int)ThreadPool::OPEN_MP ) ,
|
||||
#else // !_OPENMP
|
||||
ParallelType( "parallel" , (int)ThreadPool::THREAD_POOL ) ,
|
||||
#endif // _OPENMP
|
||||
ScheduleType( "schedule" , (int)ThreadPool::DefaultSchedule ) ,
|
||||
ThreadChunkSize( "chunkSize" , (int)ThreadPool::DefaultChunkSize ) ,
|
||||
Threads( "threads" , (int)std::thread::hardware_concurrency() ) ;
|
||||
|
||||
cmdLineReadable
|
||||
Performance( "performance" ) ,
|
||||
NoLoadBalance( "noLoadBalance" ) ,
|
||||
Density( "density" ) ,
|
||||
LinearFit( "linearFit" ) ,
|
||||
OutputVoxelGrid( "grid" ) ,
|
||||
OutputBoundarySlices( "boundary" ) ,
|
||||
NoFuse( "noFuse" ) ,
|
||||
ShowDiscontinuity( "showDiscontinuity" );
|
||||
|
||||
cmdLineParameter< float >
|
||||
Scale( "scale" , 1.1f ) ,
|
||||
Width( "width" , 0.f ) ,
|
||||
Confidence( "confidence" , 0.f ) ,
|
||||
ConfidenceBias( "confidenceBias" , 0.f ) ,
|
||||
SamplesPerNode( "samplesPerNode" , 1.5f ) ,
|
||||
DataX( "data" , 32.f ) ,
|
||||
PointWeight( "pointWeight" ) ,
|
||||
CGSolverAccuracy( "cgAccuracy" , 1e-3f );
|
||||
|
||||
cmdLineReadable* params[] =
|
||||
{
|
||||
&Port , &ClientCount , &AddressPrefix , &Performance , &Verbose ,
|
||||
&In ,
|
||||
&Scale ,
|
||||
&PartitionDepth ,
|
||||
&FilesPerDir ,
|
||||
&TempDir ,
|
||||
&Out ,
|
||||
#ifdef FAST_COMPILE
|
||||
#else // !FAST_COMPILE
|
||||
&Degree , &BType ,
|
||||
#endif // FAST_COMPILE
|
||||
&Iters , &BaseVCycles , &KernelDepth , &BaseDepth , &PadSize , &BufferSize , &Depth ,
|
||||
&SolveDepth ,
|
||||
&NoLoadBalance , &Density , &LinearFit ,
|
||||
&NoFuse ,
|
||||
&Width , &Confidence , &ConfidenceBias , &SamplesPerNode , &DataX , &PointWeight , &CGSolverAccuracy ,
|
||||
&MaxMemoryGB , &ParallelType , &ScheduleType , &ThreadChunkSize , &Threads ,
|
||||
&PeakMemorySampleMS ,
|
||||
&OutputVoxelGrid ,
|
||||
&OutputBoundarySlices ,
|
||||
&ShowDiscontinuity ,
|
||||
NULL
|
||||
};
|
||||
|
||||
void ShowUsage( char* ex )
|
||||
{
|
||||
printf( "Usage: %s\n" , ex );
|
||||
printf( "\t --%s <input points>\n" , In.name );
|
||||
printf( "\t --%s <networked temporary directory>\n" , TempDir.name );
|
||||
printf( "\t --%s <output polygon mesh>\n" , Out.name );
|
||||
printf( "\t --%s <client count>\n" , ClientCount.name );
|
||||
|
||||
printf( "\t[--%s <preferred address prefix>]\n" , AddressPrefix.name );
|
||||
printf( "\t[--%s <listen port>=%d]\n" , Port.name , Port.value );
|
||||
|
||||
#ifdef FAST_COMPILE
|
||||
#else // !FAST_COMPILE
|
||||
printf( "\t[--%s <b-spline degree>=%d]\n" , Degree.name , Degree.value );
|
||||
printf( "\t[--%s <boundary type>=%d]\n" , BType.name , BType.value );
|
||||
for( int i=0 ; i<BOUNDARY_COUNT ; i++ ) printf( "\t\t%d] %s\n" , i , BoundaryNames[i] );
|
||||
#endif // FAST_COMPILE
|
||||
printf( "\t[--%s <minimum number of samples per node>=%f]\n" , SamplesPerNode.name, SamplesPerNode.value );
|
||||
printf( "\t[--%s <base depth>=%d]\n" , BaseDepth.name , BaseDepth.value );
|
||||
printf( "\t[--%s <max reconstruction depth>=%d]\n" , Depth.name , Depth.value );
|
||||
printf( "\t[--%s <partition depth>=%d]\n" , PartitionDepth.name , PartitionDepth.value );
|
||||
printf( "\t[--%s <kernel depth>]\n" , KernelDepth.name );
|
||||
printf( "\t[--%s <solver depth>]\n" , SolveDepth.name );
|
||||
printf( "\t[--%s <scale factor>=%f]\n" , Scale.name , Scale.value );
|
||||
printf( "\t[--%s <grid width>]\n" , Width.name );
|
||||
printf( "\t[--%s <iterations>=%d]\n" , Iters.name , Iters.value );
|
||||
printf( "\t[--%s <base MG solver v-cycles>=%d]\n" , BaseVCycles.name , BaseVCycles.value );
|
||||
printf( "\t[--%s <cg solver accuracy>=%g]\n" , CGSolverAccuracy.name , CGSolverAccuracy.value );
|
||||
printf( "\t[--%s <interpolation weight>=%.3e * <b-spline degree>]\n" , PointWeight.name , DefaultPointWeightMultiplier );
|
||||
printf( "\t[--%s <normal confidence exponent>=%f]\n" , Confidence.name , Confidence.value );
|
||||
printf( "\t[--%s <normal confidence bias exponent>=%f]\n" , ConfidenceBias.name , ConfidenceBias.value );
|
||||
printf( "\t[--%s <pull factor>=%f]\n" , DataX.name , DataX.value );
|
||||
printf( "\t[--%s <pad size>=%d]\n" , PadSize.name , PadSize.value );
|
||||
printf( "\t[--%s <buffer size>=%d]\n" , BufferSize.name , BufferSize.value );
|
||||
printf( "\t[--%s <num threads>=%d]\n" , Threads.name , Threads.value );
|
||||
printf( "\t[--%s <parallel type>=%d]\n" , ParallelType.name , ParallelType.value );
|
||||
for( size_t i=0 ; i<ThreadPool::ParallelNames.size() ; i++ ) printf( "\t\t%d] %s\n" , (int)i , ThreadPool::ParallelNames[i].c_str() );
|
||||
printf( "\t[--%s <schedue type>=%d]\n" , ScheduleType.name , ScheduleType.value );
|
||||
for( size_t i=0 ; i<ThreadPool::ScheduleNames.size() ; i++ ) printf( "\t\t%d] %s\n" , (int)i , ThreadPool::ScheduleNames[i].c_str() );
|
||||
printf( "\t[--%s <thread chunk size>=%d]\n" , ThreadChunkSize.name , ThreadChunkSize.value );
|
||||
printf( "\t[--%s <peak memory sampling rate (ms)>=%d]\n" , PeakMemorySampleMS.name , PeakMemorySampleMS.value );
|
||||
printf( "\t[--%s <maximum memory (in GB)>=%d]\n" , MaxMemoryGB.name , MaxMemoryGB.value );
|
||||
printf( "\t[--%s <slab files per directory>=%u]\n" , FilesPerDir.name , (unsigned int)FilesPerDir.value );
|
||||
printf( "\t[--%s <verbosity>=%d]\n" , Verbose.name , Verbose.value );
|
||||
printf( "\t[--%s]\n" , NoLoadBalance.name );
|
||||
printf( "\t[--%s]\n" , Density.name );
|
||||
printf( "\t[--%s]\n" , LinearFit.name );
|
||||
printf( "\t[--%s]\n" , OutputVoxelGrid.name );
|
||||
printf( "\t[--%s]\n" , OutputBoundarySlices.name );
|
||||
printf( "\t[--%s]\n" , ShowDiscontinuity.name );
|
||||
printf( "\t[--%s]\n" , NoFuse.name );
|
||||
|
||||
printf( "\t[--%s]\n" , Performance.name );
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
std::pair< PointPartition::PointSetInfo< Real , Dim > , PointPartition::Partition >
|
||||
Partition
|
||||
(
|
||||
std::vector< Socket > &clientSockets ,
|
||||
const PointPartitionClientServer::ClientPartitionInfo< Real > &clientPartitionInfo ,
|
||||
bool loadBalance ,
|
||||
bool performance
|
||||
)
|
||||
{
|
||||
Timer timer;
|
||||
|
||||
std::pair< PointPartition::PointSetInfo< Real , Dim > , PointPartition::Partition > pointSetInfoAndPartition = PointPartitionClientServer::RunServer< Real , Dim >( clientSockets , clientPartitionInfo , loadBalance );
|
||||
unsigned int peakMem = 0;
|
||||
for( unsigned int c=0 ; c<clientSockets.size() ; c++ )
|
||||
{
|
||||
unsigned int _peakMem;
|
||||
SocketStream( clientSockets[c] ).read( _peakMem );
|
||||
peakMem = std::max< unsigned int >( peakMem , _peakMem );
|
||||
}
|
||||
|
||||
if( performance )
|
||||
{
|
||||
StreamFloatPrecision sfp( std::cout , 2 );
|
||||
std::cout << "Partition performance:" << std::endl;
|
||||
std::cout << "\tPeak client memory: " << peakMem << " (MB)" << std::endl;
|
||||
std::cout << "\tPeak server memory: " << MemoryInfo::PeakMemoryUsageMB() << " (MB)" << std::endl;
|
||||
std::cout << "\tServer Time: " << timer.wallTime() << " (s)" << std::endl;
|
||||
}
|
||||
return pointSetInfoAndPartition;
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim , BoundaryType BType , unsigned int Degree >
|
||||
std::vector< unsigned int >
|
||||
Reconstruct
|
||||
(
|
||||
const PointPartition::PointSetInfo< Real , Dim > &pointSetInfo ,
|
||||
const PointPartition::Partition &pointPartition ,
|
||||
std::vector< Socket > &clientSockets ,
|
||||
const PoissonReconClientServer::ClientReconstructionInfo< Real , Dim > &clientReconInfo
|
||||
)
|
||||
{
|
||||
Timer timer;
|
||||
|
||||
// Clean up files if they were not propertly cleaned up before.
|
||||
for( unsigned int i=0 ; i<clientSockets.size() ; i++ ) PoissonReconClientServer::ClientServerStream< false >::Reset( i , clientReconInfo );
|
||||
|
||||
std::vector< unsigned int > sharedVertexCounts = PoissonReconClientServer::RunServer< Real , Dim , BType , Degree >( pointSetInfo , pointPartition , clientSockets , clientReconInfo , BaseVCycles.value , PeakMemorySampleMS.value<0 ? 0 : PeakMemorySampleMS.value , ShowDiscontinuity.set , OutputBoundarySlices.set );
|
||||
|
||||
unsigned int peakMem = 0;
|
||||
for( unsigned int i=0 ; i<clientSockets.size() ; i++ )
|
||||
{
|
||||
unsigned int _peakMem;
|
||||
SocketStream( clientSockets[i] ).read( _peakMem );
|
||||
peakMem = std::max< unsigned int >( peakMem , _peakMem );
|
||||
}
|
||||
|
||||
if( Performance.set )
|
||||
{
|
||||
StreamFloatPrecision sfp( std::cout , 2 );
|
||||
std::cout << "Reconstruction performance:" << std::endl;
|
||||
std::cout << "\tPeak client memory: " << peakMem << " (MB)" << std::endl;
|
||||
std::cout << "\tPeak server memory: " << MemoryInfo::PeakMemoryUsageMB() << " (MB)" << std::endl;
|
||||
std::cout << "\tServer Time: " << timer.wallTime() << " (s)" << std::endl;
|
||||
}
|
||||
|
||||
return sharedVertexCounts;
|
||||
}
|
||||
|
||||
|
||||
#ifdef FAST_COMPILE
|
||||
#else // !FAST_COMPILE
|
||||
template< typename Real , unsigned int Dim , BoundaryType BType >
|
||||
std::vector< unsigned int > Reconstruct( unsigned int degree , const PointPartition::PointSetInfo< Real , Dim > &pointSetInfo , const PointPartition::Partition &partition , std::vector< Socket > clientSockets , const PoissonReconClientServer::ClientReconstructionInfo< Real , Dim > &clientReconInfo )
|
||||
{
|
||||
switch( degree )
|
||||
{
|
||||
case 1: return Reconstruct< Real , Dim , BType , 1 >( pointSetInfo , partition , clientSockets , clientReconInfo );
|
||||
case 2: return Reconstruct< Real , Dim , BType , 2 >( pointSetInfo , partition , clientSockets , clientReconInfo );
|
||||
default: ERROR_OUT( "Only B-Splines of degree 1 - 2 are supported" );
|
||||
}
|
||||
return std::vector< unsigned int >();
|
||||
}
|
||||
|
||||
template< typename Real , unsigned int Dim >
|
||||
std::vector< unsigned int > Reconstruct( BoundaryType bType , unsigned int degree , const PointPartition::PointSetInfo< Real , Dim > &pointSetInfo , const PointPartition::Partition &partition , std::vector< Socket > clientSockets , const PoissonReconClientServer::ClientReconstructionInfo< Real , Dim > &clientReconInfo )
|
||||
{
|
||||
for( unsigned int i=0 ; i<clientSockets.size() ; i++ )
|
||||
{
|
||||
SocketStream( clientSockets[i] ).write( bType );
|
||||
SocketStream( clientSockets[i] ).write( degree );
|
||||
}
|
||||
switch( bType )
|
||||
{
|
||||
case BOUNDARY_FREE: return Reconstruct< Real , Dim , BOUNDARY_FREE >( degree , pointSetInfo , partition , clientSockets , clientReconInfo );
|
||||
case BOUNDARY_NEUMANN: return Reconstruct< Real , Dim , BOUNDARY_NEUMANN >( degree , pointSetInfo , partition , clientSockets , clientReconInfo );
|
||||
case BOUNDARY_DIRICHLET: return Reconstruct< Real , Dim , BOUNDARY_DIRICHLET >( degree , pointSetInfo , partition , clientSockets , clientReconInfo );
|
||||
default: ERROR_OUT( "Not a valid boundary type: " , bType );
|
||||
}
|
||||
return std::vector< unsigned int >();
|
||||
}
|
||||
#endif // FAST_COMPILE
|
||||
|
||||
template< typename Real , unsigned int Dim>
|
||||
void Merge
|
||||
(
|
||||
const std::vector< unsigned int > &sharedVertexCounts ,
|
||||
std::string header ,
|
||||
std::vector< Socket > &clientSockets ,
|
||||
const MergePlyClientServer::ClientMergePlyInfo &clientMergePlyInfo
|
||||
)
|
||||
{
|
||||
Timer timer;
|
||||
|
||||
MergePlyClientServer::RunServer< Real , Dim >( TempDir.value , TempDir.value , header , Out.value , clientSockets , sharedVertexCounts , clientMergePlyInfo , PeakMemorySampleMS.value );
|
||||
|
||||
unsigned int peakMem = 0;
|
||||
for( unsigned int i=0 ; i<clientSockets.size() ; i++ )
|
||||
{
|
||||
unsigned int _peakMem;
|
||||
SocketStream( clientSockets[i] ).read( _peakMem );
|
||||
peakMem = std::max< unsigned int >( peakMem , _peakMem );
|
||||
}
|
||||
|
||||
if( Performance.set )
|
||||
{
|
||||
StreamFloatPrecision sfp( std::cout , 2 );
|
||||
std::cout << "Merge performance:" << std::endl;
|
||||
std::cout << "\tPeak client memory: " << peakMem << " (MB)" << std::endl;
|
||||
std::cout << "\tPeak server memory: " << MemoryInfo::PeakMemoryUsageMB() << " (MB)" << std::endl;
|
||||
std::cout << "\tServer Time: " << timer.wallTime() << " (s)" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main( int argc , char* argv[] )
|
||||
{
|
||||
#ifdef ARRAY_DEBUG
|
||||
WARN( "Array debugging enabled" );
|
||||
#endif // ARRAY_DEBUG
|
||||
#ifdef USE_DOUBLE
|
||||
typedef double Real;
|
||||
#else // !USE_DOUBLE
|
||||
typedef float Real;
|
||||
#endif // USE_DOUBLE
|
||||
static const unsigned int Dim = DEFAULT_DIMENSION;
|
||||
|
||||
cmdLineParse( argc-1 , &argv[1] , params );
|
||||
|
||||
if( !In.set || !TempDir.set || !Out.set || !ClientCount.set )
|
||||
{
|
||||
ShowUsage( argv[0] );
|
||||
return 0;
|
||||
}
|
||||
if( PadSize.value<0 ) ERROR_OUT( "Padding size cannot be negative" );
|
||||
|
||||
if( Verbose.value>1 )
|
||||
{
|
||||
std::cout << "***********************************************************" << std::endl;
|
||||
std::cout << "***********************************************************" << std::endl;
|
||||
std::cout << "** Running Poisson Reconstruction Server (Version " << VERSION << ") **" << std::endl;
|
||||
std::cout << "***********************************************************" << std::endl;
|
||||
std::cout << "***********************************************************" << std::endl;
|
||||
}
|
||||
|
||||
#ifdef FAST_COMPILE
|
||||
if( !PointWeight.set ) PointWeight.value = DefaultPointWeightMultiplier * DEFAULT_FEM_DEGREE;
|
||||
#else // !FAST_COMPILE
|
||||
if( !PointWeight.set ) PointWeight.value = DefaultPointWeightMultiplier * Degree.value;
|
||||
#endif // FAST_COMPILE
|
||||
|
||||
if( Depth.set && Width.value>0 )
|
||||
{
|
||||
WARN( "Both --" , Depth.name , " and --" , Width.name , " set, ignoring --" , Width.name );
|
||||
Width.value = 0;
|
||||
}
|
||||
|
||||
if( MaxMemoryGB.value>0 ) SetPeakMemoryMB( MaxMemoryGB.value<<10 );
|
||||
ThreadPool::DefaultChunkSize = ThreadChunkSize.value;
|
||||
ThreadPool::DefaultSchedule = (ThreadPool::ScheduleType)ScheduleType.value;
|
||||
ThreadPool::Init( (ThreadPool::ParallelType)ParallelType.value , Threads.value );
|
||||
if( !Threads.set && Verbose.value>1 ) std::cout << "Running with " << Threads.value << " threads" << std::endl;
|
||||
std::string header;
|
||||
|
||||
// Create the connections to the clients
|
||||
std::vector< Socket > clientSockets( ClientCount.value );
|
||||
{
|
||||
int port = Port.value;
|
||||
|
||||
char address[512];
|
||||
GetHostAddress( address , AddressPrefix.value.c_str() );
|
||||
|
||||
// Create a listening SOCKET for connecting to server
|
||||
AcceptorSocket listenSocket = GetListenSocket( port );
|
||||
if( listenSocket == _INVALID_ACCEPTOR_SOCKET_ ) ERROR_OUT( "Could not create listener socket" );
|
||||
std::cout << "Server Address: " << address << ":" << port << std::endl;
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "PR_" << port;
|
||||
header = ss.str();
|
||||
}
|
||||
|
||||
// Establish a connection to the clients
|
||||
for( unsigned int i=0 ; i<(unsigned int)ClientCount.value ; i++ )
|
||||
{
|
||||
clientSockets[i] = AcceptSocket( listenSocket );
|
||||
if( Verbose.value>1 ) std::cout << "Connected to process: " << (i+1) << " / " << ClientCount.value << std::endl;
|
||||
}
|
||||
CloseAcceptorSocket( listenSocket );
|
||||
}
|
||||
std::vector< unsigned int > sharedVertexCounts;
|
||||
|
||||
|
||||
std::pair< PointPartition::PointSetInfo< Real , Dim > , PointPartition::Partition > pointSetInfoAndPartition;
|
||||
|
||||
// Get the partitioned points
|
||||
{
|
||||
PointPartition::CreatePointSlabDirs( PointPartition::FileDir( TempDir.value , header ) , 1<<PartitionDepth.value , FilesPerDir.value );
|
||||
PointPartitionClientServer::ClientPartitionInfo< Real > clientPartitionInfo;
|
||||
clientPartitionInfo.in = In.value;
|
||||
clientPartitionInfo.tempDir = TempDir.value;
|
||||
clientPartitionInfo.outDir = TempDir.value;
|
||||
clientPartitionInfo.outHeader = header;
|
||||
clientPartitionInfo.slabs = 1<<PartitionDepth.value;
|
||||
clientPartitionInfo.filesPerDir = FilesPerDir.value;
|
||||
clientPartitionInfo.bufferSize = BufferSize.value;
|
||||
clientPartitionInfo.scale = Scale.value;
|
||||
clientPartitionInfo.verbose = Verbose.value>1;
|
||||
pointSetInfoAndPartition = Partition< Real , Dim >( clientSockets , clientPartitionInfo , !NoLoadBalance.set , Performance.set );
|
||||
}
|
||||
|
||||
// Reconstruct the slabs
|
||||
{
|
||||
if( Width.value>0 )
|
||||
{
|
||||
Real maxScale = 0;
|
||||
for( unsigned int i=0 ; i<Dim ; i++ ) maxScale = std::max< Real >( maxScale , (Real)1./pointSetInfoAndPartition.first.modelToUnitCube(i,i) );
|
||||
Depth.value = (unsigned int)ceil( std::max< double >( 0. , log( maxScale/Width.value )/log(2.) ) );
|
||||
}
|
||||
PoissonReconClientServer::ClientReconstructionInfo< Real , Dim > clientReconInfo;
|
||||
clientReconInfo.inDir = TempDir.value;
|
||||
clientReconInfo.tempDir = TempDir.value;
|
||||
clientReconInfo.outDir = TempDir.value;
|
||||
clientReconInfo.header = header;
|
||||
clientReconInfo.bufferSize = BufferSize.value;
|
||||
clientReconInfo.iters = Iters.value;
|
||||
clientReconInfo.pointWeight = PointWeight.value;
|
||||
clientReconInfo.confidence = Confidence.value;
|
||||
clientReconInfo.confidenceBias = ConfidenceBias.value;
|
||||
clientReconInfo.kernelDepth = KernelDepth.value;
|
||||
clientReconInfo.solveDepth = SolveDepth.value;
|
||||
clientReconInfo.samplesPerNode = SamplesPerNode.value;
|
||||
clientReconInfo.dataX = DataX.value;
|
||||
clientReconInfo.density = Density.set;
|
||||
clientReconInfo.linearFit = LinearFit.set;
|
||||
PoissonReconClientServer::ClientReconstructionInfo< Real , Dim >::MergeType::TOPOLOGY_AND_FUNCTION;
|
||||
clientReconInfo.ouputVoxelGrid = OutputVoxelGrid.set;
|
||||
clientReconInfo.verbose = Verbose.value;
|
||||
clientReconInfo.filesPerDir = FilesPerDir.value;
|
||||
clientReconInfo.padSize = PadSize.value;
|
||||
|
||||
clientReconInfo.reconstructionDepth = Depth.value;
|
||||
clientReconInfo.sharedDepth = 0;
|
||||
while( ((size_t)1<<clientReconInfo.sharedDepth) < pointSetInfoAndPartition.first.pointsPerSlab.size() ) clientReconInfo.sharedDepth++;
|
||||
if( ((size_t)1<<clientReconInfo.sharedDepth)!=pointSetInfoAndPartition.first.pointsPerSlab.size() ) ERROR_OUT( "Number of point slabs is not a power of two: " , pointSetInfoAndPartition.first.pointsPerSlab.size() );
|
||||
clientReconInfo.baseDepth = BaseDepth.value;
|
||||
|
||||
if( clientReconInfo.pointWeight<0 ) ERROR_OUT( "Expected non-negative point-weight" );
|
||||
|
||||
if( clientReconInfo.sharedDepth>clientReconInfo.reconstructionDepth ) ERROR_OUT( "Slab depth cannot exceed reconstruction depth: " , clientReconInfo.sharedDepth , " <= " , clientReconInfo.reconstructionDepth );
|
||||
if( clientReconInfo.baseDepth>clientReconInfo.sharedDepth )
|
||||
{
|
||||
if( BaseDepth.set ) ERROR_OUT( "Base depth cannot exceed shared depth: " , clientReconInfo.baseDepth , " <=" , clientReconInfo.sharedDepth );
|
||||
else clientReconInfo.baseDepth = clientReconInfo.sharedDepth;
|
||||
}
|
||||
if( !KernelDepth.set ) KernelDepth.value = clientReconInfo.reconstructionDepth-2;
|
||||
clientReconInfo.kernelDepth = KernelDepth.value;
|
||||
|
||||
if( clientReconInfo.kernelDepth>clientReconInfo.reconstructionDepth )
|
||||
{
|
||||
WARN( "Kernel depth should not exceed depth: " , clientReconInfo.kernelDepth , " <= " , clientReconInfo.reconstructionDepth );
|
||||
clientReconInfo.kernelDepth = clientReconInfo.reconstructionDepth;
|
||||
}
|
||||
|
||||
clientReconInfo.solveDepth = SolveDepth.set ? SolveDepth.value : clientReconInfo.reconstructionDepth;
|
||||
if( clientReconInfo.solveDepth>clientReconInfo.reconstructionDepth )
|
||||
{
|
||||
WARN( "Solve depth cannot exceed reconstruction depth: " , clientReconInfo.solveDepth , " <= " , clientReconInfo.reconstructionDepth );
|
||||
clientReconInfo.solveDepth = clientReconInfo.reconstructionDepth;
|
||||
}
|
||||
if( clientReconInfo.solveDepth<clientReconInfo.baseDepth )
|
||||
{
|
||||
WARN( "Solve depth cannot be smaller than base depth: " , clientReconInfo.solveDepth , " >= " , clientReconInfo.baseDepth );
|
||||
clientReconInfo.solveDepth = clientReconInfo.baseDepth;
|
||||
}
|
||||
#ifdef FAST_COMPILE
|
||||
sharedVertexCounts = Reconstruct< Real , Dim , DEFAULT_FEM_BOUNDARY , DEFAULT_FEM_DEGREE >( pointSetInfoAndPartition.first , pointSetInfoAndPartition.second , clientSockets , clientReconInfo );
|
||||
#else // !FAST_COMPILE
|
||||
sharedVertexCounts = Reconstruct< Real , Dim >( (BoundaryType)BType.value , Degree.value , pointSetInfoAndPartition.first , pointSetInfoAndPartition.second , clientSockets , clientReconInfo );
|
||||
#endif // FAST_COMPILE
|
||||
}
|
||||
|
||||
if( Verbose.value>1 && !NoFuse.set )
|
||||
for( unsigned int i=0 ; i<sharedVertexCounts.size() ; i++ ) std::cout << "Vertices[" << (i+1) << "] " << sharedVertexCounts[i] << std::endl;
|
||||
|
||||
PointPartition::RemovePointSlabDirs( PointPartition::FileDir( TempDir.value , header ) );
|
||||
|
||||
{
|
||||
if( NoFuse.set ) for( unsigned int i=0 ; i<sharedVertexCounts.size() ; i++ ) sharedVertexCounts[i] = 0;
|
||||
MergePlyClientServer::ClientMergePlyInfo clientMergePlyInfo;
|
||||
clientMergePlyInfo.auxProperties = pointSetInfoAndPartition.first.auxiliaryProperties;
|
||||
clientMergePlyInfo.bufferSize = BufferSize.value;
|
||||
clientMergePlyInfo.verbose = Verbose.value!=0;
|
||||
Merge< Real , Dim >( sharedVertexCounts , header , clientSockets , clientMergePlyInfo );
|
||||
|
||||
auto InFile = [&]( unsigned int idx )
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << header << "." << idx << ".ply";
|
||||
return PointPartition::FileDir( TempDir.value , ss.str() );
|
||||
};
|
||||
|
||||
for( unsigned int i=0 ; i<clientSockets.size() ; i++ )
|
||||
{
|
||||
std::string fileName = InFile(i);
|
||||
std::remove( fileName.c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
for( unsigned int i=0 ; i<clientSockets.size() ; i++ ) CloseSocket( clientSockets[i] );
|
||||
|
||||
ThreadPool::Terminate();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
+4
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2019, Michael Kazhdan and Matthew Bolitho
|
||||
Copyright (c) 2019, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -29,11 +29,13 @@ DAMAGE.
|
||||
#ifndef PRE_PROCESSOR_INCLUDED
|
||||
#define PRE_PROCESSOR_INCLUDED
|
||||
|
||||
#ifndef BIG_DATA // Allow over-riding if defined before PreProcessor.h
|
||||
#undef BIG_DATA // Supports processing requiring more than 32-bit integers for indexing
|
||||
// Note: enabling BIG_DATA can generate .ply files using "longlong" for vertex indices instead of "int".
|
||||
// These are not standardly supported by .ply reading/writing applications.
|
||||
// The executable ChunkPLY can help by partitioning the mesh into more manageable chunks
|
||||
// (each of which is small enough to be represented using 32-bit indexing.)
|
||||
#endif // BIG_DATA
|
||||
|
||||
#define FAST_COMPILE // If enabled, only a single version of the code is compiled
|
||||
#undef SHOW_WARNINGS // Display compilation warnings
|
||||
@@ -43,7 +45,7 @@ DAMAGE.
|
||||
#define USE_DEEP_TREE_NODES // Chances are that if you are using big data, you want to support a tree with depth>15.
|
||||
#endif // BIG_DATA
|
||||
|
||||
#define VERSION "13.99" // The version of the code
|
||||
#define VERSION "14.00" // The version of the code
|
||||
#define MEMORY_ALLOCATOR_BLOCK_SIZE 1<<12 // The chunk size for memory allocation
|
||||
|
||||
#endif // PRE_PROCESSOR_INCLUDED
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
|
||||
Copyright (c) 2014, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
Copyright (c) 2008, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer. Redistributions in binary form must reproduce
|
||||
the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Johns Hopkins University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SOCKET_INCLUDED
|
||||
#define SOCKET_INCLUDED
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0601
|
||||
#endif // _WIN32_WINNT
|
||||
#endif // _WIN32
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/asio.hpp>
|
||||
#include <stdarg.h>
|
||||
#include <thread>
|
||||
#include "Array.h"
|
||||
#include "MyMiscellany.h"
|
||||
#include "Streams.h"
|
||||
|
||||
static const unsigned int SOCKET_CONNECT_WAIT = 500; // Default time to wait on a socket (in ms)
|
||||
|
||||
typedef boost::asio::ip::tcp::socket *Socket;
|
||||
typedef boost::asio::ip::tcp::acceptor *AcceptorSocket;
|
||||
typedef boost::asio::ip::address EndpointAddress;
|
||||
const Socket _INVALID_SOCKET_ = (Socket)NULL;
|
||||
const AcceptorSocket _INVALID_ACCEPTOR_SOCKET_ = (AcceptorSocket)NULL;
|
||||
static boost::asio::io_service io_service;
|
||||
|
||||
template< class C > int socket_receive( Socket &s , C *destination , size_t len )
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
int ret = (int)( boost::asio::read( *s , boost::asio::buffer( destination , len ) , ec ) );
|
||||
if( ec ) ERROR_OUT( "Failed to read from socket" );
|
||||
return ret;
|
||||
}
|
||||
|
||||
template< class C > int socket_send( Socket& s , const C* source , size_t len )
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
int ret = (int)( boost::asio::write( *s , boost::asio::buffer( source , len ) , ec ) );
|
||||
if( ec ) ERROR_OUT( "Failed to write to socket" );
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline bool AddressesEqual( const EndpointAddress& a1 , const EndpointAddress& a2 ){ return a1.to_string()==a2.to_string(); }
|
||||
inline const char *LastSocketError( void ){ return ""; }
|
||||
inline void PrintHostAddresses( FILE* fp )
|
||||
{
|
||||
boost::asio::ip::tcp::resolver resolver( io_service );
|
||||
boost::asio::ip::tcp::resolver::query query( boost::asio::ip::host_name() , std::string( "" ) , boost::asio::ip::resolver_query_base::numeric_service );
|
||||
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve( query ) , end;
|
||||
for( int count=0 ; iterator!=end ; )
|
||||
{
|
||||
if( (*iterator).endpoint().address().is_v4() ) fprintf( fp , "%d] %s\n" , count++ , (*iterator).endpoint().address().to_string().c_str() );
|
||||
// else fprintf( fp , "%d]* %s\n" , count++ , (*iterator).endpoint().address().to_string().c_str() );
|
||||
iterator++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ARRAY_DEBUG
|
||||
template< class C >
|
||||
int socket_receive( Socket& s , Array< C > destination , size_t len )
|
||||
{
|
||||
if( len>destination.maximum()*sizeof( C ) )
|
||||
{
|
||||
fprintf( stderr , "Size of socket_receive exceeds destination maximum: %zd > %zd\n" , len , destination.maximum()*sizeof( C ) );
|
||||
ASSERT( 0 );
|
||||
exit( 0 );
|
||||
}
|
||||
return socket_receive( s , (char*)&destination[0] , len );
|
||||
}
|
||||
template< class C >
|
||||
int socket_send( Socket s , ConstArray< C > source , size_t len )
|
||||
{
|
||||
if( len>source.maximum()*sizeof( C ) )
|
||||
{
|
||||
fprintf( stderr , "Size of socket_send exceeds source maximum: %zd > %zd\n" , len , source.maximum()*sizeof( C ) );
|
||||
ASSERT( 0 );
|
||||
exit( 0 );
|
||||
}
|
||||
return socket_send( s , (char*)&source[0] , len );
|
||||
}
|
||||
#endif // ARRAY_DEBUG
|
||||
|
||||
class ConnectionData
|
||||
{
|
||||
public:
|
||||
EndpointAddress localAddr , peerAddr;
|
||||
int localPort , peerPort;
|
||||
};
|
||||
|
||||
|
||||
template< class C > bool ReceiveOnSocket( Socket &s , Pointer( C ) data , size_t dataSize );
|
||||
template< class C > bool SendOnSocket ( Socket &s , ConstPointer( C ) data , size_t dataSize );
|
||||
template< class C > bool SendOnSocket ( Socket &s , Pointer( C ) data , size_t dataSize );
|
||||
template< class C > void ReceiveOnSocket( Socket &s , Pointer( C ) data , size_t dataSize , const char *errorMessage , ... );
|
||||
template< class C > void SendOnSocket ( Socket &s , ConstPointer( C ) data , size_t dataSize , const char *errorMessage , ... );
|
||||
template< class C > void SendOnSocket ( Socket &s , Pointer( C ) data , size_t dataSize , const char *errorMessage , ... );
|
||||
|
||||
AcceptorSocket GetListenSocket( int& port );
|
||||
Socket AcceptSocket( AcceptorSocket listen );
|
||||
Socket GetConnectSocket( const char* address , int port , int ms=5 , bool progress=false );
|
||||
Socket GetConnectSocket( EndpointAddress , int port , int ms=5 , bool progress=false );
|
||||
void CloseSocket( Socket& s );
|
||||
void CloseAcceptorSocket( AcceptorSocket& s );
|
||||
EndpointAddress GetLocalSocketEndpointAddress( Socket& s );
|
||||
int GetLocalSocketPort ( Socket& s );
|
||||
EndpointAddress GetLocalSocketEndpointAddress( Socket& s );
|
||||
int GetPeerSocketPort ( Socket& s );
|
||||
bool GetHostAddress( char* address , const char* prefix = NULL );
|
||||
bool GetHostEndpointAddress( EndpointAddress* address , const char* prefix=NULL );
|
||||
void PrintHostAddress( void );
|
||||
|
||||
struct SocketStream : public BinaryStream
|
||||
{
|
||||
SocketStream( Socket socket=_INVALID_SOCKET_ ) : _socket(socket){}
|
||||
protected:
|
||||
Socket _socket;
|
||||
bool _read( Pointer( unsigned char ) ptr , size_t sz ){ return socket_receive( _socket , ptr , sizeof(unsigned char)*sz )==sz; }
|
||||
bool _write( ConstPointer( unsigned char ) ptr , size_t sz ){ return socket_send ( _socket , ptr , sizeof(unsigned char)*sz )==sz; }
|
||||
};
|
||||
|
||||
|
||||
#include "Socket.inl"
|
||||
#endif // SOCKET_INCLUDED
|
||||
+239
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
Copyright (c) 2008, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer. Redistributions in binary form must reproduce
|
||||
the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Johns Hopkins University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
template<class C>
|
||||
bool ReceiveOnSocket( Socket& s , Pointer( C ) data , size_t dataSize )
|
||||
{
|
||||
#ifdef ARRAY_DEBUG
|
||||
if( dataSize>data.maximum()*sizeof( C ) ) ERROR_OUT( "Size of socket read exceeds source maximum: " , dataSize , " > " , data.maximum()*sizeof( C ) );
|
||||
#endif // ARRAY_DEBUG
|
||||
unsigned long long rec=0;
|
||||
while( rec!=dataSize )
|
||||
{
|
||||
int tmp = socket_receive( s , ( ( Pointer( char ) ) data) + rec , dataSize-rec );
|
||||
if( tmp<=0 )
|
||||
{
|
||||
if( !tmp ) ERROR_OUT( "Connection Closed" );
|
||||
else ERROR_OUT( "socket_receive from client failed: " , LastSocketError() );
|
||||
return false;
|
||||
}
|
||||
rec+=tmp;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class C>
|
||||
bool SendOnSocket( Socket& s , ConstPointer( C ) data , size_t dataSize )
|
||||
{
|
||||
#ifdef ARRAY_DEBUG
|
||||
if( dataSize>data.maximum()*sizeof( C ) ) ERROR_OUT( "Size of socket write exceeds source maximum: " , dataSize , " > " , data.maximum()*sizeof( C ) );
|
||||
#endif // ARRAY_DEBUG
|
||||
if( socket_send( s , ( ConstPointer( char ) )data , dataSize )<0 )
|
||||
{
|
||||
ERROR_OUT( "socket_send to client failed (" , s , "): " , LastSocketError() );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class C>
|
||||
bool SendOnSocket( Socket& s , Pointer( C ) data , size_t dataSize ){ return SendOnSocket( ( ConstPointer( C ) )data , dataSize ); }
|
||||
|
||||
template<class C>
|
||||
void ReceiveOnSocket( Socket& s , Pointer( C ) data , size_t dataSize , const char* errorMessage , ... )
|
||||
{
|
||||
#ifdef ARRAY_DEBUG
|
||||
if( dataSize>data.maximum()*sizeof( C ) ) ERROR_OUT( "Size of socket read exceeds source maximum: " , dataSize , " > " , data.maximum()*sizeof( C ) );
|
||||
#endif // ARRAY_DEBUG
|
||||
unsigned long long rec=0;
|
||||
while( rec!=dataSize )
|
||||
{
|
||||
int tmp = socket_receive( s , ( ( Pointer( char ) ) data) + rec , dataSize-rec );
|
||||
if( tmp<=0 )
|
||||
{
|
||||
if( !tmp ) ERROR_OUT( "Connection Closed" );
|
||||
else ERROR_OUT( "socket_receive from client failed: " , LastSocketError() );
|
||||
{
|
||||
fprintf( stderr , "\t" );
|
||||
va_list args;
|
||||
va_start( args , errorMessage );
|
||||
vfprintf( stderr , errorMessage , args );
|
||||
va_end( args );
|
||||
fprintf( stderr , "\n" );
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
rec+=tmp;
|
||||
}
|
||||
}
|
||||
|
||||
template<class C>
|
||||
void SendOnSocket( Socket& s , ConstPointer( C ) data , size_t dataSize , const char* errorMessage , ... )
|
||||
{
|
||||
#ifdef ARRAY_DEBUG
|
||||
if( dataSize>data.maximum()*sizeof( C ) ) ERROR_OUT( "Size of socket write exceeds source maximum: " , dataSize , " > " , data.maximum()*sizeof( C ) );
|
||||
#endif // ARRAY_DEBUG
|
||||
if( socket_send( s , ( ConstPointer( char ) )data , dataSize )<0 )
|
||||
{
|
||||
fprintf( stderr , "socket_send to client failed: %s\n" , LastSocketError());
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
template<class C>
|
||||
void SendOnSocket( Socket& s , Pointer( C ) data , size_t dataSize , const char* errorMessage , ... )
|
||||
{
|
||||
#ifdef ARRAY_DEBUG
|
||||
if( dataSize>data.maximum()*sizeof( C ) ) ERROR_OUT( "Size of socket write exceeds source maximum: " , dataSize , " > " , data.maximum()*sizeof( C ) );
|
||||
#endif // ARRAY_DEBUG
|
||||
if( socket_send( s , ( ConstPointer( char ) )data , dataSize )<0 )
|
||||
{
|
||||
fprintf( stderr , "socket_send to client failed: %s\n" , LastSocketError());
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool GetHostEndpointAddress( EndpointAddress* address , const char* prefix )
|
||||
{
|
||||
boost::asio::ip::tcp::resolver resolver( io_service );
|
||||
boost::asio::ip::tcp::resolver::query query( boost::asio::ip::host_name() , std::string( "" ) , boost::asio::ip::resolver_query_base::numeric_service );
|
||||
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve( query ) , end;
|
||||
for( int count=0 ; iterator!=end ; )
|
||||
{
|
||||
if( (*iterator).endpoint().address().is_v4() )
|
||||
{
|
||||
std::string addrss_string = (*iterator).endpoint().address().to_string();
|
||||
const char* _address = addrss_string.c_str();
|
||||
if( !prefix || strstr( _address , prefix ) )
|
||||
{
|
||||
*address = (*iterator).endpoint().address();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
iterator++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool GetHostAddress( char* address , const char* prefix )
|
||||
{
|
||||
EndpointAddress _address;
|
||||
if( !GetHostEndpointAddress( &_address , prefix ) ) return false;
|
||||
strcpy( address , _address.to_string().c_str() );
|
||||
return true;
|
||||
}
|
||||
|
||||
inline int GetLocalSocketPort( Socket& s )
|
||||
{
|
||||
return s->local_endpoint().port();
|
||||
}
|
||||
|
||||
inline EndpointAddress GetLocalSocketEndpointAddress( Socket& s )
|
||||
{
|
||||
return s->local_endpoint().address();
|
||||
}
|
||||
|
||||
inline int GetPeerSocketPort( Socket& s )
|
||||
{
|
||||
return s->remote_endpoint().port();
|
||||
}
|
||||
|
||||
inline EndpointAddress GetPeerSocketEndpointAddress( Socket& s )
|
||||
{
|
||||
return s->remote_endpoint().address();
|
||||
}
|
||||
|
||||
inline Socket GetConnectSocket( const char* address , int port , int ms , bool progress )
|
||||
{
|
||||
char _port[128];
|
||||
sprintf( _port , "%d" , port );
|
||||
boost::asio::ip::tcp::resolver resolver( io_service );
|
||||
boost::asio::ip::tcp::resolver::query query( address , _port );
|
||||
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve( query );
|
||||
Socket s = new boost::asio::ip::tcp::socket( io_service );
|
||||
boost::system::error_code ec;
|
||||
long long sleepCount = 0;
|
||||
do
|
||||
{
|
||||
boost::asio::connect( *s , resolver.resolve(query) , ec );
|
||||
sleepCount++;
|
||||
std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) );
|
||||
if( progress && !(sleepCount%ms) ) printf( "." );
|
||||
}
|
||||
while( ec );
|
||||
if( progress ) printf( "\n" ) , fflush( stdout );
|
||||
return s;
|
||||
}
|
||||
|
||||
inline Socket GetConnectSocket( EndpointAddress address , int port , int ms , bool progress )
|
||||
{
|
||||
char _port[128];
|
||||
sprintf( _port , "%d" , port );
|
||||
boost::asio::ip::tcp::resolver resolver( io_service );
|
||||
boost::asio::ip::tcp::resolver::query query( address.to_string().c_str() , _port );
|
||||
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve( query );
|
||||
Socket s = new boost::asio::ip::tcp::socket( io_service );
|
||||
boost::system::error_code ec;
|
||||
long long sleepCount = 0;
|
||||
do
|
||||
{
|
||||
boost::asio::connect( *s , resolver.resolve(query) , ec );
|
||||
sleepCount++;
|
||||
std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) );
|
||||
if( progress && !(sleepCount%ms) ) std::cout << ".";
|
||||
}
|
||||
while( ec );
|
||||
if( progress ) std::cout << std::endl;
|
||||
return s;
|
||||
}
|
||||
|
||||
inline Socket AcceptSocket( AcceptorSocket listen )
|
||||
{
|
||||
Socket s = new boost::asio::ip::tcp::socket( io_service );
|
||||
listen->accept( *s );
|
||||
return s;
|
||||
}
|
||||
|
||||
inline AcceptorSocket GetListenSocket( int &port )
|
||||
{
|
||||
AcceptorSocket s = new boost::asio::ip::tcp::acceptor( io_service , boost::asio::ip::tcp::endpoint( boost::asio::ip::tcp::v4() , port ) );
|
||||
port = s->local_endpoint().port();
|
||||
return s;
|
||||
}
|
||||
|
||||
inline void CloseSocket( Socket& s )
|
||||
{
|
||||
delete s;
|
||||
s = _INVALID_SOCKET_;
|
||||
}
|
||||
|
||||
inline void CloseAcceptorSocket( AcceptorSocket& s )
|
||||
{
|
||||
delete s;
|
||||
s = _INVALID_ACCEPTOR_SOCKET_;
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
|
||||
Copyright (c) 2020, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
|
||||
Copyright (c) 2020, Michael Kazhdan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
||||
Reference in New Issue
Block a user