├── .appveyor.yml
├── .clang-format
├── .gitignore
├── .gitmodules
├── .travis.yml
├── 3rdparty
└── CMakeLists.txt
├── CMakeLists.txt
├── LICENSE
├── README.md
├── data
├── building_blocks_fig1.svg
├── building_blocks_fig1.xml
├── building_blocks_fig11.xml
├── building_blocks_fig6a.svg
├── building_blocks_fig6a.xml
├── building_blocks_fig6b.svg
├── building_blocks_fig6b.xml
├── building_blocks_fig6c.svg
├── building_blocks_fig6c.xml
├── building_blocks_fig6d.svg
├── building_blocks_fig6d.xml
├── config.txt
├── planar_graph_fig1.svg
├── planar_graph_fig1.xml
├── planar_graph_fig10_floor1.svg
├── planar_graph_fig10_floor1.xml
├── planar_graph_fig10_floor2.svg
├── planar_graph_fig10_floor2.xml
├── planar_graph_fig10_floor3.svg
├── planar_graph_fig10_floor3.xml
├── planar_graph_fig11.svg
├── planar_graph_fig11.xml
├── planar_graph_fig7_bottom.svg
├── planar_graph_fig7_bottom.xml
├── planar_graph_fig7_top.svg
├── planar_graph_fig7_top.xml
├── planar_graph_fig8.svg
├── planar_graph_fig8.xml
├── planar_graph_fig9.svg
└── planar_graph_fig9.xml
└── src
├── CMakeLists.txt
├── ConfigSpace.cpp
├── ConfigSpace.h
├── GraphChain.h
├── GraphEdge.h
├── GraphFace.h
├── GraphNode.h
├── LevelConfig.cpp
├── LevelConfig.h
├── LevelMath.cpp
├── LevelMath.h
├── LevelSynth.cpp
├── LevelSynth.h
├── LevelTimer.h
├── LineBase.h
├── PlanarGraph.cpp
├── PlanarGraph.h
├── Room.cpp
├── Room.h
├── RoomEdge.h
├── RoomLayout.cpp
├── RoomLayout.h
├── RoomTemplates.cpp
├── RoomTemplates.h
├── clipperWrapper.cpp
├── clipperWrapper.h
├── levels.cpp
├── util.h
└── vec.h
/.appveyor.yml:
--------------------------------------------------------------------------------
1 | version: "{build}"
2 |
3 | os: Visual Studio 2015
4 |
5 | platform:
6 | - Win32
7 | #- x64
8 |
9 | environment:
10 | MSVC_DEFAULT_OPTIONS: ON
11 | BOOST_ROOT: C:\Libraries\boost_1_69_0
12 | BOOST_LIBRARYDIR: C:\Libraries\boost_1_69_0\lib32-msvc-14.0
13 |
14 | configuration:
15 | #- Debug
16 | - Release
17 |
18 | clone_folder: C:\projects\LevelSyn
19 |
20 | branches:
21 | only:
22 | - master
23 |
24 | install:
25 | - git submodule update --init --recursive
26 |
27 | build_script:
28 | - cd C:\projects\LevelSyn
29 | - md build
30 | - cd build
31 | - if "%platform%"=="Win32" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015
32 | - if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015 Win64
33 | - cmake -G "%CMAKE_GENERATOR_NAME%" -DCMAKE_BUILD_TYPE=%configuration% -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_LIBRARYDIR%" -DBoost_USE_STATIC_LIBS="ON" ../
34 | - msbuild %MSBuildOptions% LevelSyn.sln
35 | - cd ..\bin
36 | - levels.exe ..\data\planar_graph_fig1.xml ..\data\building_blocks_fig1.xml ..\data\config.txt 10
37 |
--------------------------------------------------------------------------------
/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | Language: Cpp
3 | BasedOnStyle: LLVM
4 | AccessModifierOffset: -4
5 | #AlignAfterOpenBracket: Align
6 | AlignConsecutiveAssignments: false
7 | AlignConsecutiveDeclarations: false
8 | AlignEscapedNewlines: Left
9 | AlignOperands: false
10 | AlignTrailingComments: true
11 | AllowAllParametersOfDeclarationOnNextLine: true
12 | AllowShortBlocksOnASingleLine: Empty
13 | AllowShortCaseLabelsOnASingleLine: false
14 | AllowShortFunctionsOnASingleLine: InlineOnly
15 | AllowShortIfStatementsOnASingleLine: WithoutElse
16 | AllowShortLoopsOnASingleLine: false
17 | AlwaysBreakAfterDefinitionReturnType: None
18 | AlwaysBreakAfterReturnType: None
19 | AlwaysBreakBeforeMultilineStrings: false
20 | AlwaysBreakTemplateDeclarations: MultiLine
21 | BinPackArguments: true
22 | BinPackParameters: true
23 | BreakBeforeBraces: Custom
24 | BraceWrapping:
25 | AfterClass: true
26 | AfterControlStatement: Always
27 | AfterEnum: true
28 | AfterFunction: true
29 | AfterNamespace: true
30 | AfterObjCDeclaration: true
31 | AfterStruct: true
32 | AfterUnion: true
33 | AfterExternBlock: true
34 | BeforeCatch: true
35 | BeforeElse: true
36 | IndentBraces: false
37 | SplitEmptyFunction: false
38 | SplitEmptyRecord: false
39 | SplitEmptyNamespace: false
40 | BreakBeforeBinaryOperators: None
41 | BreakInheritanceList: AfterColon
42 | BreakBeforeTernaryOperators: false
43 | BreakConstructorInitializers: AfterColon
44 | BreakAfterJavaFieldAnnotations: true
45 | BreakStringLiterals: false
46 | ColumnLimit: 0
47 | CommentPragmas: '^ IWYU pragma:'
48 | CompactNamespaces: false
49 | ConstructorInitializerAllOnOneLineOrOnePerLine: true
50 | ConstructorInitializerIndentWidth: 4
51 | ContinuationIndentWidth: 4
52 | Cpp11BracedListStyle: false
53 | DerivePointerAlignment: false
54 | DisableFormat: false
55 | ExperimentalAutoDetectBinPacking: false
56 | FixNamespaceComments: true
57 | ForEachMacros:
58 | - foreach
59 | - Q_FOREACH
60 | - BOOST_FOREACH
61 | IncludeBlocks: Regroup
62 | IncludeCategories:
63 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
64 | Priority: 2
65 | - Regex: '^(<|"(gtest|gmock|isl|json)/)'
66 | Priority: 3
67 | - Regex: '.*'
68 | Priority: 1
69 | #IncludeIsMainRegex: '(Test)?$'
70 | IndentCaseLabels: false
71 | IndentPPDirectives: BeforeHash
72 | IndentWidth: 4
73 | IndentWrappedFunctionNames: true
74 | JavaScriptQuotes: Leave
75 | JavaScriptWrapImports: true
76 | KeepEmptyLinesAtTheStartOfBlocks: false
77 | #MacroBlockBegin: ''
78 | #MacroBlockEnd: ''
79 | MaxEmptyLinesToKeep: 1
80 | NamespaceIndentation: None
81 | PenaltyBreakAssignment: 4
82 | PenaltyBreakBeforeFirstCallParameter: 19
83 | PenaltyBreakComment: 300
84 | PenaltyBreakFirstLessLess: 120
85 | PenaltyBreakString: 1000
86 | PenaltyBreakTemplateDeclaration: 10
87 | PenaltyExcessCharacter: 1000000
88 | PenaltyReturnTypeOnItsOwnLine: 60
89 | PointerAlignment: Left
90 | ReflowComments: false
91 | SortIncludes: true
92 | SortUsingDeclarations: true
93 | SpaceAfterCStyleCast: false
94 | SpaceAfterTemplateKeyword: true
95 | SpaceBeforeAssignmentOperators: true
96 | SpaceBeforeCpp11BracedList: false
97 | SpaceBeforeCtorInitializerColon: true
98 | SpaceBeforeInheritanceColon: true
99 | SpaceBeforeParens: ControlStatements
100 | SpaceBeforeRangeBasedForLoopColon: true
101 | SpaceInEmptyParentheses: false
102 | SpacesBeforeTrailingComments: 1
103 | SpacesInAngles: false
104 | SpacesInContainerLiterals: true
105 | SpacesInCStyleCastParentheses: false
106 | SpacesInParentheses: false
107 | SpacesInSquareBrackets: false
108 | Standard: c++17
109 | StatementMacros:
110 | - Q_UNUSED
111 | - QT_REQUIRE_VERSION
112 | TabWidth: 4
113 | UseTab: Never
114 | ...
115 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 | *.obj
6 |
7 | # Precompiled Headers
8 | *.gch
9 | *.pch
10 |
11 | # Compiled Dynamic libraries
12 | *.so
13 | *.dylib
14 | *.dll
15 |
16 | # Fortran module files
17 | *.mod
18 |
19 | # Compiled Static libraries
20 | *.lai
21 | *.la
22 | *.a
23 | *.lib
24 |
25 | # Executables
26 | *.exe
27 | *.out
28 | *.app
29 |
30 | build
31 | bin
32 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "3rdparty/clipper"]
2 | path = 3rdparty/clipper
3 | url = https://github.com/skyrpex/clipper.git
4 | [submodule "3rdparty/tinyxml2"]
5 | path = 3rdparty/tinyxml2
6 | url = https://github.com/leethomason/tinyxml2.git
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: cpp
2 | dist: trusty
3 |
4 | os:
5 | - linux
6 | - osx
7 |
8 | compiler:
9 | - gcc
10 | - clang
11 |
12 | before_script:
13 | - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install cmake; fi
14 | - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install libboost-all-dev; fi
15 | - mkdir build
16 | - cd build
17 | - cmake ..
18 |
19 | script:
20 | - make
21 | - cd ../bin
22 | - ./levels ../data/planar_graph_fig1.xml ../data/building_blocks_fig1.xml ../data/config.txt 10
23 |
--------------------------------------------------------------------------------
/3rdparty/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ADD_LIBRARY(polyclipping STATIC clipper/cpp/clipper.cpp clipper/cpp/clipper.hpp)
2 | ADD_LIBRARY(tinyxml2 STATIC tinyxml2/tinyxml2.cpp tinyxml2/tinyxml2.h)
3 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12)
2 | PROJECT(LevelSyn)
3 |
4 | include(CheckCXXCompilerFlag)
5 | CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
6 | if(COMPILER_SUPPORTS_CXX11)
7 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
8 | else()
9 | message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
10 | endif()
11 |
12 | ADD_SUBDIRECTORY(3rdparty)
13 | ADD_SUBDIRECTORY(src)
14 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2016, the LevelSyn authors
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | LevelSyn
2 | ========
3 |
4 | [](https://app.travis-ci.com/chongyangma/LevelSyn) [](https://ci.appveyor.com/project/chongyangma/levelsyn)
5 |
6 | This repository contains the source code and example data of the following publication:
7 |
8 | > Game Level Layout from Design Specification
9 | >
10 | > [Chongyang Ma](http://chongyangma.com/), [Nicholas Vining](http://www.cs.ubc.ca/~nvining/), [Sylvain Lefebvre](https://www.antexel.com/sylefeb-research/), [Alla Sheffer](http://www.cs.ubc.ca/~sheffa/)
11 | >
12 | > In _Computer Graphics Forum (Proceedings of Eurographics 2014)_
13 | >
14 | > [Project page](http://chongyangma.com/publications/gl/index.html),
15 | > [Paper](http://chongyangma.com/publications/gl/2014_gl_preprint.pdf),
16 | > [Slides](http://chongyangma.com/publications/gl/2014_gl_slides.pdf),
17 | > [BibTex](http://chongyangma.com/publications/gl/2014_gl_bib.txt)
18 |
19 | Requirements
20 | ------------
21 |
22 | The code is cross-platform and has been tested under Windows (MSVC), Linux and Mac OS X. Compiling from scratch requires the installation of [CMake](https://cmake.org/) and [Boost C++ Libraries](http://www.boost.org/). Additional third-party dependencies (included in this repo as submodules) are:
23 | * [Clipper 6.4.2](https://github.com/skyrpex/clipper) for polygon intersection computation
24 | * [TinyXML-2](https://github.com/leethomason/tinyxml2) for loading/saving xml files
25 |
26 | Usage
27 | -----
28 |
29 | Launching the compiled application from command line without any argument will print the usage information (MSVC version):
30 |
31 | ```bash
32 | levels.exe graph.xml templates.xml config.txt [target_solution_number]
33 | ```
34 |
35 | Contact information
36 | -------------------
37 |
38 | Questions? Bug reports? Please send email to Chongyang Ma chongyangm@gmail.com .
39 |
--------------------------------------------------------------------------------
/data/building_blocks_fig1.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
415 |
--------------------------------------------------------------------------------
/data/building_blocks_fig1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/data/building_blocks_fig11.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/data/building_blocks_fig6a.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
219 |
--------------------------------------------------------------------------------
/data/building_blocks_fig6a.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/data/building_blocks_fig6b.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
307 |
--------------------------------------------------------------------------------
/data/building_blocks_fig6b.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/data/building_blocks_fig6c.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
30 |
--------------------------------------------------------------------------------
/data/building_blocks_fig6c.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/data/building_blocks_fig6d.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
--------------------------------------------------------------------------------
/data/building_blocks_fig6d.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/data/config.txt:
--------------------------------------------------------------------------------
1 | FLAG_RANDOMNESS 0
2 | FLAG_ENABLE_TYPE_CHANGE 1
3 | FLAG_ENRICH_TEMPLATES 1
4 | FLAG_EQUAL_PICK_PROBABILITY 1
5 | FLAG_DISCRETE_CONNECTIVITY_FUNCTION 0
6 | FLAG_RANDOM_PICK 0
7 | FLAG_NON_OVERLAP_CONTACT 1
8 | FLAG_SMALL_FACE_FIRST 1
9 | FLAG_USE_ILS 0
10 | FLAG_RANDOM_WALK 0
11 | NUMBER_OF_SOLUTIONS_TO_TRACK 15
12 | SYNTHESIS_METHOD 0
13 | SA_NUM_OF_CYCLES 50
14 | SA_NUM_OF_TRIALS 500
15 | SA_PROB_0 0.010000
16 | SA_PROB_1 0.200000
17 | DELTA_E_SCALING 35.000000
18 | SIGMA_COLLIDE 5.000000
19 | SIGMA_CONTACT 0.000000
20 | SIGMA_CONNECTIVITY 5.000000
21 | GRAPH_SCALING 1.500000
22 | ROOM_SCALING 0.970000
23 | STATE_DIFFERENCE_THRESHOLD 0.010000
24 | ROOM_CONTACT_THRESHOLD 0.100000
25 | OUTPUT_PREFIX level_syn_output01\
26 |
--------------------------------------------------------------------------------
/data/planar_graph_fig1.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
59 |
--------------------------------------------------------------------------------
/data/planar_graph_fig1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/data/planar_graph_fig10_floor1.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
270 |
--------------------------------------------------------------------------------
/data/planar_graph_fig10_floor1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/data/planar_graph_fig10_floor2.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
319 |
--------------------------------------------------------------------------------
/data/planar_graph_fig10_floor2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/data/planar_graph_fig10_floor3.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
348 |
--------------------------------------------------------------------------------
/data/planar_graph_fig10_floor3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/data/planar_graph_fig11.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
348 |
--------------------------------------------------------------------------------
/data/planar_graph_fig11.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/data/planar_graph_fig7_bottom.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
59 |
--------------------------------------------------------------------------------
/data/planar_graph_fig7_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/data/planar_graph_fig7_top.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
34 |
--------------------------------------------------------------------------------
/data/planar_graph_fig7_top.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/data/planar_graph_fig8.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
129 |
--------------------------------------------------------------------------------
/data/planar_graph_fig8.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/data/planar_graph_fig9.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
49 |
--------------------------------------------------------------------------------
/data/planar_graph_fig9.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12)
2 | PROJECT(LevenSyn)
3 |
4 | IF(MSVC)
5 | # set( BOOST_ROOT "C:/Program Files/boost/boost_1_54_0")
6 | # set( BOOST_LIBRARYDIR "C:/Program Files/boost/boost_1_54_0/lib64-msvc-10.0" )
7 | ENDIF()
8 |
9 | SET(Boost_USE_STATIC_LIBS TRUE)
10 | FIND_PACKAGE(Boost COMPONENTS thread REQUIRED)
11 | LINK_DIRECTORIES (${Boost_LIBRARY_DIRS})
12 | INCLUDE_DIRECTORIES (${Boost_INCLUDE_DIRS})
13 |
14 | IF(APPLE)
15 | FIND_LIBRARY(coreFoundation CoreFoundation)
16 | ENDIF()
17 |
18 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY $<1:${CMAKE_SOURCE_DIR}/bin>)
19 |
20 | FILE(GLOB LEVEL_SYN_SOURCES "*.cpp")
21 | FILE(GLOB LEVEL_SYN_HEADERS "*.h")
22 |
23 | INCLUDE_DIRECTORIES(../3rdparty/clipper/cpp)
24 | INCLUDE_DIRECTORIES(../3rdparty/tinyxml2)
25 |
26 | ADD_EXECUTABLE(levels ${LEVEL_SYN_SOURCES} ${LEVEL_SYN_HEADERS})
27 | TARGET_LINK_LIBRARIES(levels tinyxml2 polyclipping ${Boost_LIBRARIES} ${Boost_THREAD_LIBRARY})
28 |
29 | if(APPLE)
30 | TARGET_LINK_LIBRARIES(levels ${coreFoundation})
31 | endif()
32 |
--------------------------------------------------------------------------------
/src/ConfigSpace.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) www.chongyangma.com
2 | //
3 | // author: Chongyang Ma - 2013-07-15
4 | // email: chongyangm@gmail.com
5 | // info: class declaration of a configuration space
6 | // --------------------------------------------------------------
7 |
8 | #ifndef CONFIGSPACE_H
9 | #define CONFIGSPACE_H
10 |
11 | #include "LevelMath.h"
12 | #include "Room.h"
13 | #include "clipperWrapper.h"
14 |
15 | using namespace level_math;
16 |
17 | class CConfigLine : public CLineBase
18 | {
19 | public:
20 | CConfigLine(v2f pos1, v2f pos2) :
21 | CLineBase(pos1, pos2) {}
22 |
23 | CConfigLine(v2f pos) :
24 | CLineBase(pos) {}
25 |
26 | v2f RandomlySampleConfigLine();
27 |
28 | v2f RandomlySampleConfigLineDiscrete();
29 |
30 | float GetConfigLineLength() const;
31 |
32 | float GetConfigLineSqLength() const;
33 |
34 | void PrintConfigLine();
35 |
36 | void TranslateConfigLine(v2f trans);
37 | };
38 |
39 | class CConfigSpace
40 | {
41 | public:
42 | CConfigSpace() {}
43 |
44 | // The configuration space to put room2 around room1...
45 | CConfigSpace(const CRoom& room1, const CRoom& room2);
46 |
47 | CConfigSpace(const std::vector& vecConfigLines);
48 |
49 | void AddConfigLine(const CConfigLine& line) { m_vecConfigLine.push_back(line); }
50 |
51 | v2f RandomlySampleConfigSpace();
52 |
53 | v2f RandomlySampleConfigSpaceContinuous();
54 |
55 | v2f RandomlySampleConfigSpaceDiscrete();
56 |
57 | std::vector SmartlySampleConfigSpace();
58 |
59 | int GetNumOfLines() { return int(m_vecConfigLine.size()); }
60 |
61 | bool IsEmpty() { return m_vecConfigLine.empty(); }
62 |
63 | void SetConfigLines(const std::vector& vecConfigLine) { m_vecConfigLine = vecConfigLine; }
64 |
65 | std::vector& GetConfigLines() { return m_vecConfigLine; }
66 |
67 | CConfigLine& GetConfigLine(int idx) { return m_vecConfigLine[idx]; }
68 |
69 | static CConfigSpace FindIntersection(CConfigSpace& configSpace1, CConfigSpace& configSpace2);
70 |
71 | static CConfigSpace FindUnion(CConfigSpace& configSpace, CConfigLine& configLine);
72 |
73 | void SelfMerge();
74 |
75 | float GetConfigSpaceSize();
76 |
77 | void PrintConfigSpace();
78 |
79 | void TranslateConfigSpace(v2f trans);
80 |
81 | static bool CompareConfigLineLength(const CConfigLine& line1, const CConfigLine& line2);
82 |
83 | static void PrecomputeTable(const std::vector& vecRooms);
84 |
85 | static std::vector> m_precomputedTable;
86 |
87 | static bool m_flagPrecomputed;
88 |
89 | private:
90 | std::vector m_vecConfigLine;
91 | };
92 |
93 | #endif // CONFIGSPACE_H
94 |
--------------------------------------------------------------------------------
/src/GraphChain.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) www.chongyangma.com
2 | //
3 | // author: Chongyang Ma - 2013-08-17
4 | // email: chongyangm@gmail.com
5 | // info: class declaration of a graph chain
6 | // --------------------------------------------------------------
7 |
8 | #ifndef GRAPHCHAIN_H
9 | #define GRAPHCHAIN_H
10 |
11 | #include
12 | #include
13 |
14 | class CGraphChain
15 | {
16 | public:
17 | CGraphChain() {}
18 |
19 | CGraphChain(std::vector& indices, bool flag)
20 | {
21 | m_indices = indices;
22 | m_flagCyclic = flag;
23 | }
24 |
25 | std::vector& GetIndices() { return m_indices; }
26 |
27 | void AddIndex(int idx) { m_indices.push_back(idx); }
28 |
29 | void ClearIndices() { m_indices.clear(); }
30 |
31 | int GetChainSize() { return int(m_indices.size()); }
32 |
33 | bool IsEmpty() { return m_indices.empty(); }
34 |
35 | bool GetFlagCyclic() { return m_flagCyclic; }
36 |
37 | void SetFlagCyclic(bool flag) { m_flagCyclic = flag; }
38 |
39 | private:
40 | std::vector m_indices; // graph nodes that form a chain
41 | bool m_flagCyclic;
42 | };
43 |
44 | #endif // GRAPHCHAIN_H
45 |
--------------------------------------------------------------------------------
/src/GraphEdge.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) www.chongyangma.com
2 | //
3 | // author: Chongyang Ma - 2013-06-06
4 | // email: chongyangm@gmail.com
5 | // info: class declaration of a graph edge
6 | // --------------------------------------------------------------
7 |
8 | #ifndef GRAPHEDGE_H
9 | #define GRAPHEDGE_H
10 |
11 | #include
12 | #include
13 |
14 | class CGraphEdge
15 | {
16 | public:
17 | CGraphEdge(int idx0, int idx1)
18 | {
19 | m_indices.resize(2);
20 | m_indices[0] = idx0;
21 | m_indices[1] = idx1;
22 | }
23 |
24 | std::vector& GetIndices() { return m_indices; }
25 |
26 | int GetIdx0() const { return m_indices[0]; }
27 | int GetIdx1() const { return m_indices[1]; }
28 |
29 | void SetIdx0(int idx0) { m_indices[0] = idx0; }
30 | void SetIdx1(int idx1) { m_indices[1] = idx1; }
31 |
32 | private:
33 | std::vector m_indices;
34 | };
35 |
36 | #endif // GRAPHEDGE_H
37 |
--------------------------------------------------------------------------------
/src/GraphFace.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) www.chongyangma.com
2 | //
3 | // author: Chongyang Ma - 2013-06-06
4 | // email: chongyangm@gmail.com
5 | // info: class declaration of a graph face
6 | // --------------------------------------------------------------
7 |
8 | #ifndef GRAPHFACE_H
9 | #define GRAPHFACE_H
10 |
11 | #include
12 | #include
13 |
14 | class CGraphFace
15 | {
16 | public:
17 | CGraphFace() {}
18 |
19 | CGraphFace(std::vector& indices)
20 | {
21 | m_indices = indices;
22 | }
23 |
24 | std::vector& GetIndices() { return m_indices; }
25 |
26 | void AddIndex(int idx) { m_indices.push_back(idx); }
27 |
28 | void ClearIndices() { m_indices.clear(); }
29 |
30 | int GetFaceSize() { return int(m_indices.size()); }
31 |
32 | bool IsEmpty() { return m_indices.empty(); }
33 |
34 | private:
35 | std::vector m_indices; // graph nodes that form a face
36 | };
37 |
38 | #endif // GRAPHFACE_H
39 |
--------------------------------------------------------------------------------
/src/GraphNode.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) www.chongyangma.com
2 | //
3 | // author: Chongyang Ma - 2013-06-06
4 | // email: chongyangm@gmail.com
5 | // info: class declaration of a graph node
6 | // --------------------------------------------------------------
7 |
8 | #ifndef GRAPHNODE_H
9 | #define GRAPHNODE_H
10 |
11 | #include "vec.h"
12 |
13 | #include
14 | #include
15 | #include
16 |
17 | class CGraphNode
18 | {
19 | public:
20 | CGraphNode()
21 | {
22 | RandomlyInitPos();
23 | m_flagVisited = false;
24 | m_flagFixed = false;
25 | m_type = 0;
26 | m_boundaryType = 0;
27 | }
28 |
29 | CGraphNode(std::string name)
30 | {
31 | m_name = name;
32 | RandomlyInitPos();
33 | }
34 |
35 | std::string GetName() { return m_name; }
36 | void SetName(std::string name) { m_name = name; }
37 |
38 | void RandomlyInitPos()
39 | {
40 | for (int i = 0; i < 2; i++)
41 | {
42 | float p = rand() / float(RAND_MAX);
43 | p -= 0.5f;
44 | p *= 1.5f;
45 | m_pos[i] = p;
46 | }
47 | }
48 |
49 | v2f GetPos() { return m_pos; }
50 | void SetPos(v2f pos) { m_pos = pos; }
51 | void SetPos(float px, float py)
52 | {
53 | m_pos[0] = px;
54 | m_pos[1] = py;
55 | }
56 |
57 | void ClearNeighbors() { m_neighbors.clear(); }
58 | void AddNeighbor(int idx) { m_neighbors.push_back(idx); }
59 | std::vector& GetNeighbors() { return m_neighbors; }
60 | bool IsNeighbor(int idx)
61 | {
62 | for (int i = 0; i < int(m_neighbors.size()); i++)
63 | {
64 | if (m_neighbors[i] == idx)
65 | {
66 | return true;
67 | }
68 | }
69 | return false;
70 | }
71 |
72 | bool GetFlagVisited() { return m_flagVisited; }
73 | void SetFlagVisited(bool flagVisited) { m_flagVisited = flagVisited; }
74 |
75 | bool GetFlagFixed() const { return m_flagFixed; }
76 | void SetFlagFixed(bool flagFixed) { m_flagFixed = flagFixed; }
77 |
78 | int GetType() { return m_type; }
79 | void SetType(int type) { m_type = type; }
80 |
81 | int GetBoundaryType() const { return m_boundaryType; }
82 | void SetBoundaryType(int type) { m_boundaryType = type; }
83 |
84 | private:
85 | std::string m_name;
86 | v2f m_pos;
87 | std::vector m_neighbors;
88 | bool m_flagVisited;
89 | bool m_flagFixed;
90 | int m_type; // index of the room template
91 | int m_boundaryType;
92 | };
93 |
94 | #endif // GRAPHNODE_H
95 |
--------------------------------------------------------------------------------
/src/LevelConfig.cpp:
--------------------------------------------------------------------------------
1 | #include "LevelConfig.h"
2 |
3 | #ifndef WIN32
4 | #define MAX_PATH 260
5 | #endif
6 |
7 | bool CLevelConfig::m_flagRandomness = false;
8 | bool CLevelConfig::m_flagEnableTypeChange = true;
9 | bool CLevelConfig::m_flagEnrichTemplates = false;
10 | bool CLevelConfig::m_flagEqualPickProb = true;
11 | bool CLevelConfig::m_flagDiscreteConnectFunc = true;
12 | bool CLevelConfig::m_flagRandomPick = true;
13 | bool CLevelConfig::m_flagNonOverlapContact = false;
14 | bool CLevelConfig::m_flagSmallFaceFirst = false;
15 | bool CLevelConfig::m_flagUseILS = false;
16 | bool CLevelConfig::m_flagRandomWalk = false;
17 | int CLevelConfig::m_numOfSolutionsToTrack = 10;
18 | int CLevelConfig::m_synMethod = 0;
19 | int CLevelConfig::m_saNumOfCycles = 1000;
20 | int CLevelConfig::m_saNumOfTrials = 1000;
21 | int CLevelConfig::m_targetNumOfSolutions = 100;
22 | float CLevelConfig::m_saProb0 = 0.001f;
23 | float CLevelConfig::m_saProb1 = 0.7f;
24 | float CLevelConfig::m_deltaEscaling = 1.0f;
25 | float CLevelConfig::m_sigmaCollide = 50.f;
26 | float CLevelConfig::m_sigmaContact = 1.f;
27 | float CLevelConfig::m_sigmaConnectivity = 2.f;
28 | float CLevelConfig::m_graphScaling = 1.f;
29 | float CLevelConfig::m_roomScaling = 0.9f;
30 | float CLevelConfig::m_stateDiffThresh = 0.f;
31 | float CLevelConfig::m_roomContactThresh = 1e-6f;
32 | std::string CLevelConfig::m_outputPrefix;
33 |
34 | CLevelConfig::CLevelConfig()
35 | {
36 | }
37 |
38 | bool CLevelConfig::LoadFromSynConfig(std::string fileName, bool resetFlag /* = true */)
39 | {
40 | std::ifstream fin(fileName.c_str());
41 | if (fin.fail() == true)
42 | {
43 | std::cout << "Failed to load config parameters from config file " << fileName << "!\n";
44 | return false;
45 | }
46 | std::string param;
47 | while (fin >> param)
48 | {
49 | if (param == std::string("FLAG_RANDOMNESS"))
50 | {
51 | fin >> m_flagRandomness;
52 | }
53 | else if (param == std::string("FLAG_ENABLE_TYPE_CHANGE"))
54 | {
55 | fin >> m_flagEnableTypeChange;
56 | }
57 | else if (param == std::string("FLAG_ENRICH_TEMPLATES"))
58 | {
59 | fin >> m_flagEnrichTemplates;
60 | }
61 | else if (param == std::string("FLAG_EQUAL_PICK_PROBABILITY"))
62 | {
63 | fin >> m_flagEqualPickProb;
64 | }
65 | else if (param == std::string("FLAG_DISCRETE_CONNECTIVITY_FUNCTION"))
66 | {
67 | fin >> m_flagDiscreteConnectFunc;
68 | }
69 | else if (param == std::string("FLAG_RANDOM_PICK"))
70 | {
71 | fin >> m_flagRandomPick;
72 | }
73 | else if (param == std::string("FLAG_NON_OVERLAP_CONTACT"))
74 | {
75 | fin >> m_flagNonOverlapContact;
76 | }
77 | else if (param == std::string("FLAG_SMALL_FACE_FIRST"))
78 | {
79 | fin >> m_flagSmallFaceFirst;
80 | }
81 | else if (param == std::string("FLAG_USE_ILS"))
82 | {
83 | fin >> m_flagUseILS;
84 | }
85 | else if (param == std::string("FLAG_RANDOM_WALK"))
86 | {
87 | fin >> m_flagRandomWalk;
88 | }
89 | else if (param == std::string("NUMBER_OF_SOLUTIONS_TO_TRACK"))
90 | {
91 | fin >> m_numOfSolutionsToTrack;
92 | }
93 | else if (param == std::string("SYNTHESIS_METHOD"))
94 | {
95 | fin >> m_synMethod;
96 | }
97 | else if (param == std::string("SA_NUM_OF_CYCLES"))
98 | {
99 | fin >> m_saNumOfCycles;
100 | }
101 | else if (param == std::string("SA_NUM_OF_TRIALS"))
102 | {
103 | fin >> m_saNumOfTrials;
104 | }
105 | else if (param == std::string("SA_PROB_0"))
106 | {
107 | fin >> m_saProb0;
108 | }
109 | else if (param == std::string("SA_PROB_1"))
110 | {
111 | fin >> m_saProb1;
112 | }
113 | else if (param == std::string("DELTA_E_SCALING"))
114 | {
115 | fin >> m_deltaEscaling;
116 | }
117 | else if (param == std::string("SIGMA_COLLIDE"))
118 | {
119 | fin >> m_sigmaCollide;
120 | }
121 | else if (param == std::string("SIGMA_CONTACT"))
122 | {
123 | fin >> m_sigmaContact;
124 | }
125 | else if (param == std::string("SIGMA_CONNECTIVITY"))
126 | {
127 | fin >> m_sigmaConnectivity;
128 | }
129 | else if (param == std::string("GRAPH_SCALING"))
130 | {
131 | fin >> m_graphScaling;
132 | }
133 | else if (param == std::string("ROOM_SCALING"))
134 | {
135 | fin >> m_roomScaling;
136 | }
137 | else if (param == std::string("STATE_DIFFERENCE_THRESHOLD"))
138 | {
139 | fin >> m_stateDiffThresh;
140 | }
141 | else if (param == std::string("ROOM_CONTACT_THRESHOLD"))
142 | {
143 | fin >> m_roomContactThresh;
144 | }
145 | else if (param == std::string("OUTPUT_PREFIX"))
146 | {
147 | fin >> m_outputPrefix;
148 | }
149 | }
150 | if (resetFlag == false)
151 | {
152 | return true;
153 | }
154 | ResetConfig();
155 |
156 | return true;
157 | }
158 |
159 | std::string CLevelConfig::AddOutputPrefix(std::string str)
160 | {
161 | if (m_outputPrefix.empty() == true)
162 | {
163 | return str;
164 | }
165 | std::ostringstream oss;
166 | oss << m_outputPrefix << str;
167 | std::string strNew = oss.str();
168 | return strNew;
169 | }
170 |
171 | void CLevelConfig::ResetConfig()
172 | {
173 | if (m_flagRandomness == true)
174 | {
175 | srand((unsigned int)time(0));
176 | }
177 | if (m_outputPrefix.empty() == false)
178 | {
179 | UpdateOutputPrefix();
180 | }
181 | DumpToSynConfig();
182 | }
183 |
184 | bool CLevelConfig::DumpToSynConfig()
185 | {
186 | std::ostringstream oss;
187 | oss << m_outputPrefix << "SynConfig.txt";
188 | std::string fileName = oss.str();
189 | FILE* file;
190 | file = fopen(fileName.c_str(), "w");
191 | if (!file)
192 | {
193 | std::cout << "Failed to dump parameters into config file " << fileName << "!\n";
194 | return false;
195 | }
196 | DumpTimeAndDate(file);
197 | DumpParameters(file);
198 | fclose(file);
199 |
200 | return true;
201 | }
202 |
203 | void CLevelConfig::DumpTimeAndDate(FILE* file)
204 | {
205 | time_t myTime = time(NULL);
206 | tm* ptrTime = localtime(&myTime);
207 | fprintf(file, "%02d:%02d:%02d ", ptrTime->tm_hour, ptrTime->tm_min, ptrTime->tm_sec);
208 | fprintf(file, "%02d/%02d/%04d\n\n", ptrTime->tm_mon + 1, ptrTime->tm_mday, ptrTime->tm_year + 1900);
209 | }
210 |
211 | void CLevelConfig::DumpTimeAndDate(std::ofstream& fout)
212 | {
213 | time_t myTime = time(NULL);
214 | tm* ptrTime = localtime(&myTime);
215 | char str[1000];
216 | sprintf(str, "%02d:%02d:%02d ", ptrTime->tm_hour, ptrTime->tm_min, ptrTime->tm_sec);
217 | fout << str;
218 | sprintf(str, "%02d/%02d/%04d", ptrTime->tm_mon + 1, ptrTime->tm_mday, ptrTime->tm_year + 1900);
219 | fout << str << std::endl;
220 | }
221 |
222 | void CLevelConfig::DumpParameters(FILE* file)
223 | {
224 | fprintf(file, "%s\t%d\n", "FLAG_RANDOMNESS", m_flagRandomness);
225 | fprintf(file, "%s\t%d\n", "FLAG_ENABLE_TYPE_CHANGE", m_flagEnableTypeChange);
226 | fprintf(file, "%s\t%d\n", "FLAG_ENRICH_TEMPLATES", m_flagEnrichTemplates);
227 | fprintf(file, "%s\t%d\n", "FLAG_EQUAL_PICK_PROBABILITY", m_flagEqualPickProb);
228 | fprintf(file, "%s\t%d\n", "FLAG_DISCRETE_CONNECTIVITY_FUNCTION", m_flagDiscreteConnectFunc);
229 | fprintf(file, "%s\t%d\n", "FLAG_RANDOM_PICK", m_flagRandomPick);
230 | fprintf(file, "%s\t%d\n", "FLAG_NON_OVERLAP_CONTACT", m_flagNonOverlapContact);
231 | fprintf(file, "%s\t%d\n", "FLAG_SMALL_FACE_FIRST", m_flagSmallFaceFirst);
232 | fprintf(file, "%s\t%d\n", "FLAG_USE_ILS", m_flagUseILS);
233 | fprintf(file, "%s\t%d\n", "FLAG_RANDOM_WALK", m_flagRandomWalk);
234 | fprintf(file, "%s\t%d\n", "NUMBER_OF_SOLUTIONS_TO_TRACK", m_numOfSolutionsToTrack);
235 | fprintf(file, "%s\t%d\n", "SYNTHESIS_METHOD", m_synMethod);
236 | fprintf(file, "%s\t%d\n", "SA_NUM_OF_CYCLES", m_saNumOfCycles);
237 | fprintf(file, "%s\t%d\n", "SA_NUM_OF_TRIALS", m_saNumOfTrials);
238 | fprintf(file, "%s\t%f\n", "SA_PROB_0", m_saProb0);
239 | fprintf(file, "%s\t%f\n", "SA_PROB_1", m_saProb1);
240 | fprintf(file, "%s\t%f\n", "DELTA_E_SCALING", m_deltaEscaling);
241 | fprintf(file, "%s\t%f\n", "SIGMA_COLLIDE", m_sigmaCollide);
242 | fprintf(file, "%s\t%f\n", "SIGMA_CONTACT", m_sigmaContact);
243 | fprintf(file, "%s\t%f\n", "SIGMA_CONNECTIVITY", m_sigmaConnectivity);
244 | fprintf(file, "%s\t%f\n", "GRAPH_SCALING", m_graphScaling);
245 | fprintf(file, "%s\t%f\n", "ROOM_SCALING", m_roomScaling);
246 | fprintf(file, "%s\t%f\n", "STATE_DIFFERENCE_THRESHOLD", m_stateDiffThresh);
247 | fprintf(file, "%s\t%f\n", "ROOM_CONTACT_THRESHOLD", m_roomContactThresh);
248 | DumpStringParam(file, "OUTPUT_PREFIX", m_outputPrefix);
249 | }
250 |
251 | void CLevelConfig::UpdateOutputPrefix()
252 | {
253 | #ifdef WIN32
254 | if (m_outputPrefix[m_outputPrefix.size() - 1] != '\\')
255 | {
256 | m_outputPrefix = m_outputPrefix + std::string("\\");
257 | }
258 | #else
259 | while (m_outputPrefix.empty() == false && isdigit(m_outputPrefix[m_outputPrefix.size() - 1]) == 0)
260 | {
261 | m_outputPrefix = m_outputPrefix.substr(0, m_outputPrefix.size() - 1);
262 | }
263 | if (m_outputPrefix[m_outputPrefix.size() - 1] != '/')
264 | {
265 | m_outputPrefix = m_outputPrefix + std::string("/");
266 | }
267 | #endif
268 | std::ostringstream oss;
269 | #ifdef WIN32
270 | bool flag = CreateDirectoryA(m_outputPrefix.c_str(), NULL);
271 | const int numLength = 2;
272 | while (flag == false && m_outputPrefix.size() >= 2)
273 | {
274 | std::string subStr = m_outputPrefix.substr(m_outputPrefix.length() - numLength - 1, 2);
275 | int num = atoi(subStr.c_str()) + 1;
276 | char numChar[MAX_PATH];
277 | sprintf_s(numChar, "%02d", num);
278 | std::ostringstream oss;
279 | oss << m_outputPrefix.substr(0, m_outputPrefix.length() - numLength - 1) << numChar << "\\";
280 | m_outputPrefix = oss.str();
281 | flag = CreateDirectoryA(m_outputPrefix.c_str(), NULL);
282 | }
283 | #else
284 | std::string outputFolder = m_outputPrefix.substr(0, m_outputPrefix.size() - 1);
285 | int flag = mkdir(outputFolder.c_str(), 0777);
286 | const int numLength = 2;
287 | while (flag == -1 && m_outputPrefix.size() >= 2)
288 | {
289 | std::string subStr = m_outputPrefix.substr(m_outputPrefix.length() - numLength - 1, 2);
290 | int num = atoi(subStr.c_str()) + 1;
291 | char numChar[MAX_PATH];
292 | sprintf(numChar, "%02d", num);
293 | std::ostringstream oss;
294 | oss << m_outputPrefix.substr(0, m_outputPrefix.length() - numLength - 1) << numChar << "/";
295 | m_outputPrefix = oss.str();
296 | outputFolder = m_outputPrefix.substr(0, m_outputPrefix.size() - 1);
297 | flag = mkdir(outputFolder.c_str(), 0777);
298 | }
299 | #endif
300 | std::cout << "Generating results into the directory: " << m_outputPrefix.c_str() << "...\n";
301 | }
302 |
303 | void CLevelConfig::DumpStringParam(FILE* file, const char* param, const std::string& str)
304 | {
305 | if (str.empty() != true)
306 | {
307 | fprintf(file, "%s\t%s\n", param, str.c_str());
308 | }
309 | else
310 | {
311 | //fprintf(file, "%s\t%s\n", param, "NULL");
312 | }
313 | }
314 |
--------------------------------------------------------------------------------
/src/LevelConfig.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) www.chongyangma.com
2 | //
3 | // author: Chongyang Ma - 2013-06-13
4 | // email: chongyangm@gmail.com
5 | // info: class declaration of config file for level synthesis
6 | // --------------------------------------------------------------
7 |
8 | #ifndef LEVELCONFIG_H
9 | #define LEVELCONFIG_H
10 |
11 | #ifdef WIN32
12 | #include
13 | #else
14 | #include
15 | #endif
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | class CLevelConfig
26 | {
27 | public:
28 | CLevelConfig();
29 |
30 | bool LoadFromSynConfig(std::string fileName, bool resetFlag = true);
31 |
32 | static std::string AddOutputPrefix(std::string str);
33 |
34 | static bool m_flagRandomness;
35 | static bool m_flagEnableTypeChange;
36 | static bool m_flagEnrichTemplates;
37 | static bool m_flagEqualPickProb;
38 | static bool m_flagDiscreteConnectFunc;
39 | static bool m_flagRandomPick;
40 | static bool m_flagNonOverlapContact;
41 | static bool m_flagSmallFaceFirst;
42 | static bool m_flagUseILS;
43 | static bool m_flagRandomWalk;
44 | static int m_numOfSolutionsToTrack;
45 | static int m_synMethod;
46 | static int m_targetNumOfSolutions;
47 | // For simulated annealing...
48 | static int m_saNumOfCycles;
49 | static int m_saNumOfTrials;
50 | static float m_saProb0;
51 | static float m_saProb1;
52 | static float m_deltaEscaling;
53 | // For layout energy calculation...
54 | static float m_sigmaCollide;
55 | static float m_sigmaContact;
56 | static float m_sigmaConnectivity;
57 | static float m_graphScaling; // For initialization
58 | static float m_roomScaling; // For rendering only
59 | static float m_stateDiffThresh;
60 | static float m_roomContactThresh;
61 | static std::string m_outputPrefix;
62 |
63 | static void DumpTimeAndDate(FILE* file);
64 |
65 | static void DumpTimeAndDate(std::ofstream& fout);
66 |
67 | protected:
68 | virtual void ResetConfig();
69 |
70 | bool DumpToSynConfig();
71 |
72 | virtual void DumpParameters(FILE* file);
73 |
74 | virtual void UpdateOutputPrefix();
75 |
76 | void DumpStringParam(FILE* file, const char* param, const std::string& str);
77 | };
78 |
79 | #endif //LEVELCONFIG_H
80 |
--------------------------------------------------------------------------------
/src/LevelMath.cpp:
--------------------------------------------------------------------------------
1 | #include "LevelMath.h"
2 |
3 | namespace level_math
4 | {
5 | float PointToSegmentSqDistance(const v2f& pt, const CLineBase& line)
6 | {
7 | if (line.GetSqLength() < g_numericalTolerance * g_numericalTolerance)
8 | {
9 | return mag2(pt - line.GetPos1());
10 | }
11 | float d1 = mag2(pt - line.GetPos1());
12 | float d2 = mag2(pt - line.GetPos2());
13 | v2f pe = line.GetPos2() - line.GetPos1();
14 | v2f pd = pt - line.GetPos1();
15 | float dp = dot(pe, pd);
16 | float r = dp / mag2(pe);
17 | float d;
18 | if (r >= 1.f)
19 | {
20 | d = d2;
21 | }
22 | else if (r <= 0.f)
23 | {
24 | d = d1;
25 | }
26 | else
27 | {
28 | v2f peNew = v2f(pe[1], -pe[0]);
29 | d = std::abs(dot(pd, peNew) / mag(peNew));
30 | d = d * d;
31 | }
32 | return d;
33 | }
34 |
35 | float PointToLineSqDistance(const v2f& pt, const CLineBase& line)
36 | {
37 | return PointToLineSqDistance(pt, line.GetPos2(), line.GetPos1());
38 | }
39 |
40 | float PointToLineSqDistance(const v2f& pt, const v2f& p1, const v2f& p2)
41 | {
42 | v2f pe = p2 - p1;
43 | v2f peNorm = normalize(pe);
44 | v2f pr = pt - p1;
45 | v3f peNew = v3f(peNorm[0], peNorm[1], 0.f);
46 | v3f prNew = v3f(pr[0], pr[1], 0.f);
47 | v3f cp = cross(peNew, prNew);
48 | float d = mag2(cp);
49 | return d;
50 | }
51 |
52 | float RoomPerimeter(const CRoom& room1)
53 | {
54 | float contactArea = 0.f;
55 | for (int i = 0; i < room1.GetNumOfEdges(); i++)
56 | {
57 | CRoomEdge edge1 = room1.GetEdge(i);
58 | contactArea += edge1.GetLength();
59 | }
60 |
61 | return contactArea;
62 | }
63 |
64 | float RoomContact(const CRoom& room1, const CRoom& room2)
65 | {
66 | float contactArea = 0.f;
67 | for (int i = 0; i < room1.GetNumOfEdges(); i++)
68 | {
69 | CRoomEdge edge1 = room1.GetEdge(i);
70 | for (int j = 0; j < room2.GetNumOfEdges(); j++)
71 | {
72 | CRoomEdge edge2 = room2.GetEdge(j);
73 | if (edge1.GetDoorFlag() == false || edge2.GetDoorFlag() == false)
74 | {
75 | continue;
76 | }
77 | float contactAreaTmp = EdgeContact(edge1, edge2);
78 | contactArea += contactAreaTmp;
79 | }
80 | }
81 |
82 | return contactArea;
83 | }
84 |
85 | float RoomContact(const CRoom& room1, const CRoom& room2, int& edgeIdx1, int& edgeIdx2)
86 | {
87 | float contactAreaMax = 0.f;
88 | for (int i = 0; i < room1.GetNumOfEdges(); i++)
89 | {
90 | CRoomEdge edge1 = room1.GetEdge(i);
91 | for (int j = 0; j < room2.GetNumOfEdges(); j++)
92 | {
93 | CRoomEdge edge2 = room2.GetEdge(j);
94 | if (edge1.GetDoorFlag() == false || edge2.GetDoorFlag() == false)
95 | {
96 | continue;
97 | }
98 | float contactAreaTmp = EdgeContact(edge1, edge2);
99 | if (contactAreaTmp > contactAreaMax)
100 | {
101 | contactAreaMax = contactAreaTmp;
102 | edgeIdx1 = i;
103 | edgeIdx2 = j;
104 | }
105 | }
106 | }
107 |
108 | return contactAreaMax;
109 | }
110 |
111 | float EdgeContact(const CLineBase& line1, const CLineBase& line2)
112 | {
113 | const float numericalTolerance = g_numericalTolerance * 100.f;
114 | const float numericalToleranceSq = numericalTolerance * numericalTolerance;
115 | v2f pr1 = line1.GetPos2() - line1.GetPos1();
116 | v2f pr2 = line2.GetPos2() - line2.GetPos1();
117 | v3f pe1 = v3f(pr1[0], pr1[1], 0.f);
118 | v3f pe2 = v3f(pr2[0], pr2[1], 0.f);
119 | v3f cp = cross(pe1, pe2);
120 | if (mag2(cp) > numericalTolerance)
121 | {
122 | return 0.f;
123 | }
124 | v2f posMin1 = min_union(line1.GetPos1(), line1.GetPos2());
125 | v2f posMax1 = max_union(line1.GetPos1(), line1.GetPos2());
126 | v2f posMin2 = min_union(line2.GetPos1(), line2.GetPos2());
127 | v2f posMax2 = max_union(line2.GetPos1(), line2.GetPos2());
128 | for (int j = 0; j < 2; j++)
129 | {
130 | if (posMax1[j] < posMin2[j] - numericalTolerance || posMin1[j] > posMax2[j] + numericalTolerance)
131 | {
132 | return 0.f;
133 | }
134 | }
135 | float d1 = PointToLineSqDistance(line2.GetPos1(), line1);
136 | float d2 = PointToLineSqDistance(line2.GetPos2(), line1);
137 | if (d1 > numericalToleranceSq || d2 > numericalToleranceSq)
138 | {
139 | return 0.f;
140 | }
141 | // Now the two edges should in the same line anyway...
142 | float len1 = mag(pe1);
143 | float len2 = mag(pe2);
144 | float d11 = mag2(line1.GetPos1() - line2.GetPos1());
145 | float d21 = mag2(line1.GetPos2() - line2.GetPos1());
146 | float d12 = mag2(line1.GetPos1() - line2.GetPos2());
147 | float d22 = mag2(line1.GetPos2() - line2.GetPos2());
148 | float dMax = sqrt(max(max(d11, d21), max(d12, d22)));
149 | dMax = max(dMax, max(len1, len2));
150 | float contactArea = len1 + len2 - dMax;
151 | contactArea = max(contactArea, 0.f);
152 | return contactArea;
153 | }
154 |
155 | float RoomDistance(const CRoom& room1, const CRoom& room2)
156 | {
157 | float d = 1e10;
158 | for (int i = 0; i < room1.GetNumOfVertices(); i++)
159 | {
160 | v2f pt = room1.GetVertex(i);
161 | for (int j = 0; j < room2.GetNumOfEdges(); j++)
162 | {
163 | CRoomEdge edge = room2.GetEdge(j);
164 | float dTmp = PointToSegmentSqDistance(pt, edge);
165 | d = min(d, dTmp);
166 | }
167 | }
168 | d = sqrt(d);
169 | return d;
170 | }
171 |
172 | bool SegmentIntersection(v2f pa, v2f pb, v2f pc, v2f pd, v2f& pi)
173 | {
174 | return SegmentIntersection(pa[0], pa[1], pb[0], pb[1], pc[0], pc[1], pd[0], pd[1], pi[0], pi[1]);
175 | }
176 |
177 | // Based on the example under http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
178 | bool SegmentIntersection(float Ax, float Ay, float Bx, float By, float Cx, float Cy, float Dx, float Dy, float& Ix, float& Iy)
179 | {
180 | float Rx = Bx - Ax;
181 | float Ry = By - Ay;
182 | float Sx = Dx - Cx;
183 | float Sy = Dy - Cy;
184 | float QPx = Cx - Ax;
185 | float QPy = Cy - Ay;
186 | float rs = Rx * Sy - Ry * Sx;
187 | if (rs == 0.f)
188 | {
189 | return false;
190 | }
191 | float t = (QPx * Sy - QPy * Sx) / rs;
192 | float u = (QPx * Ry - QPy * Rx) / rs;
193 | if (t >= 0.f && t <= 1.f && u >= 0.f && u <= 1.f)
194 | {
195 | Ix = Ax + t * Rx;
196 | Iy = Ay + t * Ry;
197 | return true;
198 | }
199 | else
200 | {
201 | return false;
202 | }
203 | }
204 |
205 | bool LineIntersection(v2f pa, v2f pb, v2f pc, v2f pd, v2f& pi)
206 | {
207 | return LineIntersection(pa[0], pa[1], pb[0], pb[1], pc[0], pc[1], pd[0], pd[1], pi[0], pi[1]);
208 | }
209 |
210 | bool LineIntersection(float Ax, float Ay, float Bx, float By, float Cx, float Cy, float Dx, float Dy, float& Ix, float& Iy)
211 | {
212 | float Rx = Bx - Ax;
213 | float Ry = By - Ay;
214 | float Sx = Dx - Cx;
215 | float Sy = Dy - Cy;
216 | float QPx = Cx - Ax;
217 | float QPy = Cy - Ay;
218 | float rs = Rx * Sy - Ry * Sx;
219 | if (rs == 0.f)
220 | {
221 | return false;
222 | }
223 | float t = (QPx * Sy - QPy * Sx) / rs;
224 | Ix = Ax + t * Rx;
225 | Iy = Ay + t * Ry;
226 | return true;
227 | }
228 |
229 | bool ComparePrSmallerFirst(const PrSort& pr1, const PrSort& pr2)
230 | {
231 | return (pr1.m_dp < pr2.m_dp);
232 | }
233 |
234 | void SortVecPr(std::vector& vecPr)
235 | {
236 | if (vecPr.size() < 2)
237 | {
238 | return;
239 | }
240 | v2f pd = vecPr[1] - vecPr[0];
241 | std::vector vecPrSort(vecPr.size());
242 | for (int i = 0; i < int(vecPrSort.size()); i++)
243 | {
244 | vecPrSort[i].m_pr = vecPr[i];
245 | vecPrSort[i].m_dp = dot(pd, vecPr[i] - vecPr[0]);
246 | }
247 | sort(vecPrSort.begin(), vecPrSort.end(), ComparePrSmallerFirst);
248 | for (int i = 0; i < int(vecPrSort.size()); i++)
249 | {
250 | vecPr[i] = vecPrSort[i].m_pr;
251 | }
252 | }
253 |
254 | v3f randomColorFromIndex(int idx)
255 | {
256 | static std::vector clrs;
257 | if (clrs.empty())
258 | {
259 | clrs.resize(256);
260 | for (int c = 0; c < clrs.size(); c++)
261 | {
262 | clrs[c] = v3f(rand(), rand(), rand());
263 | clrs[c] = clrs[c] / max(clrs[c]);
264 | }
265 | }
266 | return (clrs[idx & 255]);
267 | }
268 | } // namespace level_math
269 |
--------------------------------------------------------------------------------
/src/LevelMath.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) www.chongyangma.com
2 | //
3 | // author: Chongyang Ma - 2013-06-15
4 | // email: chongyangm@gmail.com
5 | // info: wrapper for basic math operations
6 | // --------------------------------------------------------------
7 |
8 | #ifndef LEVELMATH_H
9 | #define LEVELMATH_H
10 |
11 | #include "Room.h"
12 |
13 | namespace level_math
14 | {
15 | typedef struct PrSort
16 | {
17 | v2f m_pr;
18 | float m_dp; // dot product
19 | } PrSort;
20 |
21 | const float g_numericalTolerance = 1e-4f; //1e-6;
22 |
23 | const float g_numericalToleranceSq = g_numericalTolerance * g_numericalTolerance;
24 |
25 | float PointToSegmentSqDistance(const v2f& pt, const CLineBase& line);
26 |
27 | float PointToLineSqDistance(const v2f& pt, const CLineBase& line);
28 |
29 | float PointToLineSqDistance(const v2f& pt, const v2f& p1, const v2f& p2);
30 |
31 | float RoomPerimeter(const CRoom& room1);
32 |
33 | float RoomContact(const CRoom& room1, const CRoom& room2);
34 |
35 | float RoomContact(const CRoom& room1, const CRoom& room2, int& edgeIdx1, int& edgeIdx2);
36 |
37 | float EdgeContact(const CLineBase& line1, const CLineBase& line2);
38 |
39 | float RoomDistance(const CRoom& room1, const CRoom& room2);
40 |
41 | bool SegmentIntersection(v2f pa, v2f pb, v2f pc, v2f pd, v2f& pi);
42 |
43 | bool SegmentIntersection(float Ax, float Ay, float Bx, float By, float Cx, float Cy, float Dx, float Dy, float& Ix, float& Iy);
44 |
45 | bool LineIntersection(v2f pa, v2f pb, v2f pc, v2f pd, v2f& pi);
46 |
47 | bool LineIntersection(float Ax, float Ay, float Bx, float By, float Cx, float Cy, float Dx, float Dy, float& Ix, float& Iy);
48 |
49 | bool ComparePrSmallerFirst(const PrSort& pr1, const PrSort& pr2);
50 |
51 | void SortVecPr(std::vector& vecPr);
52 |
53 | v3f randomColorFromIndex(int idx);
54 | } // namespace level_math
55 |
56 | #endif // LEVELMATH_H
57 |
--------------------------------------------------------------------------------
/src/LevelSynth.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) www.chongyangma.com
2 | //
3 | // author: Chongyang Ma - 2013-03-07
4 | // email: chongyangm@gmail.com
5 | // info: class declaration of the level synthesis algorithm
6 | // --------------------------------------------------------------
7 |
8 | #ifndef LEVELSYNTH_H
9 | #define LEVELSYNTH_H
10 |
11 | #include "ConfigSpace.h"
12 | #include "LevelConfig.h"
13 | #include "PlanarGraph.h"
14 | #include "RoomLayout.h"
15 | #include "RoomTemplates.h"
16 | #include "clipperWrapper.h"
17 |
18 | #include
19 | #include
20 |
21 | #ifdef __linux__
22 | #include
23 | #endif
24 |
25 | //#define PRINT_OUT_DEBUG_INFO
26 |
27 | // Use to track current solution state
28 | class CurrentState
29 | {
30 | public:
31 | CPlanarGraph m_stateGraph;
32 | std::vector m_stateRoomPositions;
33 | std::vector myIndices;
34 |
35 | float m_stateEnergy;
36 |
37 | void MoveRoomsToSceneCenter(CPlanarGraph* ptrGraph);
38 |
39 | void Move1DchainToSceneCenter(std::vector& indices);
40 |
41 | float GetStateDifference(CurrentState& otherState, CPlanarGraph* ptrGraph);
42 |
43 | bool InsertToNewStates(std::vector& newStates, CPlanarGraph* ptrGraph);
44 | };
45 |
46 | class CLevelSynth
47 | {
48 | public:
49 | CLevelSynth();
50 |
51 | CLevelSynth(CPlanarGraph* ptrGraph, CRoomTemplates* ptrTemplates);
52 |
53 | void SetGraphAndTemplates(CPlanarGraph* ptrGraph, CRoomTemplates* ptrTemplates);
54 |
55 | void SetGraph(CPlanarGraph* ptrGraph);
56 |
57 | bool MovePickedGraphNode(float& dx, float& dy);
58 |
59 | bool AdjustPickedRoom(float& dx, float& dy);
60 |
61 | void InitScene();
62 |
63 | CRoomLayout GetLayout(CPlanarGraph* ptrGraph, std::vector& roomPositions);
64 |
65 | void SynthesizeScene();
66 |
67 | void UpdateGraphFromLayout();
68 |
69 | bool PostProcessing(CRoomLayout& layout, CPlanarGraph* ptrGraph);
70 |
71 | bool OpenDoors(CRoomLayout& layout, CPlanarGraph* ptrGraph, bool flagPartial = false);
72 |
73 | bool OpenDoor(CRoom& room, RoomDoor& door, float width = -1.f);
74 |
75 | bool OpenDoors(CRoomLayout& layout, CRoomLayout& layoutShrinked, CPlanarGraph* ptrGraph, float thrinkDist);
76 |
77 | void ShrinkRooms(CRoomLayout& layout, float dist);
78 |
79 | void ShrinkRoom(CRoom& room, float dist);
80 |
81 | bool SaveGraphAsSVG(const char* fileName, CPlanarGraph* ptrGraph, int wd = 800, int ht = 800, float labelRad = 0.25f);
82 |
83 | static bool CompareStateEnergySmallerFirst(const CurrentState& state1, const CurrentState& state2);
84 |
85 | int GetSolutionCount() { return m_solutionCount; }
86 |
87 | void ResetSolutionCount() { m_solutionCount = 0; }
88 |
89 | void ResetIterationCount()
90 | {
91 | m_chainCount = 0;
92 | }
93 |
94 | inline std::string sprint(const char* fmt, ...)
95 | {
96 | int size = 512;
97 | char* buffer = 0;
98 | buffer = new char[size];
99 | va_list vl;
100 | va_start(vl, fmt);
101 | int nsize = vsnprintf(buffer, size, fmt, vl);
102 | if (size <= nsize)
103 | {
104 | //fail delete buffer and try again
105 | delete[] buffer;
106 | buffer = 0;
107 | buffer = new char[nsize + 1]; //+1 for /0
108 | nsize = vsnprintf(buffer, size, fmt, vl);
109 | }
110 | std::string ret(buffer);
111 | va_end(vl);
112 | delete[] buffer;
113 | return ret;
114 | }
115 |
116 | private:
117 | void SynthesizeSceneViaMainLoop();
118 |
119 | bool Solve1Dchain(std::vector& indices, std::vector* tmpIndices, CurrentState& oldState, std::vector& newStates);
120 |
121 | bool Solve1DchainILS(std::vector& indices, CurrentState& oldState, std::vector& newStates);
122 |
123 | void SetCurrentState(CurrentState& s);
124 |
125 | void SetSequenceAs1Dchain(const std::vector& indices, CPlanarGraph* ptrGraph);
126 |
127 | void SetVisitedNeighbors(const std::vector& indices);
128 |
129 | void DumpSolutionIntoXML();
130 |
131 | int RandomlyPickOneRoom(CRoomLayout& layout);
132 |
133 | int RandomlyPickOneRoom(std::vector& indices, std::vector* weightedIndices = NULL);
134 |
135 | int RandomlyPickOneRoom(CRoomLayout& layout, std::vector& indices, std::vector* weightedIndices);
136 |
137 | int RandomlyPickAnotherRoom(CRoomLayout& layout, int pickedIndex);
138 |
139 | std::vector GetConnectedIndices(CPlanarGraph* ptrGraph, int pickedIndex, bool flagVisitedOnly = true);
140 |
141 | int RandomlyAdjustOneRoom(CRoomLayout& layout, CPlanarGraph* ptrGraph, std::vector& indices, std::vector* weightedIndices);
142 |
143 | void RandomlyAdjustOneRoom01(CRoomLayout& layout, CPlanarGraph* ptrGraph, std::vector& indices);
144 |
145 | void RandomlyAdjustOneRoom02(CRoomLayout& layout, CPlanarGraph* ptrGraph, std::vector& indices);
146 |
147 | int RandomlyAdjustOneRoom03(CRoomLayout& layout, CPlanarGraph* ptrGraph, std::vector& indices, std::vector* weightedIndices);
148 |
149 | void SampleConfigSpaceForPickedRoom(CRoomLayout& layout, CPlanarGraph* ptrGraph, std::vector& indices, int pickedRoomIndex);
150 |
151 | int RandomlyAdjustOneRoom04(CRoomLayout& layout, CPlanarGraph* ptrGraph, std::vector& indices, std::vector* weightedIndices);
152 |
153 | int GradientDescentOneRoom(CRoomLayout& layout, CPlanarGraph* ptrGraph, std::vector& indices);
154 |
155 | float GetLayoutEnergy(CRoomLayout& layout, CPlanarGraph* ptrGraph, float& collideArea, float& connectivity, int roomThatMoved = -1, bool doContact = false, std::vector* indicesForContact = NULL);
156 |
157 | bool GetLayoutEnergyEarlyOut(CRoomLayout& layout, CPlanarGraph* ptrGraph, float& collideArea, float& connectivity, int roomThatMoved = -1, float* energyTmp = NULL, float energyCurrent = 0.0f);
158 |
159 | float CheckRoomConnectivity(CRoomLayout& layout, CPlanarGraph* ptrGraph, bool flagVisitedOnly = false, int roomThatMoved = -1);
160 |
161 | float LayoutCollide(CRoomLayout& layout, CPlanarGraph* ptrGraph, bool flagVisitedOnly = false, int roomThatMoved = -1);
162 |
163 | float LayoutCollide(CRoomLayout& layout);
164 |
165 | float RoomCollides(CRoom& room1, CRoom& room2);
166 |
167 | float BoundingBoxCollidesArea(AABB2f& bb1, AABB2f& bb2); // not-in-use
168 |
169 | bool TestBoundingBoxCollides(AABB2f& bb1, AABB2f& bb2);
170 |
171 | float LayoutContact(CRoomLayout& layout, CPlanarGraph* ptrGraph, bool flagVisitedOnly = false, bool flagNonOverlap = false, std::vector* indices = NULL, int roomThatMoved = -1);
172 |
173 | v2f ComputeLabelPosition(int idx, CPlanarGraph* ptrGraph, float labelRad);
174 |
175 | std::vector m_sequence; // 1D chain of instantiated room templates
176 |
177 | CPlanarGraph* m_ptrGraph;
178 | CRoomTemplates* m_ptrTemplates;
179 | CRoomLayout m_layout;
180 |
181 | int m_solutionCount;
182 | std::vector m_roomPositions;
183 | std::vector> m_visitedNeighbors;
184 | int m_bestSolCount = 0;
185 |
186 | bool m_flagVisitedNoNode;
187 |
188 | int m_chainCount;
189 |
190 | int m_backTrackCount;
191 | int m_backTrackLevel;
192 | };
193 |
194 | #endif // LEVELSYNTH_H
195 |
--------------------------------------------------------------------------------
/src/LevelTimer.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) www.chongyangma.com
2 | //
3 | // author: Chongyang Ma - 2013-08-28
4 | // email: chongyangm@gmail.com
5 | // info: class declaration of CLevelTimer for performance measurement
6 | // -------------------------------------------------------------------
7 |
8 | #ifndef LEVELTIMER_H
9 | #define LEVELTIMER_H
10 |
11 | #ifdef __APPLE__
12 |
13 | #include
14 |
15 | class CLevelTimer
16 | {
17 | public:
18 | CLevelTimer() {}
19 |
20 | double GetTime()
21 | {
22 | double time = CFAbsoluteTimeGetCurrent();
23 | return time;
24 | }
25 |
26 | double GetElapsedTime(double old_time)
27 | {
28 | double time = CFAbsoluteTimeGetCurrent();
29 | return (time - old_time);
30 | }
31 | };
32 |
33 | #endif
34 |
35 | #ifdef WIN32
36 |
37 | #include
38 | typedef __int64 i64;
39 |
40 | class CLevelTimer
41 | {
42 | public:
43 | CLevelTimer();
44 | double GetTime();
45 | double GetElapsedTime(double old_time);
46 |
47 | private:
48 | i64 m_freq;
49 | i64 m_clocks;
50 | };
51 |
52 | CLevelTimer::CLevelTimer() :
53 | m_clocks(0)
54 | {
55 | QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq);
56 | }
57 |
58 | double CLevelTimer::GetTime()
59 | {
60 | QueryPerformanceCounter((LARGE_INTEGER*)&m_clocks);
61 | return (double)m_clocks / (double)m_freq;
62 | }
63 |
64 | double CLevelTimer::GetElapsedTime(double old_time)
65 | {
66 | QueryPerformanceCounter((LARGE_INTEGER*)&m_clocks);
67 | return ((double)m_clocks / (double)m_freq - old_time);
68 | }
69 |
70 | #endif
71 |
72 | #ifdef __linux__
73 |
74 | #include
75 |
76 | class CLevelTimer
77 | {
78 | public:
79 | CLevelTimer() {}
80 |
81 | double GetTime()
82 | {
83 | double time_res = (double)time(NULL);
84 | return time_res;
85 | }
86 |
87 | double GetElapsedTime(double old_time)
88 | {
89 | double time_res = time(NULL);
90 | return (time_res - old_time);
91 | }
92 | };
93 |
94 | #endif
95 |
96 | #endif // LEVELTIMER_H
97 |
--------------------------------------------------------------------------------
/src/LineBase.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) www.chongyangma.com
2 | //
3 | // author: Chongyang Ma - 2013-08-22
4 | // email: chongyangm@gmail.com
5 | // info: base class declaration of a line-shaped object
6 | // --------------------------------------------------------------
7 |
8 | #ifndef LINEBASE_H
9 | #define LINEBASE_H
10 |
11 | #include "vec.h"
12 |
13 | class CLineBase
14 | {
15 | public:
16 | CLineBase()
17 | {
18 | m_pos1 = v2f(0.f);
19 | m_pos2 = v2f(0.f);
20 | }
21 |
22 | CLineBase(v2f pos) :
23 | m_pos1(pos), m_pos2(pos)
24 | {
25 | }
26 |
27 | CLineBase(v2f pos1, v2f pos2) :
28 | m_pos1(pos1), m_pos2(pos2)
29 | {
30 | }
31 |
32 | float GetLength() const { return mag(m_pos2 - m_pos1); }
33 |
34 | float GetSqLength() const { return mag2(m_pos2 - m_pos1); }
35 |
36 | v2f GetPos1() const { return m_pos1; }
37 | v2f GetPos2() const { return m_pos2; }
38 |
39 | void SetPos1(v2f pos1) { m_pos1 = pos1; }
40 | void SetPos2(v2f pos2) { m_pos2 = pos2; }
41 |
42 | protected:
43 | v2f m_pos1;
44 | v2f m_pos2;
45 | };
46 |
47 | #endif // LINEBASE_H
48 |
--------------------------------------------------------------------------------
/src/PlanarGraph.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) www.chongyangma.com
2 | //
3 | // author: Chongyang Ma - 2013-02-28
4 | // email: chongyangm@gmail.com
5 | // info: class declaration of a planar graph
6 | // --------------------------------------------------------------
7 |
8 | #ifndef PLANARGRAPH_H
9 | #define PLANARGRAPH_H
10 |
11 | #include "tinyxml2.h"
12 |
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | using namespace boost;
28 |
29 | #include "GraphChain.h"
30 | #include "GraphEdge.h"
31 | #include "GraphFace.h"
32 | #include "GraphNode.h"
33 | #include "vec.h"
34 |
35 | class CPlanarGraph
36 | {
37 | public:
38 | typedef adjacency_list,
42 | property>
43 | Graph;
44 |
45 | typedef graph_traits::vertex_descriptor VertexDescriptor;
46 | typedef graph_traits::vertex_iterator VertexIterator;
47 | typedef graph_traits::edge_descriptor EdgeDescriptor;
48 | typedef graph_traits::out_edge_iterator OutEdgeIterator;
49 |
50 | CPlanarGraph();
51 |
52 | void ClearGraph();
53 |
54 | void PrintGraph();
55 |
56 | bool LoadGraphFromXML(const char* fileName, bool flagDetectFaces = true, bool flagIgnoreIndiv = true);
57 |
58 | bool SaveGraphAsXML(const char* fileName);
59 |
60 | void AddGraphNode(CGraphNode& node) { m_nodes.push_back(node); }
61 | //void AddGraphEdge(CGraphEdge& edge) { m_edges.push_back(edge); }
62 | bool AddGraphEdge(const CGraphEdge& edge);
63 |
64 | bool CheckDuplicatedEdge(const CGraphEdge& edge);
65 |
66 | void AddGraphNodes(int numOfNodes, int parent = -1);
67 |
68 | void SetNodeNeighbors();
69 |
70 | bool FindLineIntersect(v2f p1, v2f p2, v2f p3, v2f p4)
71 | {
72 | return FindLineIntersect(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1], p4[0], p4[1]);
73 | }
74 |
75 | bool FindLineIntersect(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4)
76 | {
77 | float s1 = (y1 - y2) * (x3 - x4) - (x1 - x2) * (y3 - y4);
78 | float s0 = (x1 - x2) * (y4 - y2) - (y1 - y2) * (x4 - x2);
79 | float t1 = (y3 - y4) * (x1 - x2) - (x3 - x4) * (y1 - y2);
80 | float t0 = (x3 - x4) * (y2 - y4) - (y3 - y4) * (x2 - x4);
81 | if (std::abs(s1) > 0.f && std::abs(t1) > 0.f)
82 | {
83 | float s = s0 / s1;
84 | float t = t0 / t1;
85 | if (s > 0.f && s < 1.f && t > 0.f && t < 1.f)
86 | {
87 | return true;
88 | }
89 | }
90 |
91 | return false;
92 | }
93 |
94 | void PickClosestNode(float px, float py);
95 |
96 | void MovePickedNode(float dx, float dy);
97 |
98 | void MovePickedNode(v2f dp) { MovePickedNode(dp[0], dp[1]); }
99 |
100 | void UnpickNode() { m_pickedNodeIndex = -1; }
101 |
102 | int GetPickedNodeIndex() { return m_pickedNodeIndex; }
103 |
104 | int GetNumOfNodes() { return int(m_nodes.size()); }
105 |
106 | int GetNumOfEdges() { return int(m_edges.size()); }
107 |
108 | int GetNumOfFaces() { return int(m_faces.size()); }
109 |
110 | v2f GetNodePos(int idx) { return m_nodes[idx].GetPos(); }
111 |
112 | void RandomInitGraph();
113 |
114 | void RandomInitPositions();
115 |
116 | void RandomInitTypes();
117 |
118 | void DetectFaces();
119 |
120 | void SortAdjacentVertices(const Graph& g, VertexDescriptor vert, std::vector& adjacentEdges);
121 |
122 | bool CompareEdgeDirections(const v2f& edgePr1, const v2f& edgePr2, const v2f& edgeRef);
123 |
124 | void RemoveTheOutsideFace();
125 |
126 | CGraphNode& GetNode(int idx) { return m_nodes[idx]; }
127 | CGraphEdge& GetEdge(int idx) { return m_edges[idx]; }
128 | CGraphFace& GetFace(int idx) { return m_faces[idx]; }
129 | CGraphChain& GetChain(int idx) { return m_chains[idx]; }
130 |
131 | bool VisitedAllNodes();
132 |
133 | bool VisitedNoNode();
134 |
135 | bool HasFixedNode();
136 |
137 | std::vector GetFixedNodes();
138 |
139 | std::vector GetUnfixedNodes();
140 |
141 | // Step 3: Extract the 'deepest' face or chain not yet inserted (the most included one)
142 | std::vector ExtractDeepestFaceOrChain(bool& flagCyclic, bool flagSmallFaceFirst);
143 |
144 | std::vector ExtractDeepestFaceOrChainOld(bool& flagCyclic, bool flagSmallFaceFirst);
145 |
146 | // Extract the 'deepest' face not yet inserted
147 | std::vector ExtractDeepestFace(bool flagSmallFaceFirst);
148 |
149 | // Extract the 'deepest' chain not yet inserted
150 | std::vector ExtractDeepestChainNew();
151 |
152 | std::vector ExtractDeepestChain();
153 |
154 | int CountConstraints(std::vector& indices);
155 |
156 | void SetNumOfTypes(int numOfTypes) { m_numOfTypes = numOfTypes; }
157 |
158 | void GetGraphBoundingBox(v2f& posMin, v2f& posMax);
159 |
160 | void MoveGraphToSceneCenter();
161 |
162 | void ScaleGraphNodePositions(float scaling);
163 |
164 | bool LoadChainsFromTXT(const char* fileName);
165 |
166 | int FindNodeAccordingToName(const char* str);
167 |
168 | void RemoveIndividualNodes();
169 |
170 | private:
171 | inline int Random2(int max)
172 | {
173 | if (max < 1 || max >= RAND_MAX)
174 | return 0;
175 | else
176 | return (int)rand() / (RAND_MAX / max + 1);
177 | }
178 |
179 | inline bool OneChanceIn(int a_million)
180 | {
181 | return (Random2(a_million) == 0);
182 | }
183 |
184 | inline bool CoinFlip()
185 | {
186 | return OneChanceIn(2);
187 | }
188 |
189 | std::vector m_nodes;
190 | std::vector m_edges;
191 | int m_pickedNodeIndex;
192 |
193 | static CGraphFace m_faceTmp;
194 | static std::vector m_faces;
195 |
196 | std::vector m_chains;
197 |
198 | int m_numOfTypes; // number of node types
199 |
200 | // Some planar face traversal visitors that will
201 | // print the vertices and edges on the faces
202 | struct output_visitor : public planar_face_traversal_visitor
203 | {
204 | void begin_face()
205 | {
206 | m_faceTmp.ClearIndices();
207 | std::cout << "New face: ";
208 | }
209 |
210 | void end_face()
211 | {
212 | std::cout << std::endl;
213 | if (m_faceTmp.IsEmpty() == false)
214 | {
215 | m_faces.push_back(m_faceTmp);
216 | }
217 | }
218 | };
219 |
220 | struct vertex_output_visitor : public output_visitor
221 | {
222 | template
223 | void next_vertex(Vertex v)
224 | {
225 | std::cout << v << " ";
226 | m_faceTmp.AddIndex(int(v));
227 | }
228 | };
229 |
230 | struct edge_output_visitor : public output_visitor
231 | {
232 | template
233 | void next_edge(Edge e)
234 | {
235 | std::cout << e << " ";
236 | }
237 | };
238 | };
239 |
240 | #endif // PLANARGRAPH_H
241 |
--------------------------------------------------------------------------------
/src/Room.cpp:
--------------------------------------------------------------------------------
1 | #include "Room.h"
2 |
3 | #include "LevelConfig.h"
4 |
5 | CRoom::CRoom()
6 | {
7 | m_templateType = -1;
8 | m_flagFixed = false;
9 | m_boundaryType = 0;
10 | ResetEnergy();
11 | }
12 |
13 | CRoomEdge CRoom::GetEdge(int idx) const
14 | {
15 | int idx1 = idx;
16 | int idx2 = (idx + 1) % GetNumOfVertices();
17 | CRoomEdge edge;
18 | edge.SetPos1(GetVertex(idx1));
19 | edge.SetPos2(GetVertex(idx2));
20 | edge.SetIdx1(idx1);
21 | edge.SetIdx2(idx2);
22 | edge.SetDoorFlag(GetDoorFlag(idx));
23 | return edge;
24 | }
25 |
26 | v2f CRoom::GetRoomCenter() const
27 | {
28 | v2f center(0.f);
29 | if (GetNumOfVertices() == 0)
30 | {
31 | return center;
32 | }
33 | v2f posMin(1e10);
34 | v2f posMax(-1e10);
35 | for (int i = 0; i < GetNumOfVertices(); i++)
36 | {
37 | v2f pi = m_vertices[i];
38 | for (int j = 0; j < 2; j++)
39 | {
40 | posMin[j] = min(posMin[j], pi[j]);
41 | posMax[j] = max(posMax[j], pi[j]);
42 | }
43 | }
44 | center = (posMin + posMax) * 0.5f;
45 | return center;
46 | }
47 |
48 | v2f CRoom::GetShiftedRoomCenter()
49 | {
50 | v2f center = GetRoomCenter() + m_centerShift;
51 | return center;
52 | }
53 |
54 | void CRoom::TranslateRoom(v2f trans)
55 | {
56 | for (int i = 0; i < GetNumOfVertices(); i++)
57 | {
58 | m_vertices[i] = m_vertices[i] + trans;
59 | }
60 | }
61 |
62 | void CRoom::RotateRoom(float rad)
63 | {
64 | float cv = cos(rad);
65 | float sv = sin(rad);
66 | for (int i = 0; i < GetNumOfVertices(); i++)
67 | {
68 | float p0 = m_vertices[i][0];
69 | float p1 = m_vertices[i][1];
70 | m_vertices[i][0] = p0 * cv + p1 * sv;
71 | m_vertices[i][1] = -p0 * sv + p1 * cv;
72 | }
73 | float p0 = m_centerShift[0];
74 | float p1 = m_centerShift[1];
75 | m_centerShift[0] = p0 * cv + p1 * sv;
76 | m_centerShift[1] = -p0 * sv + p1 * cv;
77 | }
78 |
79 | void CRoom::ScaleRoom(float scaling)
80 | {
81 | v2f center = GetRoomCenter();
82 | for (int i = 0; i < GetNumOfVertices(); i++)
83 | {
84 | v2f pi = m_vertices[i] - center;
85 | m_vertices[i] = center + pi * scaling;
86 | }
87 | m_centerShift = m_centerShift * scaling;
88 | }
89 |
90 | void CRoom::ScaleRoom(v2f scaling)
91 | {
92 | v2f center = GetRoomCenter();
93 | for (int i = 0; i < GetNumOfVertices(); i++)
94 | {
95 | v2f pi = m_vertices[i] - center;
96 | pi[0] *= scaling[0];
97 | pi[1] *= scaling[1];
98 | m_vertices[i] = center + pi;
99 | }
100 | m_centerShift[0] *= scaling[0];
101 | m_centerShift[1] *= scaling[1];
102 | }
103 |
104 | void CRoom::GetRoomBoundingBox(v2f& posMin, v2f& posMax)
105 | {
106 | v2f pMin(1e10);
107 | v2f pMax(-1e10);
108 | for (int i = 0; i < GetNumOfVertices(); i++)
109 | {
110 | v2f pi = m_vertices[i];
111 | for (int j = 0; j < 2; j++)
112 | {
113 | pMin[j] = min(pMin[j], pi[j]);
114 | pMax[j] = max(pMax[j], pi[j]);
115 | }
116 | }
117 | posMin = pMin;
118 | posMax = pMax;
119 | }
120 |
121 | void CRoom::GetRoomBoundingBox(AABB2f& boundingBox)
122 | {
123 | v2f posMin, posMax;
124 | GetRoomBoundingBox(posMin, posMax);
125 | boundingBox.m_posMin = posMin;
126 | boundingBox.m_posMax = posMax;
127 | }
128 |
129 | void CRoom::PrintRoom()
130 | {
131 | std::cout << "A room with " << GetNumOfVertices() << " vertices...\n";
132 | for (int i = 0; i < GetNumOfVertices(); i++)
133 | {
134 | std::cout << i << "th vertex: " << GetVertex(i) << std::endl;
135 | }
136 | }
137 |
138 | void CRoom::InitWalls()
139 | {
140 | m_walls.clear();
141 | for (int i = 0; i < GetNumOfVertices(); i++)
142 | {
143 | int idx1 = i;
144 | int idx2 = (i + 1) % GetNumOfVertices();
145 | v2f pos1 = GetVertex(idx1);
146 | v2f pos2 = GetVertex(idx2);
147 | RoomWall wall(pos1, pos2);
148 | m_walls.push_back(wall);
149 | }
150 | }
151 |
152 | bool CRoom::EraseWall(int idx)
153 | {
154 | if (idx >= GetNumOfWalls())
155 | {
156 | return false;
157 | }
158 | m_walls.erase(m_walls.begin() + idx);
159 | return true;
160 | }
161 |
162 | void CRoom::ResetDoorFlags()
163 | {
164 | if (m_doorFlags.empty() == false)
165 | {
166 | return;
167 | }
168 | m_doorFlags.resize(GetNumOfEdges(), false);
169 | }
170 |
171 | void CRoom::SetDoorFlag(int edgeIdx, bool doorFlag)
172 | {
173 | if (edgeIdx < 0 || edgeIdx >= int(m_doorFlags.size()))
174 | {
175 | return;
176 | }
177 | m_doorFlags[edgeIdx] = doorFlag;
178 | }
179 |
180 | bool CRoom::GetDoorFlag(int edgeIdx) const
181 | {
182 | if (edgeIdx < 0 || edgeIdx >= int(m_doorFlags.size()))
183 | {
184 | return true;
185 | }
186 | return m_doorFlags[edgeIdx];
187 | }
188 |
189 | std::vector CRoom::GetDoorFlags() const
190 | {
191 | return m_doorFlags;
192 | }
193 |
194 | bool CRoom::HasRestrictedDoorPosition() const
195 | {
196 | for (int i = 0; i < int(m_doorFlags.size()); i++)
197 | {
198 | if (m_doorFlags[i] == false)
199 | {
200 | return true;
201 | }
202 | }
203 | return false;
204 | }
205 |
--------------------------------------------------------------------------------
/src/Room.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) www.chongyangma.com
2 | //
3 | // author: Chongyang Ma - 2013-03-07
4 | // email: chongyangm@gmail.com
5 | // info: class declaration of a single room
6 | // --------------------------------------------------------------
7 |
8 | #ifndef ROOM_H
9 | #define ROOM_H
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 |
17 | #include "tinyxml2.h"
18 |
19 | #include "vec.h"
20 | #include "RoomEdge.h"
21 |
22 | typedef struct AABB2f
23 | {
24 | v2f m_posMin;
25 | v2f m_posMax;
26 | } AABB2f;
27 |
28 | typedef CLineBase RoomWall;
29 | typedef CLineBase RoomDoor;
30 |
31 | class CRoom
32 | {
33 | public:
34 | CRoom();
35 |
36 | std::vector& GetVertices() { return m_vertices; }
37 |
38 | void SetVertices(std::vector& vertices) { m_vertices = vertices; }
39 |
40 | void SetVertex(v2f& pos, int idx) { m_vertices[idx] = pos; }
41 |
42 | void SetCenterShift(v2f& shift) { m_centerShift = shift; }
43 |
44 | v2f GetCenterShift() const { return m_centerShift; }
45 |
46 | v2f GetVertex(int idx) const { return m_vertices[idx]; }
47 |
48 | CRoomEdge GetEdge(int idx) const;
49 |
50 | int GetNumOfVertices() const { return int(m_vertices.size()); }
51 |
52 | int GetNumOfEdges() const { return int(m_vertices.size()); }
53 |
54 | v2f GetRoomCenter() const;
55 |
56 | v2f GetShiftedRoomCenter();
57 |
58 | void TranslateRoom(v2f trans);
59 |
60 | void RotateRoom(float rad);
61 |
62 | void ScaleRoom(float scaling);
63 |
64 | void ScaleRoom(v2f scaling);
65 |
66 | void GetRoomBoundingBox(v2f& posMin, v2f& posMax);
67 |
68 | void GetRoomBoundingBox(AABB2f& boundingBox);
69 |
70 | v3f GetColor() { return m_color; }
71 | void SetColor(v3f color) { m_color = color; }
72 |
73 | float GetEnergy() { return m_energy; }
74 | void SetEnergy(float energy) { m_energy = energy; }
75 | void ResetEnergy() { SetEnergy(1.f); }
76 | void UpdateEnergy(float factor) { m_energy *= factor; }
77 |
78 | void PrintRoom();
79 |
80 | bool HasWalls() const { return (m_walls.empty() == false); }
81 |
82 | void InitWalls();
83 |
84 | bool EraseWall(int idx);
85 |
86 | void InsertWall(RoomWall& wall) { m_walls.push_back(wall); }
87 |
88 | int GetNumOfWalls() const { return int(m_walls.size()); }
89 |
90 | RoomWall& GetWall(int idx) { return m_walls[idx]; }
91 |
92 | int GetTemplateType() const { return m_templateType; }
93 | void SetTemplateType(int type) { m_templateType = type; }
94 |
95 | int GetBoundaryType() const { return m_boundaryType; }
96 | void SetBoundaryType(int type) { m_boundaryType = type; }
97 |
98 | bool GetFlagFixed() const { return m_flagFixed; }
99 | void SetFlagFixed(bool flagFixed) { m_flagFixed = flagFixed; }
100 |
101 | void ResetDoorFlags();
102 | void SetDoorFlag(int edgeIdx, bool doorFlag);
103 | bool GetDoorFlag(int edgeIdx) const;
104 | std::vector GetDoorFlags() const;
105 | bool HasRestrictedDoorPosition() const;
106 |
107 | private:
108 | std::vector m_vertices;
109 | v2f m_centerShift = v2f(0.f, 0.f);;
110 | std::vector m_walls;
111 | v3f m_color = v3f(0.5f, 0.5f, 0.5f);
112 | float m_energy;
113 | int m_templateType;
114 | bool m_flagFixed;
115 | int m_boundaryType;
116 | std::vector m_doorFlags;
117 | };
118 |
119 | #endif // ROOM_H
120 |
--------------------------------------------------------------------------------
/src/RoomEdge.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) www.chongyangma.com
2 | //
3 | // author: Chongyang Ma - 2013-08-22
4 | // email: chongyangm@gmail.com
5 | // info: class declaration of a room edge
6 | // --------------------------------------------------------------
7 |
8 | #ifndef ROOMEDGE_H
9 | #define ROOMEDGE_H
10 |
11 | #include "LineBase.h"
12 |
13 | class CRoomEdge : public CLineBase
14 | {
15 | public:
16 | CRoomEdge()
17 | {
18 | m_idx1 = -1;
19 | m_idx2 = -1;
20 | m_doorFlag = true;
21 | }
22 |
23 | CRoomEdge(v2f pos1, v2f pos2) : CLineBase(pos1, pos2)
24 | {
25 | m_idx1 = -1;
26 | m_idx2 = -1;
27 | m_doorFlag = true;
28 | }
29 |
30 | CRoomEdge(v2f pos1, v2f pos2, int idx1, int idx2) : CLineBase(pos1, pos2), m_idx1(idx1), m_idx2(idx2)
31 | {
32 | m_doorFlag = true;
33 | }
34 |
35 | v2f GetDirection() { return (m_pos2 - m_pos1); }
36 |
37 | v3f GetDirection3D() { return v3f(GetDirection()[0], GetDirection()[1], 0.f); }
38 |
39 | int GetIdx1() const { return m_idx1; }
40 | int GetIdx2() const { return m_idx2; }
41 |
42 | void SetIdx1(int idx1) { m_idx1 = idx1; }
43 | void SetIdx2(int idx2) { m_idx2 = idx2; }
44 |
45 | void SetDoorFlag(bool flag) { m_doorFlag = flag; }
46 | bool GetDoorFlag() { return m_doorFlag; }
47 |
48 | private:
49 | int m_idx1;
50 | int m_idx2;
51 |
52 | bool m_doorFlag;
53 | };
54 |
55 | #endif // ROOMEDGE_H
56 |
--------------------------------------------------------------------------------
/src/RoomLayout.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) www.chongyangma.com
2 | //
3 | // author: Chongyang Ma - 2013-03-07
4 | // email: chongyangm@gmail.com
5 | // info: class declaration of a room layout, i.e. a set of rooms
6 | // --------------------------------------------------------------
7 |
8 | #ifndef ROOMLAYOUT_H
9 | #define ROOMLAYOUT_H
10 |
11 | //#define DUMP_INTERMEDIATE_OUTPUT
12 | //#define DUMP_PARTIAL_SOLUTION
13 | #define PERFORMANCE_TEST 1
14 |
15 | #include "Room.h"
16 |
17 | #include