Version 14.00

This commit is contained in:
mkazhdan
2023-05-02 18:26:03 -04:00
parent 86aede4f68
commit d9df5cd413
38 changed files with 6547 additions and 285 deletions
+101 -1
View File
@@ -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
+37 -7
View File
@@ -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
View File
@@ -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>
-84
View File
@@ -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>
+171
View File
@@ -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>
+171
View File
@@ -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 -1
View File
@@ -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,
+3 -1
View File
@@ -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;
-1
View File
@@ -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
+2
View File
@@ -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
View File
@@ -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
+1
View File
@@ -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
View File
@@ -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"
+28
View File
@@ -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>
+71
View File
@@ -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
+530
View File
@@ -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
View File
@@ -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();
}
+28
View File
@@ -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
View File
@@ -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
View File
@@ -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 );
+3 -2
View File
@@ -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;
}
+161
View File
@@ -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
+659
View File
@@ -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++;
}
+70
View File
@@ -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
+471
View File
@@ -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
View File
@@ -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;
+744
View File
@@ -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;
}
+208
View File
@@ -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;
}
+97
View File
@@ -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
+386
View File
@@ -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();
}
+515
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 -1
View File
@@ -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,