1 /*
2  Copyright (C) 2010-2014 Kristian Duske
3 
4  This file is part of TrenchBroom.
5 
6  TrenchBroom is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  TrenchBroom is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "PointFile.h"
21 
22 #include "IO/Path.h"
23 
24 #include <cassert>
25 #include <fstream>
26 
27 namespace TrenchBroom {
28     namespace Model {
PointFile()29         PointFile::PointFile() :
30         m_current(0) {}
31 
PointFile(const IO::Path & mapFilePath)32         PointFile::PointFile(const IO::Path& mapFilePath) :
33         m_current(0) {
34             load(pointFilePath(mapFilePath));
35         }
36 
empty() const37         bool PointFile::empty() const {
38             return m_points.empty();
39         }
40 
hasNextPoint() const41         bool PointFile::hasNextPoint() const {
42             return m_current < m_points.size() - 1;
43         }
44 
hasPreviousPoint() const45         bool PointFile::hasPreviousPoint() const {
46             return m_current > 0;
47         }
48 
points() const49         const Vec3f::List& PointFile::points() const {
50             return m_points;
51         }
52 
currentPoint() const53         const Vec3f& PointFile::currentPoint() const {
54             return m_points[m_current];
55         }
56 
currentDirection() const57         const Vec3f PointFile::currentDirection() const {
58             if (m_points.size() <= 1)
59                 return Vec3f::PosX;
60             if (m_current >= m_points.size() - 1)
61                 return (m_points[m_points.size() - 1] - m_points[m_points.size() - 2]).normalized();
62             return (m_points[m_current + 1] - m_points[m_current]).normalized();
63         }
64 
advance()65         void PointFile::advance() {
66             assert(hasNextPoint());
67             ++m_current;
68         }
69 
retreat()70         void PointFile::retreat() {
71             assert(hasPreviousPoint());
72             --m_current;
73         }
74 
pointFilePath(const IO::Path & mapFilePath)75         IO::Path PointFile::pointFilePath(const IO::Path& mapFilePath) {
76             return mapFilePath.deleteExtension().addExtension("pts");
77         }
78 
load(const IO::Path & pointFilePath)79         void PointFile::load(const IO::Path& pointFilePath) {
80             static const float Threshold = Math::radians(15.0f);
81 
82             std::fstream stream(pointFilePath.asString().c_str(), std::ios::in);
83             assert(stream.is_open());
84 
85             Vec3f::List points;
86             String line;
87 
88             if (!stream.eof()) {
89                 std::getline(stream, line);
90                 points.push_back(Vec3f::parse(line));
91                 Vec3f lastPoint = points.back();
92 
93                 if (!stream.eof()) {
94                     std::getline(stream, line);
95                     Vec3f curPoint = Vec3f::parse(line);
96                     Vec3f refDir = (curPoint - lastPoint).normalized();
97 
98                     while (!stream.eof()) {
99                         lastPoint = curPoint;
100                         std::getline(stream, line);
101                         curPoint = Vec3f::parse(line);
102 
103                         const Vec3f dir = (curPoint - lastPoint).normalized();
104                         if (std::acos(dir.dot(refDir)) > Threshold) {
105                             points.push_back(lastPoint);
106                             refDir = dir;
107                         }
108                     }
109 
110                     points.push_back(curPoint);
111                 }
112             }
113 
114             if (points.size() > 1) {
115                 for (size_t i = 0; i < points.size() - 1; ++i) {
116                     const Vec3f& curPoint = points[i];
117                     const Vec3f& nextPoint = points[i + 1];
118                     const Vec3f dir = (nextPoint - curPoint).normalized();
119 
120                     m_points.push_back(curPoint);
121                     const float dist = (nextPoint - curPoint).length();
122                     size_t segments = static_cast<size_t>(dist / 64.0f);
123                     for (unsigned int j = 1; j < segments; ++j)
124                         m_points.push_back(curPoint + dir * static_cast<float>(j) * 64.0f);
125                 }
126                 m_points.push_back(points.back());
127             }
128         }
129     }
130 }
131