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