<commit_before>/*
 * This file is a part of Xpiks - cross platform application for
 * keywording and uploading images for microstocks
 * Copyright (C) 2014-2016 Taras Kushnir <kushnirTV@gmail.com>
 *
 * Xpiks is distributed under the GNU General Public License, version 3.0
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "artworkmetadata.h"
#include <QReadLocker>
#include <QWriteLocker>
#include <QStringBuilder>
#include <QDir>
#include "../Helpers/keywordvalidator.h"
#include "settingsmodel.h"
#include "../SpellCheck/spellsuggestionsitem.h"
#include "../SpellCheck/spellcheckitem.h"
#include "../SpellCheck/spellcheckiteminfo.h"
#include "../Common/defines.h"

namespace Models {
    ArtworkMetadata::ArtworkMetadata(const QString &filepath, qint64 ID) :
        Common::BasicKeywordsModel(),
        m_ArtworkFilepath(filepath),
        m_ID(ID),
        m_IsModified(false),
        m_IsUnavailable(false),
        m_IsSelected(false),
        m_IsInitialized(false),
        m_HasAttachedVector(false)
    {
        setSpellCheckInfo(new SpellCheck::SpellCheckItemInfo());
    }

    ArtworkMetadata::~ArtworkMetadata() {
        this->freeSpellCheckInfo();
    }

    bool ArtworkMetadata::initialize(const QString &title,
                                     const QString &description, const QStringList &rawKeywords, bool overwrite) {
        bool anythingModified = false;

        if (overwrite || (isTitleEmpty() && !title.trimmed().isEmpty())) {
            anythingModified = true;
            BasicKeywordsModel::setTitle(title);
        }

        if (overwrite || (isDescriptionEmpty() && !description.trimmed().isEmpty())) {
            anythingModified = true;
            BasicKeywordsModel::setDescription(description);
        }

        if (overwrite) {
            anythingModified = anythingModified || (!(areKeywordsEmpty() && rawKeywords.isEmpty()));
            beginResetModel();
            BasicKeywordsModel::resetKeywords();
            BasicKeywordsModel::addKeywords(rawKeywords);
            endResetModel();
        } else if (!rawKeywords.isEmpty()) {
            int appendedCount = appendKeywords(rawKeywords);
            anythingModified = anythingModified || (appendedCount > 0);
        }

        m_IsModified = false;
        m_IsInitialized = true;

        return anythingModified;
    }

    bool ArtworkMetadata::isInDirectory(const QString &directoryAbsolutePath) const {
        bool isInDir = false;
        Q_ASSERT(directoryAbsolutePath == QDir(directoryAbsolutePath).absolutePath());

        if (m_ArtworkFilepath.startsWith(directoryAbsolutePath)) {
            QFileInfo fi(m_ArtworkFilepath);
            QString artworksDirectory = fi.absolutePath();

            isInDir = artworksDirectory == directoryAbsolutePath;
        }

        return isInDir;
    }

    void ArtworkMetadata::attachVector(const QString &vectorFilepath) {
        m_HasAttachedVector = true;
        m_AttachedVector = vectorFilepath;
    }

    void ArtworkMetadata::detachVector() {
        m_HasAttachedVector = false;
        m_AttachedVector.clear();
    }

    void ArtworkMetadata::clearModel() {
        BasicKeywordsModel::clearModel();
        markModified();
    }

    bool ArtworkMetadata::clearKeywords() {
        bool result = BasicKeywordsModel::clearKeywords();
        if (result) { markModified(); }
        return result;
    }

    bool ArtworkMetadata::editKeyword(int index, const QString &replacement) {
        bool result = BasicKeywordsModel::editKeyword(index, replacement);
        if (result) { markModified(); }
        return result;
    }

    bool ArtworkMetadata::removeKeywordAt(int index) {
        QString removed;
        bool result = BasicKeywordsModel::takeKeywordAt(index, removed);
        if (result) { markModified(); }
        return result;
    }

    bool ArtworkMetadata::removeLastKeyword() {
        QString removed;
        bool result = BasicKeywordsModel::takeLastKeyword(removed);
        if (result) { markModified(); }
        return result;
    }

    bool ArtworkMetadata::appendKeyword(const QString &keyword) {
        bool result = BasicKeywordsModel::appendKeyword(keyword);
        if (result) { markModified(); }
        return result;
    }

    int ArtworkMetadata::appendKeywords(const QStringList &keywordsList) {
        int result = BasicKeywordsModel::appendKeywords(keywordsList);
        LOG_DEBUG << "Appended" << result << "keywords out of" << keywordsList.length();
        if (result > 0) { markModified(); }
        return result;
    }

    void ArtworkMetadata::markModified() {
        if (!m_IsModified) {
            m_IsModified = true;
            emit modifiedChanged(m_IsModified);
        }
    }
}
<commit_msg>reorder to correspond to init order<commit_after>/*
 * This file is a part of Xpiks - cross platform application for
 * keywording and uploading images for microstocks
 * Copyright (C) 2014-2016 Taras Kushnir <kushnirTV@gmail.com>
 *
 * Xpiks is distributed under the GNU General Public License, version 3.0
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "artworkmetadata.h"
#include <QReadLocker>
#include <QWriteLocker>
#include <QStringBuilder>
#include <QDir>
#include "../Helpers/keywordvalidator.h"
#include "settingsmodel.h"
#include "../SpellCheck/spellsuggestionsitem.h"
#include "../SpellCheck/spellcheckitem.h"
#include "../SpellCheck/spellcheckiteminfo.h"
#include "../Common/defines.h"

namespace Models {
    ArtworkMetadata::ArtworkMetadata(const QString &filepath, qint64 ID) :
        Common::BasicKeywordsModel(),
        m_ArtworkFilepath(filepath),
        m_ID(ID),
        m_IsModified(false),
        m_IsSelected(false),
        m_IsInitialized(false),
        m_HasAttachedVector(false),
        m_IsUnavailable(false)
    {
        setSpellCheckInfo(new SpellCheck::SpellCheckItemInfo());
    }

    ArtworkMetadata::~ArtworkMetadata() {
        this->freeSpellCheckInfo();
    }

    bool ArtworkMetadata::initialize(const QString &title,
                                     const QString &description, const QStringList &rawKeywords, bool overwrite) {
        bool anythingModified = false;

        if (overwrite || (isTitleEmpty() && !title.trimmed().isEmpty())) {
            anythingModified = true;
            BasicKeywordsModel::setTitle(title);
        }

        if (overwrite || (isDescriptionEmpty() && !description.trimmed().isEmpty())) {
            anythingModified = true;
            BasicKeywordsModel::setDescription(description);
        }

        if (overwrite) {
            anythingModified = anythingModified || (!(areKeywordsEmpty() && rawKeywords.isEmpty()));
            beginResetModel();
            BasicKeywordsModel::resetKeywords();
            BasicKeywordsModel::addKeywords(rawKeywords);
            endResetModel();
        } else if (!rawKeywords.isEmpty()) {
            int appendedCount = appendKeywords(rawKeywords);
            anythingModified = anythingModified || (appendedCount > 0);
        }

        m_IsModified = false;
        m_IsInitialized = true;

        return anythingModified;
    }

    bool ArtworkMetadata::isInDirectory(const QString &directoryAbsolutePath) const {
        bool isInDir = false;
        Q_ASSERT(directoryAbsolutePath == QDir(directoryAbsolutePath).absolutePath());

        if (m_ArtworkFilepath.startsWith(directoryAbsolutePath)) {
            QFileInfo fi(m_ArtworkFilepath);
            QString artworksDirectory = fi.absolutePath();

            isInDir = artworksDirectory == directoryAbsolutePath;
        }

        return isInDir;
    }

    void ArtworkMetadata::attachVector(const QString &vectorFilepath) {
        m_HasAttachedVector = true;
        m_AttachedVector = vectorFilepath;
    }

    void ArtworkMetadata::detachVector() {
        m_HasAttachedVector = false;
        m_AttachedVector.clear();
    }

    void ArtworkMetadata::clearModel() {
        BasicKeywordsModel::clearModel();
        markModified();
    }

    bool ArtworkMetadata::clearKeywords() {
        bool result = BasicKeywordsModel::clearKeywords();
        if (result) { markModified(); }
        return result;
    }

    bool ArtworkMetadata::editKeyword(int index, const QString &replacement) {
        bool result = BasicKeywordsModel::editKeyword(index, replacement);
        if (result) { markModified(); }
        return result;
    }

    bool ArtworkMetadata::removeKeywordAt(int index) {
        QString removed;
        bool result = BasicKeywordsModel::takeKeywordAt(index, removed);
        if (result) { markModified(); }
        return result;
    }

    bool ArtworkMetadata::removeLastKeyword() {
        QString removed;
        bool result = BasicKeywordsModel::takeLastKeyword(removed);
        if (result) { markModified(); }
        return result;
    }

    bool ArtworkMetadata::appendKeyword(const QString &keyword) {
        bool result = BasicKeywordsModel::appendKeyword(keyword);
        if (result) { markModified(); }
        return result;
    }

    int ArtworkMetadata::appendKeywords(const QStringList &keywordsList) {
        int result = BasicKeywordsModel::appendKeywords(keywordsList);
        LOG_DEBUG << "Appended" << result << "keywords out of" << keywordsList.length();
        if (result > 0) { markModified(); }
        return result;
    }

    void ArtworkMetadata::markModified() {
        if (!m_IsModified) {
            m_IsModified = true;
            emit modifiedChanged(m_IsModified);
        }
    }
}
<|endoftext|>


<commit_before>#include <easylogging.h>

#include <glm/gtc/type_ptr.hpp>

#include "core/model.h"

#include <stdexcept>

std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    split(s, delim, elems);
    return elems;
}

void Model::addGroup(std::string g) {
	groups[g];
}
Model::Model(std::string filename) {
	mode = G308_SHADE_POLYGON;
    m_glGeomListPoly = 0;
    m_glGeomListWire = 0;

	std::string line;
	std::ifstream myfile(filename);
	int v1, v2, v3, n1, n2, n3, t1, t2, t3;
	std::string g;
	if (myfile.is_open())
	{
		while (getline(myfile, line))
		{
			//LOG(INFO) << line;
			if (line.size()<=1 || line[0] == '#') continue;
			std::vector<std::string> t = split(line, ' ');
			if (t[0] == "v" && t.size() == 4) {
				vertices.push_back(glm::vec3(std::stof(t[1]),
                                             std::stof(t[2]),
                                             std::stof(t[3])));
			}
			else if (t[0] == "vt" && t.size() == 4) {
				uv.push_back(glm::vec3(std::stof(t[1]),
                                       std::stof(t[2]),
                                       std::stof(t[3])));
			}
			else if (t[0] == "vt" && t.size() == 3) {
				uv.push_back(glm::vec3(std::stof(t[1]),
                                       std::stof(t[2]),
                                       0));
			}
			else if (t[0] == "vn" && t.size() == 4) {
				normals.push_back(glm::vec3(std::stof(t[1]),
                                            std::stof(t[2]),
                                            std::stof(t[3])));
			}
			else if (t[0] == "f") {
				if (t.size() == 5) {
					int v[4];
					int n[4];
					int u[4];
					for (size_t i = 1; i < t.size(); i++) {
						//LOG(INFO) << t[i];
						v[i-1] = std::stoi(t[i].substr(0, t[i].find_first_of('/')),nullptr);
						u[i - 1] = std::stoi(t[i].substr(t[i].find_first_of('/') + 1, t[i].find_last_of('/') - t[i].find_first_of('/') - 1));
						n[i - 1] = std::stoi(t[i].substr(t[i].find_last_of('/') + 1, t[i].size() - t[i].find_last_of('/') - 1));
					}
					if (g.size() == 0) {
						g = "default";
						addGroup(g);
					}
					groups[g].triangles.push_back(Triangle(glm::ivec3(v[0] - 1, v[1] - 1, v[3] - 1),
                                                           glm::ivec3(n[0] - 1, n[1] - 1, n[3] - 1),
                                                           glm::ivec3(u[0] - 1, u[1] - 1, u[3] - 1)));
					groups[g].triangles.push_back(Triangle(glm::ivec3(v[3] - 1, v[1] - 1, v[2] - 1),
                                                           glm::ivec3(n[3] - 1, n[1] - 1, n[2] - 1),
                                                           glm::ivec3(u[3] - 1, u[1] - 1, u[2] - 1)));
				}
				else if (t[0].size()) {
					int scan = sscanf(line.c_str(), "f %d/%d/%d %d/%d/%d %d/%d/%d", &v1, &t1, &n1, &v2, &t2, &n2, &v3, &t3, &n3);
					if (scan < 9) {
						scan = sscanf(line.c_str(), "f %d//%d %d//%d %d//%d", &v1, &n1, &v2, &n2, &v3, &n3);
						if (scan < 6) {
							scan = sscanf(line.c_str(), "f %d/%d %d/%d %d/%d", &v1, &t1, &v2, &t2, &v3, &t3);
							if (scan < 6) {
								LOG(ERROR) << "Failed to parse '" << line << "'.";
								throw std::runtime_error("");
							}
						}
					}
					if (g.size() == 0) {
						g = "default";
						addGroup(g);
					}
					groups[g].triangles.push_back(Triangle(glm::ivec3(v1 - 1, v2 - 1, v3 - 1),
                                                           glm::ivec3(n1 - 1, n2 - 1, n3 - 1),
                                                           glm::ivec3(t1 - 1, t2 - 1, t3 - 1)));
				}
			}
			else if (t[0] == "mtllib") {
				size_t found = filename.find_last_of("/");
				if (found == std::string::npos) readMTL(t[1]);
				else {
					readMTL(filename.substr(0, found + 1) + t[1]);
				}
			}
			else if (t[0] == "usemtl") {
				if (g.size() == 0) {
					g = "default";
					addGroup(g);
				}
				groups[g].materialIdx = t[1];
				if (materials.find(t[1]) == materials.end()) {
					LOG(ERROR) << "missing material " << t[1];
					throw std::runtime_error("");
				}
			}
			else if (t[0] == "g") {
				g = t[1];
				addGroup(g);
			}
			else if (t[0] == "s") {
				groups[g].s = t[1];
			}
			else {
				LOG(ERROR) << "Failed to parse '" << line << "'.";
				throw std::runtime_error("");
			}
		}
		myfile.close();
	}
	LOG(INFO) << "Finished loading '" << filename << "'.";
	LOG(TRACE) << vertices.size() << " vertices, "
	           << uv.size() << " texcoords, "
	           << normals.size() << " normals.";
}

void Model::readMTL(std::string filename) {
	std::string line;
	std::ifstream myfile(filename);
	int prev = materials.size();
	LOG(INFO) << "reading mtl file" << filename;
	if (myfile.is_open())
	{
		std::string mtl;
		while (getline(myfile, line)) {
			std::vector<std::string> t = split(line, ' ');
			if (t.size() == 0 || t[0] == "#" || t[0] == "\n");
			else if (t[0] == "newmtl") {
				mtl = t[1];
				materials[mtl];
			}
			else if (t[0] == "illum") materials[mtl].illum = std::stoi(t[1]);
			else if (t[0] == "Ka") materials[mtl].Ka = glm::vec3(std::stof(t[1]), std::stof(t[2]), std::stof(t[3]));
			else if (t[0] == "Kd") materials[mtl].Kd = glm::vec3(std::stof(t[1]), std::stof(t[2]), std::stof(t[3]));
			else if (t[0] == "Ks") materials[mtl].Ks = glm::vec3(std::stof(t[1]), std::stof(t[2]), std::stof(t[3]));
			else if (t[0] == "Ke") materials[mtl].Ke = glm::vec3(std::stof(t[1]), std::stof(t[2]), std::stof(t[3]));
			else if (t[0] == "Tf") materials[mtl].Tf = glm::vec3(std::stof(t[1]), std::stof(t[2]), std::stof(t[3]));
			else if (t[0] == "Ns") materials[mtl].Ns = std::stof(t[1]);
			else if (t[0] == "Ni") materials[mtl].Ni = std::stof(t[1]);
			else if (t[0] == "d") materials[mtl].d = std::stof(t[1]);
			else if (t[0] == "Tr") materials[mtl].Tr = std::stof(t[1]);
			/*else if (t2[0] == "map_Kd") {
				m.map_Kd = new gl::texture2D(t2[1], GL_UNSIGNED_BYTE);
			}*/
			else {
				LOG(ERROR) << t[0];
			}
		}
	}
	LOG(INFO) << "finished reading mtl file " << std::to_string(materials.size() - prev);
}

void Model::display() {
	if (drawLists.empty()) {
		CreateDrawingLists();
	}
	if (mode == G308_SHADE_POLYGON) {
		if (m_glGeomListPoly == 0) CreateGLPolyGeometry();
		glCallList(m_glGeomListPoly);
	}
	else if (mode == G308_SHADE_WIREFRAME) {
		if (m_glGeomListWire == 0) CreateGLWireGeometry();
		glCallList(m_glGeomListWire);
	}
	else {
		printf("Warning: Wrong Shading Mode. \n");
	}
}

void Model::useMTL(std::string mtl) {
	glMaterialfv(GL_FRONT, GL_AMBIENT, glm::value_ptr(materials[mtl].Ka));
	glMaterialfv(GL_FRONT, GL_DIFFUSE, glm::value_ptr(materials[mtl].Kd));
	glMaterialfv(GL_FRONT, GL_SPECULAR, glm::value_ptr(glm::vec4(materials[mtl].Ks, materials[mtl].Ns)));
	//glEnable(GL_TEXTURE_2D);
	//materials[mtl].map_Kd->bind(0);
	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
void Model::addToList(int v, int n, int u) {
	if (uv.size()>0) glTexCoord2f(uv[u].x, uv[u].y);
	glNormal3f(normals[n].x, normals[n].y, normals[n].z); //Add the normal
	glVertex3f(vertices[v].x, vertices[v].y, vertices[v].z); //Add the vertex
}
void Model::CreateDrawingLists() {
	if (!drawLists.empty()) {
		for each (std::pair<std::string,int> var in drawLists)
		{
			glDeleteLists(var.second, 1);
		}
		drawLists.clear();
	}
	for (auto& g : groups) {
		int l = glGenLists(1);
		glBegin(GL_TRIANGLES);
		for (Triangle t : g.second.triangles) {
			addToList(t.v[0], t.n[0], t.t[0]);
			addToList(t.v[1], t.n[1], t.t[1]);
			addToList(t.v[2], t.n[2], t.t[2]);
		}
		glEnd();
		drawLists.push_back(std::pair<std::string, int>(g.second.materialIdx, l));
	}
}<commit_msg>model now compiles<commit_after>#include <easylogging.h>

#include <glm/gtc/type_ptr.hpp>

#include "core/model.h"

#include <stdexcept>

std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    split(s, delim, elems);
    return elems;
}

void Model::addGroup(std::string g) {
	groups[g];
}
Model::Model(std::string filename) {
	std::string line;
	std::ifstream myfile(filename);
	int v1, v2, v3, n1, n2, n3, t1, t2, t3;
	std::string g;
	if (myfile.is_open())
	{
		while (getline(myfile, line))
		{
			//LOG(INFO) << line;
			if (line.size()<=1 || line[0] == '#') continue;
			std::vector<std::string> t = split(line, ' ');
			if (t[0] == "v" && t.size() == 4) {
				vertices.push_back(glm::vec3(std::stof(t[1]),
                                             std::stof(t[2]),
                                             std::stof(t[3])));
			}
			else if (t[0] == "vt" && t.size() == 4) {
				uv.push_back(glm::vec3(std::stof(t[1]),
                                       std::stof(t[2]),
                                       std::stof(t[3])));
			}
			else if (t[0] == "vt" && t.size() == 3) {
				uv.push_back(glm::vec3(std::stof(t[1]),
                                       std::stof(t[2]),
                                       0));
			}
			else if (t[0] == "vn" && t.size() == 4) {
				normals.push_back(glm::vec3(std::stof(t[1]),
                                            std::stof(t[2]),
                                            std::stof(t[3])));
			}
			else if (t[0] == "f") {
				if (t.size() == 5) {
					int v[4];
					int n[4];
					int u[4];
					for (size_t i = 1; i < t.size(); i++) {
						//LOG(INFO) << t[i];
						v[i-1] = std::stoi(t[i].substr(0, t[i].find_first_of('/')),nullptr);
						u[i - 1] = std::stoi(t[i].substr(t[i].find_first_of('/') + 1, t[i].find_last_of('/') - t[i].find_first_of('/') - 1));
						n[i - 1] = std::stoi(t[i].substr(t[i].find_last_of('/') + 1, t[i].size() - t[i].find_last_of('/') - 1));
					}
					if (g.size() == 0) {
						g = "default";
						addGroup(g);
					}
					groups[g].triangles.push_back(Triangle(glm::ivec3(v[0] - 1, v[1] - 1, v[3] - 1),
                                                           glm::ivec3(n[0] - 1, n[1] - 1, n[3] - 1),
                                                           glm::ivec3(u[0] - 1, u[1] - 1, u[3] - 1)));
					groups[g].triangles.push_back(Triangle(glm::ivec3(v[3] - 1, v[1] - 1, v[2] - 1),
                                                           glm::ivec3(n[3] - 1, n[1] - 1, n[2] - 1),
                                                           glm::ivec3(u[3] - 1, u[1] - 1, u[2] - 1)));
				}
				else if (t[0].size()) {
					int scan = sscanf(line.c_str(), "f %d/%d/%d %d/%d/%d %d/%d/%d", &v1, &t1, &n1, &v2, &t2, &n2, &v3, &t3, &n3);
					if (scan < 9) {
						scan = sscanf(line.c_str(), "f %d//%d %d//%d %d//%d", &v1, &n1, &v2, &n2, &v3, &n3);
						if (scan < 6) {
							scan = sscanf(line.c_str(), "f %d/%d %d/%d %d/%d", &v1, &t1, &v2, &t2, &v3, &t3);
							if (scan < 6) {
								LOG(ERROR) << "Failed to parse '" << line << "'.";
								throw std::runtime_error("");
							}
						}
					}
					if (g.size() == 0) {
						g = "default";
						addGroup(g);
					}
					groups[g].triangles.push_back(Triangle(glm::ivec3(v1 - 1, v2 - 1, v3 - 1),
                                                           glm::ivec3(n1 - 1, n2 - 1, n3 - 1),
                                                           glm::ivec3(t1 - 1, t2 - 1, t3 - 1)));
				}
			}
			else if (t[0] == "mtllib") {
				size_t found = filename.find_last_of("/");
				if (found == std::string::npos) readMTL(t[1]);
				else {
					readMTL(filename.substr(0, found + 1) + t[1]);
				}
			}
			else if (t[0] == "usemtl") {
				if (g.size() == 0) {
					g = "default";
					addGroup(g);
				}
				groups[g].materialIdx = t[1];
				if (materials.find(t[1]) == materials.end()) {
					LOG(ERROR) << "missing material " << t[1];
					throw std::runtime_error("");
				}
			}
			else if (t[0] == "g") {
				g = t[1];
				addGroup(g);
			}
			else if (t[0] == "s") {
				groups[g].s = t[1];
			}
			else {
				LOG(ERROR) << "Failed to parse '" << line << "'.";
				throw std::runtime_error("");
			}
		}
		myfile.close();
	}
	LOG(INFO) << "Finished loading '" << filename << "'.";
	LOG(TRACE) << vertices.size() << " vertices, "
	           << uv.size() << " texcoords, "
	           << normals.size() << " normals.";
}

void Model::readMTL(std::string filename) {
	std::string line;
	std::ifstream myfile(filename);
	int prev = materials.size();
	LOG(INFO) << "reading mtl file" << filename;
	if (myfile.is_open())
	{
		std::string mtl;
		while (getline(myfile, line)) {
			std::vector<std::string> t = split(line, ' ');
			if (t.size() == 0 || t[0] == "#" || t[0] == "\n");
			else if (t[0] == "newmtl") {
				mtl = t[1];
				materials[mtl];
			}
			else if (t[0] == "illum") materials[mtl].illum = std::stoi(t[1]);
			else if (t[0] == "Ka") materials[mtl].Ka = glm::vec3(std::stof(t[1]), std::stof(t[2]), std::stof(t[3]));
			else if (t[0] == "Kd") materials[mtl].Kd = glm::vec3(std::stof(t[1]), std::stof(t[2]), std::stof(t[3]));
			else if (t[0] == "Ks") materials[mtl].Ks = glm::vec3(std::stof(t[1]), std::stof(t[2]), std::stof(t[3]));
			else if (t[0] == "Ke") materials[mtl].Ke = glm::vec3(std::stof(t[1]), std::stof(t[2]), std::stof(t[3]));
			else if (t[0] == "Tf") materials[mtl].Tf = glm::vec3(std::stof(t[1]), std::stof(t[2]), std::stof(t[3]));
			else if (t[0] == "Ns") materials[mtl].Ns = std::stof(t[1]);
			else if (t[0] == "Ni") materials[mtl].Ni = std::stof(t[1]);
			else if (t[0] == "d") materials[mtl].d = std::stof(t[1]);
			else if (t[0] == "Tr") materials[mtl].Tr = std::stof(t[1]);
			/*else if (t2[0] == "map_Kd") {
				m.map_Kd = new gl::texture2D(t2[1], GL_UNSIGNED_BYTE);
			}*/
			else {
				LOG(ERROR) << t[0];
			}
		}
	}
	LOG(INFO) << "finished reading mtl file " << std::to_string(materials.size() - prev);
}

void Model::display() {
	if (drawLists.empty()) {
		CreateDrawingLists();
	}
	for each (std::pair<std::string, int> var in drawLists)
	{
		glCallList(var.second);
	}
}

void Model::useMTL(std::string mtl) {
	glMaterialfv(GL_FRONT, GL_AMBIENT, glm::value_ptr(materials[mtl].Ka));
	glMaterialfv(GL_FRONT, GL_DIFFUSE, glm::value_ptr(materials[mtl].Kd));
	glMaterialfv(GL_FRONT, GL_SPECULAR, glm::value_ptr(glm::vec4(materials[mtl].Ks, materials[mtl].Ns)));
	//glEnable(GL_TEXTURE_2D);
	//materials[mtl].map_Kd->bind(0);
	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
void Model::addToList(int v, int n, int u) {
	if (uv.size()>0) glTexCoord2f(uv[u].x, uv[u].y);
	glNormal3f(normals[n].x, normals[n].y, normals[n].z); //Add the normal
	glVertex3f(vertices[v].x, vertices[v].y, vertices[v].z); //Add the vertex
}
void Model::CreateDrawingLists() {
	if (!drawLists.empty()) {
		for each (std::pair<std::string,int> var in drawLists)
		{
			glDeleteLists(var.second, 1);
		}
		drawLists.clear();
	}
	for (auto& g : groups) {
		int l = glGenLists(1);
		glBegin(GL_TRIANGLES);
		for (Triangle t : g.second.triangles) {
			addToList(t.v[0], t.n[0], t.t[0]);
			addToList(t.v[1], t.n[1], t.t[1]);
			addToList(t.v[2], t.n[2], t.t[2]);
		}
		glEnd();
		drawLists.push_back(std::pair<std::string, int>(g.second.materialIdx, l));
	}
}<|endoftext|>


<commit_before>/* -*-  mode: c++; c-default-style: "google"; indent-tabs-mode: nil -*- */
/* -------------------------------------------------------------------------
ATS

License: see $AMANZI_DIR/COPYRIGHT
Author: ??

Effectively stolen from Amanzi, with few modifications.
------------------------------------------------------------------------- */

#include <iostream>
#include <cstdlib>
#include <cmath>

#include "Exodus_readers.hh"
#include "Parallel_Exodus_file.hh"

#include <Epetra_Comm.h>
#include <Epetra_MpiComm.h>
#include "Epetra_SerialComm.h"

#include "Teuchos_ParameterList.hpp"
#include "Teuchos_XMLParameterListHelpers.hpp"
#include "Teuchos_CommandLineProcessor.hpp"
#include "Teuchos_GlobalMPISession.hpp"
#include "Teuchos_oblackholestream.hpp"
#include "Teuchos_Version.hpp"
#include "Teuchos_DefaultMpiComm.hpp"
#include "Teuchos_StrUtils.hpp"
#include "Teuchos_TimeMonitor.hpp"

#include "MeshAudit.hh"
#include "MeshFactory.hh"
#include "Domain.hh"
#include "GeometricModel.hh"
#include "coordinator.hh"
#include "State.hh"

#include "errors.hh"
#include "exceptions.hh"

#include "amanzi_unstructured_grid_simulation_driver.hh"
#include "InputParserIS.hh"
#include "global_verbosity.hh"

Amanzi::Simulator::ReturnType AmanziUnstructuredGridSimulationDriver::Run(
        const MPI_Comm& mpi_comm, Teuchos::ParameterList& input_parameter_list) {

  using Teuchos::OSTab;
  setDefaultVerbLevel(Amanzi::VerbosityLevel::level_);
  Teuchos::EVerbosityLevel verbLevel = getVerbLevel();
  Teuchos::RCP<Teuchos::FancyOStream> out = getOStream();
  OSTab tab = getOSTab(); // This sets the line prefix and adds one tab

#ifdef HAVE_MPI
  Epetra_MpiComm *comm = new Epetra_MpiComm(mpi_comm);
#else
  Epetra_SerialComm *comm = new Epetra_SerialComm();
#endif

  int rank;
  MPI_Comm_rank(mpi_comm,&rank);
  int size;
  MPI_Comm_size(mpi_comm,&size);

  Teuchos::ParameterList params_copy;
  bool native = input_parameter_list.get<bool>("Native Unstructured Input",false);
  ASSERT(native);
  params_copy = input_parameter_list;

  if(out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW,true)) {
    // print parameter list
    *out << "======================> dumping parameter list <======================" <<
      std::endl;
    Teuchos::writeParameterListToXmlOStream(params_copy, *out);
    *out << "======================> done dumping parameter list. <================" <<
      std::endl;
  }

  // ------  domain and geometric model  ------
  Teuchos::ParameterList domain_params = params_copy.sublist("Domain");
  unsigned int spdim = domain_params.get<int>("Spatial Dimension");
  Amanzi::AmanziGeometry::Domain *simdomain_ptr = new Amanzi::AmanziGeometry::Domain(spdim);

  // Under the simulation domain we have different geometric
  // models. We can also have free geometric regions not associated
  // with a geometric model.

  // For now create one geometric model from all the regions in the spec
  Teuchos::ParameterList reg_params = params_copy.sublist("Regions");

  Amanzi::AmanziGeometry::GeometricModelPtr
    geom_model_ptr( new Amanzi::AmanziGeometry::GeometricModel(spdim, reg_params, comm) );

  // Add the geometric model to the domain
  simdomain_ptr->Add_Geometric_Model(geom_model_ptr);

  // If we had geometric models and free regions coexisting then we would
  // create the free regions here and add them to the simulation domain
  // Nothing to do for now

  // ------ mesh ------
  Amanzi::AmanziMesh::MeshFactory factory(comm);
  Teuchos::RCP<Amanzi::AmanziMesh::Mesh> mesh;

  // select the mesh framework
  Teuchos::ParameterList mesh_plist = params_copy.sublist("Mesh");

  int ierr = 0;
  try {
    std::string framework = mesh_plist.get<string>("Framework");
    Amanzi::AmanziMesh::FrameworkPreference prefs(factory.preference());
    if (framework == Amanzi::AmanziMesh::framework_name(Amanzi::AmanziMesh::Simple)) {
      prefs.clear(); prefs.push_back(Amanzi::AmanziMesh::Simple);
    } else if (framework == Amanzi::AmanziMesh::framework_name(Amanzi::AmanziMesh::MOAB)) {
      prefs.clear(); prefs.push_back(Amanzi::AmanziMesh::MOAB);
    } else if (framework == Amanzi::AmanziMesh::framework_name(Amanzi::AmanziMesh::STKMESH)) {
      prefs.clear(); prefs.push_back(Amanzi::AmanziMesh::STKMESH);
    } else if (framework == Amanzi::AmanziMesh::framework_name(Amanzi::AmanziMesh::MSTK)) {
      prefs.clear(); prefs.push_back(Amanzi::AmanziMesh::MSTK);
    } else if (framework == "") {
      // do nothing
    } else {
      std::string s(framework);
      s += ": specified mesh framework preference not understood";
      amanzi_throw(Errors::Message(s));
    }
    factory.preference(prefs);
  } catch (const Teuchos::Exceptions::InvalidParameterName& e) {
    // do nothing, this means that the "Framework" parameter was not in the input
  } catch (const std::exception& e) {
    std::cout << rank << ": error: " << e.what() << std::endl;
    ierr++;
  }

  int aerr = 0;
  comm->SumAll(&ierr, &aerr, 1);
  if (aerr > 0) {
    return Amanzi::Simulator::FAIL;
  }

  // Create the mesh
  std::string file(""), format("");

  if (mesh_plist.isSublist("Read Mesh File")) {
    // try to read mesh from file
    Teuchos::ParameterList read_params = mesh_plist.sublist("Read Mesh File");

    if (read_params.isParameter("File")) {
      file = read_params.get<string>("File");
    } else {
      std::cerr << "Must specify File parameter for Read option under Mesh" << std::endl;
      throw std::exception();
    }

    if (read_params.isParameter("Format")) {
      // Is the format one that we can read?
      format = read_params.get<string>("Format");
      if (format != "Exodus II") {
        std::cerr << "Can only read files in Exodus II format" << std::endl;
        throw std::exception();
      }
    } else {
      std::cerr << "Must specify Format parameter for Read option under Mesh" << std::endl;
      throw std::exception();
    }

    if (!file.empty()) {
      ierr = 0;
      try {
        // create the mesh from the file
        Teuchos::RCP<Teuchos::Time> volmeshtime = Teuchos::TimeMonitor::getNewCounter("volume mesh creation");
        Teuchos::TimeMonitor timer(*volmeshtime);
        mesh = factory.create(file, geom_model_ptr);
      } catch (const std::exception& e) {
        std::cerr << rank << ": error: " << e.what() << std::endl;
        ierr++;
      }

      comm->SumAll(&ierr, &aerr, 1);
      if (aerr > 0) return Amanzi::Simulator::FAIL;
    }
  } else if (mesh_plist.isSublist("Generate Mesh")) {
    // try to generate the mesh from data in plist
    Teuchos::ParameterList gen_params = mesh_plist.sublist("Generate Mesh");
    ierr = 0;

    try {
      mesh = factory.create(gen_params, geom_model_ptr);
    } catch (const std::exception& e) {
      std::cerr << rank << ": error: " << e.what() << std::endl;
      ierr++;
    }

    comm->SumAll(&ierr, &aerr, 1);
    if (aerr > 0) return Amanzi::Simulator::FAIL;

  } else {
    std::cerr << rank << ": error: "
              << "Neither Read nor Generate options specified for mesh" << std::endl;
    throw std::exception();
  }
  ASSERT(!mesh.is_null());

  // mesh verification
  bool expert_params_specified = mesh_plist.isSublist("Expert");
  if (expert_params_specified) {
    Teuchos::ParameterList expert_mesh_params = mesh_plist.sublist("Expert");

    bool verify_mesh_param = expert_mesh_params.isParameter("Verify Mesh");
    if (verify_mesh_param) {
      bool verify = expert_mesh_params.get<bool>("Verify Mesh");
      if (verify) {
        std::cerr << "Verifying mesh with Mesh Audit..." << std::endl;
        if (size == 1) {
          Amanzi::MeshAudit mesh_auditor(mesh);
          int status = mesh_auditor.Verify();
          if (status == 0) {
            std::cout << "Mesh Audit confirms that mesh is ok" << std::endl;
          } else {
            std::cout << "Mesh Audit could not verify correctness of mesh" << std::endl;
            return Amanzi::Simulator::FAIL;
          }
        } else {
          std::ostringstream ofile;
          ofile << "mesh_audit_" << std::setfill('0') << std::setw(4) << rank << ".txt";
          std::ofstream ofs(ofile.str().c_str());
          if (rank == 0)
            std::cerr << "Writing Mesh Audit output to " << ofile.str() << ", etc." << std::endl;

          ierr = 0;
          Amanzi::MeshAudit mesh_auditor(mesh, ofs);
          int status = mesh_auditor.Verify();        // check the mesh
          if (status != 0) ierr++;

          comm->SumAll(&ierr, &aerr, 1);
          if (aerr == 0) {
            std::cerr << "Mesh Audit confirms that mesh is ok" << std::endl;
          } else {
            if (rank == 0)
              std::cerr << "Mesh Audit could not verify correctness of mesh" << std::endl;
            return Amanzi::Simulator::FAIL;
          }
        }
      }  // if verify
    }  // if verify_mesh_param
  }  // If expert_params_specified

  // Create the surface mesh if needed
  Teuchos::RCP<Amanzi::AmanziMesh::Mesh> surface_mesh = Teuchos::null;
  Teuchos::RCP<Amanzi::AmanziMesh::Mesh> surface3D_mesh = Teuchos::null;
  if (mesh_plist.isSublist("Surface Mesh")) {
    Teuchos::ParameterList surface_plist = mesh_plist.sublist("Surface Mesh");

    std::vector<std::string> setnames;
    if (surface_plist.isParameter("surface sideset name")) {
      setnames.push_back(surface_plist.get<std::string>("surface sideset name"));
    } else if (surface_plist.isParameter("surface sideset names")) {
      setnames = surface_plist.get<Teuchos::Array<std::string> >("surface sideset names").toVector();
    } else {
      Errors::Message message("Surface mesh ParameterList needs sideset names.");
      Exceptions::amanzi_throw(message);
    }

    if (mesh->cell_dimension() == 3) {
      surface3D_mesh = factory.create(&*mesh,setnames,Amanzi::AmanziMesh::FACE,false,false);
      surface_mesh = factory.create(&*mesh,setnames,Amanzi::AmanziMesh::FACE,true,false);
    } else {
      surface3D_mesh = mesh;
      surface_mesh = factory.create(&*mesh,setnames,Amanzi::AmanziMesh::CELL,true,false);
    }
  }

  Teuchos::TimeMonitor::summarize();
  Teuchos::TimeMonitor::zeroOutTimers();

  // Create the state.
  Teuchos::ParameterList state_plist = params_copy.sublist("state");
  Teuchos::RCP<Amanzi::State> S = Teuchos::rcp(new Amanzi::State(state_plist));
  S->RegisterDomainMesh(mesh);
  if (surface3D_mesh != Teuchos::null) S->RegisterMesh("surface_3d", surface3D_mesh);
  if (surface_mesh != Teuchos::null) S->RegisterMesh("surface", surface_mesh);

  // create the top level Coordinator
  Amanzi::Coordinator coordinator(params_copy, S, comm);

  // run the simulation
  coordinator.cycle_driver();

  mesh.reset();
  delete comm;
  delete simdomain_ptr;
  delete geom_model_ptr;
  return Amanzi::Simulator::SUCCESS;
}

<commit_msg>adds mesh-audit for surface mesh<commit_after>/* -*-  mode: c++; c-default-style: "google"; indent-tabs-mode: nil -*- */
/* -------------------------------------------------------------------------
ATS

License: see $AMANZI_DIR/COPYRIGHT
Author: ??

Effectively stolen from Amanzi, with few modifications.
------------------------------------------------------------------------- */

#include <iostream>
#include <cstdlib>
#include <cmath>

#include "Exodus_readers.hh"
#include "Parallel_Exodus_file.hh"

#include <Epetra_Comm.h>
#include <Epetra_MpiComm.h>
#include "Epetra_SerialComm.h"

#include "Teuchos_ParameterList.hpp"
#include "Teuchos_XMLParameterListHelpers.hpp"
#include "Teuchos_CommandLineProcessor.hpp"
#include "Teuchos_GlobalMPISession.hpp"
#include "Teuchos_oblackholestream.hpp"
#include "Teuchos_Version.hpp"
#include "Teuchos_DefaultMpiComm.hpp"
#include "Teuchos_StrUtils.hpp"
#include "Teuchos_TimeMonitor.hpp"

#include "MeshAudit.hh"
#include "MeshFactory.hh"
#include "Domain.hh"
#include "GeometricModel.hh"
#include "coordinator.hh"
#include "State.hh"

#include "errors.hh"
#include "exceptions.hh"

#include "amanzi_unstructured_grid_simulation_driver.hh"
#include "InputParserIS.hh"
#include "global_verbosity.hh"

Amanzi::Simulator::ReturnType AmanziUnstructuredGridSimulationDriver::Run(
        const MPI_Comm& mpi_comm, Teuchos::ParameterList& input_parameter_list) {

  using Teuchos::OSTab;
  setDefaultVerbLevel(Amanzi::VerbosityLevel::level_);
  Teuchos::EVerbosityLevel verbLevel = getVerbLevel();
  Teuchos::RCP<Teuchos::FancyOStream> out = getOStream();
  OSTab tab = getOSTab(); // This sets the line prefix and adds one tab

#ifdef HAVE_MPI
  Epetra_MpiComm *comm = new Epetra_MpiComm(mpi_comm);
#else
  Epetra_SerialComm *comm = new Epetra_SerialComm();
#endif

  int rank;
  MPI_Comm_rank(mpi_comm,&rank);
  int size;
  MPI_Comm_size(mpi_comm,&size);

  Teuchos::ParameterList params_copy;
  bool native = input_parameter_list.get<bool>("Native Unstructured Input",false);
  ASSERT(native);
  params_copy = input_parameter_list;

  if(out.get() && includesVerbLevel(verbLevel,Teuchos::VERB_LOW,true)) {
    // print parameter list
    *out << "======================> dumping parameter list <======================" <<
      std::endl;
    Teuchos::writeParameterListToXmlOStream(params_copy, *out);
    *out << "======================> done dumping parameter list. <================" <<
      std::endl;
  }

  // ------  domain and geometric model  ------
  Teuchos::ParameterList domain_params = params_copy.sublist("Domain");
  unsigned int spdim = domain_params.get<int>("Spatial Dimension");
  Amanzi::AmanziGeometry::Domain *simdomain_ptr = new Amanzi::AmanziGeometry::Domain(spdim);

  // Under the simulation domain we have different geometric
  // models. We can also have free geometric regions not associated
  // with a geometric model.

  // For now create one geometric model from all the regions in the spec
  Teuchos::ParameterList reg_params = params_copy.sublist("Regions");

  Amanzi::AmanziGeometry::GeometricModelPtr
    geom_model_ptr( new Amanzi::AmanziGeometry::GeometricModel(spdim, reg_params, comm) );

  // Add the geometric model to the domain
  simdomain_ptr->Add_Geometric_Model(geom_model_ptr);

  // If we had geometric models and free regions coexisting then we would
  // create the free regions here and add them to the simulation domain
  // Nothing to do for now

  // ------ mesh ------
  Amanzi::AmanziMesh::MeshFactory factory(comm);
  Teuchos::RCP<Amanzi::AmanziMesh::Mesh> mesh;

  // select the mesh framework
  Teuchos::ParameterList mesh_plist = params_copy.sublist("Mesh");

  int ierr = 0;
  try {
    std::string framework = mesh_plist.get<string>("Framework");
    Amanzi::AmanziMesh::FrameworkPreference prefs(factory.preference());
    if (framework == Amanzi::AmanziMesh::framework_name(Amanzi::AmanziMesh::Simple)) {
      prefs.clear(); prefs.push_back(Amanzi::AmanziMesh::Simple);
    } else if (framework == Amanzi::AmanziMesh::framework_name(Amanzi::AmanziMesh::MOAB)) {
      prefs.clear(); prefs.push_back(Amanzi::AmanziMesh::MOAB);
    } else if (framework == Amanzi::AmanziMesh::framework_name(Amanzi::AmanziMesh::STKMESH)) {
      prefs.clear(); prefs.push_back(Amanzi::AmanziMesh::STKMESH);
    } else if (framework == Amanzi::AmanziMesh::framework_name(Amanzi::AmanziMesh::MSTK)) {
      prefs.clear(); prefs.push_back(Amanzi::AmanziMesh::MSTK);
    } else if (framework == "") {
      // do nothing
    } else {
      std::string s(framework);
      s += ": specified mesh framework preference not understood";
      amanzi_throw(Errors::Message(s));
    }
    factory.preference(prefs);
  } catch (const Teuchos::Exceptions::InvalidParameterName& e) {
    // do nothing, this means that the "Framework" parameter was not in the input
  } catch (const std::exception& e) {
    std::cout << rank << ": error: " << e.what() << std::endl;
    ierr++;
  }

  int aerr = 0;
  comm->SumAll(&ierr, &aerr, 1);
  if (aerr > 0) {
    return Amanzi::Simulator::FAIL;
  }

  // Create the mesh
  std::string file(""), format("");

  if (mesh_plist.isSublist("Read Mesh File")) {
    // try to read mesh from file
    Teuchos::ParameterList read_params = mesh_plist.sublist("Read Mesh File");

    if (read_params.isParameter("File")) {
      file = read_params.get<string>("File");
    } else {
      std::cerr << "Must specify File parameter for Read option under Mesh" << std::endl;
      throw std::exception();
    }

    if (read_params.isParameter("Format")) {
      // Is the format one that we can read?
      format = read_params.get<string>("Format");
      if (format != "Exodus II") {
        std::cerr << "Can only read files in Exodus II format" << std::endl;
        throw std::exception();
      }
    } else {
      std::cerr << "Must specify Format parameter for Read option under Mesh" << std::endl;
      throw std::exception();
    }

    if (!file.empty()) {
      ierr = 0;
      try {
        // create the mesh from the file
        Teuchos::RCP<Teuchos::Time> volmeshtime = Teuchos::TimeMonitor::getNewCounter("volume mesh creation");
        Teuchos::TimeMonitor timer(*volmeshtime);
        mesh = factory.create(file, geom_model_ptr);
      } catch (const std::exception& e) {
        std::cerr << rank << ": error: " << e.what() << std::endl;
        ierr++;
      }

      comm->SumAll(&ierr, &aerr, 1);
      if (aerr > 0) return Amanzi::Simulator::FAIL;
    }
  } else if (mesh_plist.isSublist("Generate Mesh")) {
    // try to generate the mesh from data in plist
    Teuchos::ParameterList gen_params = mesh_plist.sublist("Generate Mesh");
    ierr = 0;

    try {
      mesh = factory.create(gen_params, geom_model_ptr);
    } catch (const std::exception& e) {
      std::cerr << rank << ": error: " << e.what() << std::endl;
      ierr++;
    }

    comm->SumAll(&ierr, &aerr, 1);
    if (aerr > 0) return Amanzi::Simulator::FAIL;

  } else {
    std::cerr << rank << ": error: "
              << "Neither Read nor Generate options specified for mesh" << std::endl;
    throw std::exception();
  }
  ASSERT(!mesh.is_null());

  // mesh verification
  bool expert_params_specified = mesh_plist.isSublist("Expert");
  if (expert_params_specified) {
    Teuchos::ParameterList expert_mesh_params = mesh_plist.sublist("Expert");

    bool verify_mesh_param = expert_mesh_params.isParameter("Verify Mesh");
    if (verify_mesh_param) {
      bool verify = expert_mesh_params.get<bool>("Verify Mesh");
      if (verify) {
        std::cerr << "Verifying mesh with Mesh Audit..." << std::endl;
        if (size == 1) {
          Amanzi::MeshAudit mesh_auditor(mesh);
          int status = mesh_auditor.Verify();
          if (status == 0) {
            std::cout << "Mesh Audit confirms that mesh is ok" << std::endl;
          } else {
            std::cout << "Mesh Audit could not verify correctness of mesh" << std::endl;
            return Amanzi::Simulator::FAIL;
          }
        } else {
          std::ostringstream ofile;
          ofile << "mesh_audit_" << std::setfill('0') << std::setw(4) << rank << ".txt";
          std::ofstream ofs(ofile.str().c_str());
          if (rank == 0)
            std::cerr << "Writing Mesh Audit output to " << ofile.str() << ", etc." << std::endl;

          ierr = 0;
          Amanzi::MeshAudit mesh_auditor(mesh, ofs);
          int status = mesh_auditor.Verify();        // check the mesh
          if (status != 0) ierr++;

          comm->SumAll(&ierr, &aerr, 1);
          if (aerr == 0) {
            std::cerr << "Mesh Audit confirms that mesh is ok" << std::endl;
          } else {
            if (rank == 0)
              std::cerr << "Mesh Audit could not verify correctness of mesh" << std::endl;
            return Amanzi::Simulator::FAIL;
          }
        }
      }  // if verify
    }  // if verify_mesh_param
  }  // If expert_params_specified

  // Create the surface mesh if needed
  Teuchos::RCP<Amanzi::AmanziMesh::Mesh> surface_mesh = Teuchos::null;
  Teuchos::RCP<Amanzi::AmanziMesh::Mesh> surface3D_mesh = Teuchos::null;
  if (mesh_plist.isSublist("Surface Mesh")) {
    Teuchos::ParameterList surface_plist = mesh_plist.sublist("Surface Mesh");

    std::vector<std::string> setnames;
    if (surface_plist.isParameter("surface sideset name")) {
      setnames.push_back(surface_plist.get<std::string>("surface sideset name"));
    } else if (surface_plist.isParameter("surface sideset names")) {
      setnames = surface_plist.get<Teuchos::Array<std::string> >("surface sideset names").toVector();
    } else {
      Errors::Message message("Surface mesh ParameterList needs sideset names.");
      Exceptions::amanzi_throw(message);
    }

    if (mesh->cell_dimension() == 3) {
      surface3D_mesh = factory.create(&*mesh,setnames,Amanzi::AmanziMesh::FACE,false,false);
      surface_mesh = factory.create(&*mesh,setnames,Amanzi::AmanziMesh::FACE,true,false);
    } else {
      surface3D_mesh = mesh;
      surface_mesh = factory.create(&*mesh,setnames,Amanzi::AmanziMesh::CELL,true,false);
    }

    bool surf_expert_params_specified = surface_plist.isSublist("Expert");
    if (surf_expert_params_specified) {
      Teuchos::ParameterList surf_expert_mesh_params = surface_plist.sublist("Expert");
      bool verify_surf_mesh_param = surf_expert_mesh_params.isParameter("Verify Mesh");
      if (verify_surf_mesh_param) {
        bool verify = surf_expert_mesh_params.get<bool>("Verify Mesh");
        if (verify) {
          std::cerr << "Verifying surface mesh with Mesh Audit..." << std::endl;
          if (size == 1) {
            Amanzi::MeshAudit surf_mesh_auditor(surface_mesh);
            int status = surf_mesh_auditor.Verify();
            if (status == 0) {
              std::cout << "Mesh Audit confirms that surface mesh is ok" << std::endl;
            } else {
              std::cout << "Mesh Audit could not verify correctness of surface mesh" << std::endl;
              return Amanzi::Simulator::FAIL;
            }
          } else {
            std::ostringstream ofile;
            ofile << "surf_mesh_audit_" << std::setfill('0') << std::setw(4) << rank << ".txt";
            std::ofstream ofs(ofile.str().c_str());
            if (rank == 0)
              std::cerr << "Writing Surface Mesh Audit output to " << ofile.str() << ", etc." << std::endl;

            ierr = 0;
            Amanzi::MeshAudit surf_mesh_auditor(mesh, ofs);
            int status = surf_mesh_auditor.Verify();        // check the mesh
            if (status != 0) ierr++;

            comm->SumAll(&ierr, &aerr, 1);
            if (aerr == 0) {
              std::cerr << "Surface Mesh Audit confirms that mesh is ok" << std::endl;
            } else {
              if (rank == 0)
                std::cerr << "Surface Mesh Audit could not verify correctness of mesh" << std::endl;
              return Amanzi::Simulator::FAIL;
            }
          }
        }  // if verify
      }  // if verify_mesh_param
    }  // If expert_params_specified
  }

  Teuchos::TimeMonitor::summarize();
  Teuchos::TimeMonitor::zeroOutTimers();

  // Create the state.
  Teuchos::ParameterList state_plist = params_copy.sublist("state");
  Teuchos::RCP<Amanzi::State> S = Teuchos::rcp(new Amanzi::State(state_plist));
  S->RegisterDomainMesh(mesh);
  if (surface3D_mesh != Teuchos::null) S->RegisterMesh("surface_3d", surface3D_mesh);
  if (surface_mesh != Teuchos::null) S->RegisterMesh("surface", surface_mesh);

  // create the top level Coordinator
  Amanzi::Coordinator coordinator(params_copy, S, comm);

  // run the simulation
  coordinator.cycle_driver();

  mesh.reset();
  delete comm;
  delete simdomain_ptr;
  delete geom_model_ptr;
  return Amanzi::Simulator::SUCCESS;
}

<|endoftext|>


<commit_before>/*
 * Copyright 2010 Alex Graveley
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "EventMachine.hh"

#include <sstream>
#include <png.h>

EventMask::EventMask(string mask)
{
	istringstream iss(mask, istringstream::in);
	string word;
	while(iss >> word) {
		names.push_back(word);
	}
}

bool
EventMask::stateMatch(State *state)
{
	vector<string>::iterator i;
	for (i = names.begin(); i != names.end(); i++) {
		if (!state->getDigitalIn((*i).c_str())) {
			return false;
		}
	}
	return true;
}

EventScript::~EventScript()
{
	for (uint y=0; y < info->height; y++) {
		free(data[y]);
	}
#ifndef OSX
	png_read_destroy(png, info, NULL);
#endif
}

uint
EventScript::get_frames()
{
	return info->height;
}

bool
EventScript::load(string script)
{
	/* open file and test for it being a png */
	FILE *fp = fopen(script.c_str(), "rb");
	if (!fp) {
		fprintf(stderr, "Script %s could not be opened for reading", script.c_str());
		return false;
	}

	/* initialize stuff */
	png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	info = png_create_info_struct(png);

	png_init_io(png, fp);
	png_read_info(png, info);
	png_read_update_info(png, info);

        if (info->width != 58) {
		fprintf(stderr, "Script %s is not the correct width (expected 58, got %lu).\n",
                        script.c_str(), info->width);
#ifndef OSX
                png_read_destroy(png, info, NULL);
#endif
                fclose(fp);
		return false;
        }

	data = (png_bytepp) malloc(sizeof(png_bytep) * info->height);
	for (uint y=0; y < info->height; y++) {
		data[y] = (png_byte*) malloc(info->rowbytes);
	}
	png_read_image(png, data);

	fclose(fp);
	return true;
}

bool
EventScript::update(State *state,
		    uint frame,
		    vector<string> lowerLedNames,
		    vector<string> axonLedNames,
		    vector<string> upperLedNames,
		    vector<string> digitalNames)
{
	// XXX: constify offsets
	unsigned int x=0;
	unsigned int y=frame;

	if (y >= info->height) {
		fprintf(stderr, "Frame %d greater than PNG height %lu\n",
			frame, info->height);
		return false;
	}
	png_byte* row = data[y];

	vector<string>::iterator i = axonLedNames.begin();
	x = 0; //axon LED's start at pixel 0
	for (i = axonLedNames.begin(); i != axonLedNames.end(); i++) {
		png_byte* ptr = &(row[x*3]); //get pixel rgb
		//fprintf(stderr, "Pixel [x: %d, y: %d] R:%d G:%d B:%d\n",
		//	x, y, ptr[0], ptr[1], ptr[2]);
		state->setLightOut(i->c_str(), ptr[0], ptr[1], ptr[2]);
		//printf("%d %d %d | ", ptr[0], ptr[1], ptr[2]);
		x++;
	}

	i = upperLedNames.begin();
	x = 10; //upper soma LED's start at pixel 10
	for (i = upperLedNames.begin(); i != upperLedNames.end(); i++) {
		png_byte* ptr = &(row[x*3]); //get pixel rgb
		state->setLightOut(i->c_str(), ptr[0], ptr[1], ptr[2]);
		x++;
	}

	i = lowerLedNames.begin();
	x = 40; //lower soma LED's start at pixel 40
	for (i = lowerLedNames.begin(); i != lowerLedNames.end(); i++) {
		png_byte* ptr = &(row[x*3]); //get pixel rgb
		state->setLightOut(i->c_str(), ptr[0], ptr[1], ptr[2]);
		x++;
	}

	i = digitalNames.begin();
	x = 50; //digital poofers start at pixel 50
	for (i = digitalNames.begin(); i != digitalNames.end(); i++) {
		png_byte* ptr = &(row[x*3]); //get pixel rgb
		state->setDigitalOut(i->c_str(), ptr[0] + ptr[1] + ptr[2] == 0);
		x++;
	}

	return y < info->height - 1;
}

bool
EventMachine::addScript(string mask, string script)
{
	EventScript *es = scriptData[script];
	if (!es) {
		// load script file, add with name to scriptData
		es = new EventScript();
		if (!es->load(script)) {
			delete es;
			fprintf(stderr, "Failed to load script '%s'\n", script.c_str());
			return false;
		}
	}

	scriptMasks.push_back(pair<EventMask, string>(EventMask(mask), script));
	scriptData[script] = es;

	fprintf(stderr, "Added script '%s' with event mask '%s'\n",
		script.c_str(), mask.c_str());

	return true;
}

void
EventMachine::update(State *state,
		     vector<string> lowerLedNames,
		     vector<string> axonLedNames,
		     vector<string> upperLedNames,
		     vector<string> digitalNames)
{
	for (vector< pair<EventMask, string> >::iterator i = scriptMasks.begin();
	     i != scriptMasks.end(); i++) {
		if (i->first.stateMatch(state)) {
			//fprintf(stderr, "Event state matches for script: %s\n",
			//	i->second.c_str());
			EventScript *data = scriptData[i->second];
			bool isRunning = false;
			vector< pair<EventScript*, uint> >::iterator i2;
			for (i2 = scriptStates.begin(); i2 != scriptStates.end(); i2++) {
				if (data == i2->first) {
					//fprintf(stderr, "Script %p already running.\n",
					//	i2->first);
					isRunning = true;
				}
			}

			if (!isRunning) {
				fprintf(stderr, "Restarting script '%s'.\n",
				i->second.c_str());
				scriptStates.push_back(pair<EventScript *, uint>(data, 0));
			}
	      }
	}

	vector< pair<EventScript*, uint> > nextStates;
	for (vector< pair<EventScript*, uint> >::iterator i2 = scriptStates.begin();
	     i2 != scriptStates.end(); i2++) {
		// Call Ben's event updating for the row at index i2->second.
		EventScript *data = i2->first;
		uint frame = i2->second;

		if (!data) {
			fprintf(stderr, "Invalid script data!\n");
			continue;
		}

		if (data->update(state, frame, lowerLedNames, axonLedNames,
				 upperLedNames, digitalNames)) {
			//fprintf(stderr, "Advancing to frame %d of script %p\n", frame, data);
			nextStates.push_back(pair<EventScript*, uint>(data, frame + 1));
		}
	}
	scriptStates = nextStates;
}

bool
EventMachine::parseEvent(xmlNodePtr node)
{
	bool ret = false;
	xmlChar *maskStr = xmlGetProp(node, (const xmlChar *)"mask");
	xmlChar *scriptStr = xmlGetProp(node, (const xmlChar *)"script");

	if (maskStr == NULL) {
		fprintf(stderr, "%s has no mask\n", node->name);
		goto err;
	}
	if (scriptStr == NULL) {
		fprintf(stderr, "%s has no script\n", node->name);
		goto err;
	}

	ret = addScript((char *)maskStr, (char *)scriptStr);

err:
	xmlFree(maskStr);
	xmlFree(scriptStr);
	return ret;
}

bool
EventMachine::loadConfig(const char *fileName)
{
	xmlDocPtr doc;
	xmlNodePtr cur;
	xmlNodePtr child;
	bool ret = true;

	doc = xmlParseFile(fileName);

	if (doc == NULL) {
		fprintf(stderr, "Document %s not parsed successfully\n",
			fileName);
		return false;
	}

	cur = xmlDocGetRootElement(doc);
	if (cur == NULL) {
		fprintf(stderr, "empty doc\n");
		return false;
	}

	if (xmlStrcmp(cur->name, (const xmlChar *)"config")){
		fprintf(stderr, "config file does not start with config element\n");
		goto err0;
	}

	for (child = cur->xmlChildrenNode;
	     child != NULL;
	     child = child->next) {
		if (!xmlStrcmp(child->name, (const xmlChar*)"event")) {
			ret = parseEvent(child);
			if (!ret)
				goto err0;
		}
	}

err0:
	xmlFreeDoc(doc);
	return ret;
}
<commit_msg>make black the "transparent" color<commit_after>/*
 * Copyright 2010 Alex Graveley
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "EventMachine.hh"

#include <sstream>
#include <png.h>

EventMask::EventMask(string mask)
{
	istringstream iss(mask, istringstream::in);
	string word;
	while(iss >> word) {
		names.push_back(word);
	}
}

bool
EventMask::stateMatch(State *state)
{
	vector<string>::iterator i;
	for (i = names.begin(); i != names.end(); i++) {
		if (!state->getDigitalIn((*i).c_str())) {
			return false;
		}
	}
	return true;
}

EventScript::~EventScript()
{
	for (uint y=0; y < info->height; y++) {
		free(data[y]);
	}
#ifndef OSX
	png_read_destroy(png, info, NULL);
#endif
}

uint
EventScript::get_frames()
{
	return info->height;
}

bool
EventScript::load(string script)
{
	/* open file and test for it being a png */
	FILE *fp = fopen(script.c_str(), "rb");
	if (!fp) {
		fprintf(stderr, "Script %s could not be opened for reading", script.c_str());
		return false;
	}

	/* initialize stuff */
	png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	info = png_create_info_struct(png);

	png_init_io(png, fp);
	png_read_info(png, info);
	png_read_update_info(png, info);

        if (info->width != 58) {
		fprintf(stderr, "Script %s is not the correct width (expected 58, got %lu).\n",
                        script.c_str(), info->width);
#ifndef OSX
                png_read_destroy(png, info, NULL);
#endif
                fclose(fp);
		return false;
        }

	data = (png_bytepp) malloc(sizeof(png_bytep) * info->height);
	for (uint y=0; y < info->height; y++) {
		data[y] = (png_byte*) malloc(info->rowbytes);
	}
	png_read_image(png, data);

	fclose(fp);
	return true;
}

bool
EventScript::update(State *state,
		    uint frame,
		    vector<string> lowerLedNames,
		    vector<string> axonLedNames,
		    vector<string> upperLedNames,
		    vector<string> digitalNames)
{
	// XXX: constify offsets
	unsigned int x=0;
	unsigned int y=frame;

	if (y >= info->height) {
		fprintf(stderr, "Frame %d greater than PNG height %lu\n",
			frame, info->height);
		return false;
	}
	png_byte* row = data[y];

	vector<string>::iterator i = axonLedNames.begin();
	x = 0; //axon LED's start at pixel 0
	for (i = axonLedNames.begin(); i != axonLedNames.end(); i++) {
		png_byte* ptr = &(row[x*3]); //get pixel rgb
		//fprintf(stderr, "Pixel [x: %d, y: %d] R:%d G:%d B:%d\n",
		//	x, y, ptr[0], ptr[1], ptr[2]);
		if (ptr[0] > 5 || ptr[1] > 5 || ptr[2] > 5)
			state->setLightOut(i->c_str(), ptr[0], ptr[1], ptr[2]);
		//printf("%d %d %d | ", ptr[0], ptr[1], ptr[2]);
		x++;
	}

	i = upperLedNames.begin();
	x = 10; //upper soma LED's start at pixel 10
	for (i = upperLedNames.begin(); i != upperLedNames.end(); i++) {
		png_byte* ptr = &(row[x*3]); //get pixel rgb
		if (ptr[0] > 5 || ptr[1] > 5 || ptr[2] > 5)
			state->setLightOut(i->c_str(), ptr[0], ptr[1], ptr[2]);
		x++;
	}

	i = lowerLedNames.begin();
	x = 40; //lower soma LED's start at pixel 40
	for (i = lowerLedNames.begin(); i != lowerLedNames.end(); i++) {
		png_byte* ptr = &(row[x*3]); //get pixel rgb
		if (ptr[0] > 5 || ptr[1] > 5 || ptr[2] > 5)
			state->setLightOut(i->c_str(), ptr[0], ptr[1], ptr[2]);
		x++;
	}

	i = digitalNames.begin();
	x = 50; //digital poofers start at pixel 50
	for (i = digitalNames.begin(); i != digitalNames.end(); i++) {
		png_byte* ptr = &(row[x*3]); //get pixel rgb
		if (ptr[0] > 5 && ptr[1] > 5 && ptr[2] > 5)
			state->setDigitalOut(i->c_str(), true);
		x++;
	}

	return y < info->height - 1;
}

bool
EventMachine::addScript(string mask, string script)
{
	EventScript *es = scriptData[script];
	if (!es) {
		// load script file, add with name to scriptData
		es = new EventScript();
		if (!es->load(script)) {
			delete es;
			fprintf(stderr, "Failed to load script '%s'\n", script.c_str());
			return false;
		}
	}

	scriptMasks.push_back(pair<EventMask, string>(EventMask(mask), script));
	scriptData[script] = es;

	fprintf(stderr, "Added script '%s' with event mask '%s'\n",
		script.c_str(), mask.c_str());

	return true;
}

void
EventMachine::update(State *state,
		     vector<string> lowerLedNames,
		     vector<string> axonLedNames,
		     vector<string> upperLedNames,
		     vector<string> digitalNames)
{
	vector<string>::iterator i;

	for (i = digitalNames.begin(); i != digitalNames.end(); i++)
		state->setDigitalOut(i->c_str(), false);

	for (vector< pair<EventMask, string> >::iterator i = scriptMasks.begin();
	     i != scriptMasks.end(); i++) {
		if (i->first.stateMatch(state)) {
			//fprintf(stderr, "Event state matches for script: %s\n",
			//	i->second.c_str());
			EventScript *data = scriptData[i->second];
			bool isRunning = false;
			vector< pair<EventScript*, uint> >::iterator i2;
			for (i2 = scriptStates.begin(); i2 != scriptStates.end(); i2++) {
				if (data == i2->first) {
					//fprintf(stderr, "Script %p already running.\n",
					//	i2->first);
					isRunning = true;
				}
			}

			if (!isRunning) {
				fprintf(stderr, "Restarting script '%s'.\n",
				i->second.c_str());
				scriptStates.push_back(pair<EventScript *, uint>(data, 0));
			}
	      }
	}

	vector< pair<EventScript*, uint> > nextStates;
	for (vector< pair<EventScript*, uint> >::iterator i2 = scriptStates.begin();
	     i2 != scriptStates.end(); i2++) {
		// Call Ben's event updating for the row at index i2->second.
		EventScript *data = i2->first;
		uint frame = i2->second;

		if (!data) {
			fprintf(stderr, "Invalid script data!\n");
			continue;
		}

		if (data->update(state, frame, lowerLedNames, axonLedNames,
				 upperLedNames, digitalNames)) {
			//fprintf(stderr, "Advancing to frame %d of script %p\n", frame, data);
			nextStates.push_back(pair<EventScript*, uint>(data, frame + 1));
		}
	}
	scriptStates = nextStates;
}

bool
EventMachine::parseEvent(xmlNodePtr node)
{
	bool ret = false;
	xmlChar *maskStr = xmlGetProp(node, (const xmlChar *)"mask");
	xmlChar *scriptStr = xmlGetProp(node, (const xmlChar *)"script");

	if (maskStr == NULL) {
		fprintf(stderr, "%s has no mask\n", node->name);
		goto err;
	}
	if (scriptStr == NULL) {
		fprintf(stderr, "%s has no script\n", node->name);
		goto err;
	}

	ret = addScript((char *)maskStr, (char *)scriptStr);

err:
	xmlFree(maskStr);
	xmlFree(scriptStr);
	return ret;
}

bool
EventMachine::loadConfig(const char *fileName)
{
	xmlDocPtr doc;
	xmlNodePtr cur;
	xmlNodePtr child;
	bool ret = true;

	doc = xmlParseFile(fileName);

	if (doc == NULL) {
		fprintf(stderr, "Document %s not parsed successfully\n",
			fileName);
		return false;
	}

	cur = xmlDocGetRootElement(doc);
	if (cur == NULL) {
		fprintf(stderr, "empty doc\n");
		return false;
	}

	if (xmlStrcmp(cur->name, (const xmlChar *)"config")){
		fprintf(stderr, "config file does not start with config element\n");
		goto err0;
	}

	for (child = cur->xmlChildrenNode;
	     child != NULL;
	     child = child->next) {
		if (!xmlStrcmp(child->name, (const xmlChar*)"event")) {
			ret = parseEvent(child);
			if (!ret)
				goto err0;
		}
	}

err0:
	xmlFreeDoc(doc);
	return ret;
}
<|endoftext|>


<commit_before>/*
 Copyright (c) 2013, The Cinder Project (http://libcinder.org)
 All rights reserved.

 Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list of conditions and
	the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
	the following disclaimer in the documentation and/or other materials provided with the distribution.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
*/

#include "ConvexHull.h"

#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>

namespace cinder {

typedef boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > polygon;

namespace {

template<typename T>
PolyLine<Vec2<T> > toPolyLine( const polygon &p )
{
	PolyLine<Vec2<T> > result;

	for( auto pt = p.outer().begin(); pt != p.outer().end(); ++pt )
		result.push_back( Vec2<T>( boost::geometry::get<0>(*pt), boost::geometry::get<1>(*pt) ) );

	return result;
}

boost::geometry::model::d2::point_xy<double> makePoint( const Vec2f &p )
{
	return boost::geometry::make<boost::geometry::model::d2::point_xy<double> >( p.x, p.y );
}

void includePathExtremeties( const Path2d &p, polygon *output )
{
	size_t firstPoint = 0;
	for( size_t s = 0; s < p.getSegments().size(); ++s ) {
		switch( p.getSegments()[s] ) {
			case Path2d::CUBICTO: {
				float monotoneT[4];
				int monotoneCnt = Path2d::calcCubicBezierMonotoneRegions( &(p.getPoints()[firstPoint]), monotoneT );
				for( int monotoneIdx = 0; monotoneIdx < monotoneCnt; ++monotoneIdx )
					output->outer().push_back( makePoint( Path2d::calcCubicBezierPos( &(p.getPoints()[firstPoint]), monotoneT[monotoneIdx] ) ) );

				output->outer().push_back( makePoint( p.getPoints()[firstPoint+0] ) );
				output->outer().push_back( makePoint( p.getPoints()[firstPoint+1] ) );
				output->outer().push_back( makePoint( p.getPoints()[firstPoint+2] ) );
			}
			break;
			case Path2d::QUADTO: {
				float monotoneT[2];
				int monotoneCnt = Path2d::calcCubicBezierMonotoneRegions( &(p.getPoints()[firstPoint]), monotoneT );
				for( int monotoneIdx = 0; monotoneIdx < monotoneCnt; ++monotoneIdx )
					output->outer().push_back( makePoint( Path2d::calcQuadraticBezierPos( &(p.getPoints()[firstPoint]), monotoneT[monotoneIdx] ) ) );
				output->outer().push_back( makePoint( p.getPoints()[firstPoint+0] ) );
				output->outer().push_back( makePoint( p.getPoints()[firstPoint+1] ) );
			}
			break;
			case Path2d::LINETO:
				output->outer().push_back( makePoint( p.getPoints()[firstPoint+0] ) );
			break;
			case Path2d::CLOSE:
				output->outer().push_back( makePoint( p.getPoints()[firstPoint+0] ) );
			break;
			default:
				throw Path2dExc();
		}

		firstPoint += Path2d::sSegmentTypePointCounts[p.getSegments()[s]];
	}
}

} // anonymous namespace

PolyLine2f calcConvexHull( const std::vector<Vec2f> &points )
{
	return calcConvexHull( &points[0], points.size() );
}

PolyLine2f calcConvexHull( const Vec2f *points, size_t numPoints )
{
	polygon poly;
	for( size_t p = 0; p < numPoints; ++p )
		poly.outer().push_back( boost::geometry::make<boost::geometry::model::d2::point_xy<double> >( points[p].x, points[p].y ) );

	polygon result;
	boost::geometry::convex_hull( poly, result );

	return toPolyLine<float>( result );
}

PolyLine2f calcConvexHull( const Shape2d &shape )
{
	polygon poly;
	for( auto contourIt = shape.getContours().begin(); contourIt != shape.getContours().end(); ++contourIt )
		includePathExtremeties( *contourIt, &poly );

	polygon result;
	boost::geometry::convex_hull( poly, result );

	return toPolyLine<float>( result );
}

PolyLine2f calcConvexHull( const Path2d &path )
{
	polygon poly;
	includePathExtremeties( path, &poly );

	polygon result;
	boost::geometry::convex_hull( poly, result );

	return toPolyLine<float>( result );
}

PolyLine2f calcConvexHull( const PolyLine2f &polyLine )
{
	polygon poly;
	for( auto ptIt = polyLine.begin(); ptIt != polyLine.end(); ++ptIt )
		poly.outer().push_back( boost::geometry::make<boost::geometry::model::d2::point_xy<double> >( ptIt->x, ptIt->y ) );

	polygon result;
	boost::geometry::convex_hull( poly, result );

	return toPolyLine<float>( result );
}

} // namespace cinder<commit_msg>MSW ConvexHull build fixes<commit_after>/*
 Copyright (c) 2013, The Cinder Project (http://libcinder.org)
 All rights reserved.

 Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list of conditions and
	the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
	the following disclaimer in the documentation and/or other materials provided with the distribution.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
*/

#include "cinder/ConvexHull.h"

#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>

namespace cinder {

typedef boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > polygon;

namespace {

template<typename T>
PolyLine<Vec2<T> > toPolyLine( const polygon &p )
{
	PolyLine<Vec2<T> > result;

	for( auto pt = p.outer().begin(); pt != p.outer().end(); ++pt )
		result.push_back( Vec2<T>( (T)boost::geometry::get<0>(*pt), (T)boost::geometry::get<1>(*pt) ) );

	return result;
}

boost::geometry::model::d2::point_xy<double> makePoint( const Vec2f &p )
{
	return boost::geometry::make<boost::geometry::model::d2::point_xy<double> >( p.x, p.y );
}

void includePathExtremeties( const Path2d &p, polygon *output )
{
	size_t firstPoint = 0;
	for( size_t s = 0; s < p.getSegments().size(); ++s ) {
		switch( p.getSegments()[s] ) {
			case Path2d::CUBICTO: {
				float monotoneT[4];
				int monotoneCnt = Path2d::calcCubicBezierMonotoneRegions( &(p.getPoints()[firstPoint]), monotoneT );
				for( int monotoneIdx = 0; monotoneIdx < monotoneCnt; ++monotoneIdx )
					output->outer().push_back( makePoint( Path2d::calcCubicBezierPos( &(p.getPoints()[firstPoint]), monotoneT[monotoneIdx] ) ) );

				output->outer().push_back( makePoint( p.getPoints()[firstPoint+0] ) );
				output->outer().push_back( makePoint( p.getPoints()[firstPoint+1] ) );
				output->outer().push_back( makePoint( p.getPoints()[firstPoint+2] ) );
			}
			break;
			case Path2d::QUADTO: {
				float monotoneT[2];
				int monotoneCnt = Path2d::calcCubicBezierMonotoneRegions( &(p.getPoints()[firstPoint]), monotoneT );
				for( int monotoneIdx = 0; monotoneIdx < monotoneCnt; ++monotoneIdx )
					output->outer().push_back( makePoint( Path2d::calcQuadraticBezierPos( &(p.getPoints()[firstPoint]), monotoneT[monotoneIdx] ) ) );
				output->outer().push_back( makePoint( p.getPoints()[firstPoint+0] ) );
				output->outer().push_back( makePoint( p.getPoints()[firstPoint+1] ) );
			}
			break;
			case Path2d::LINETO:
				output->outer().push_back( makePoint( p.getPoints()[firstPoint+0] ) );
			break;
			case Path2d::CLOSE:
				output->outer().push_back( makePoint( p.getPoints()[firstPoint+0] ) );
			break;
			default:
				throw Path2dExc();
		}

		firstPoint += Path2d::sSegmentTypePointCounts[p.getSegments()[s]];
	}
}

} // anonymous namespace

PolyLine2f calcConvexHull( const std::vector<Vec2f> &points )
{
	return calcConvexHull( &points[0], points.size() );
}

PolyLine2f calcConvexHull( const Vec2f *points, size_t numPoints )
{
	polygon poly;
	for( size_t p = 0; p < numPoints; ++p )
		poly.outer().push_back( boost::geometry::make<boost::geometry::model::d2::point_xy<double> >( points[p].x, points[p].y ) );

	polygon result;
	boost::geometry::convex_hull( poly, result );

	return toPolyLine<float>( result );
}

PolyLine2f calcConvexHull( const Shape2d &shape )
{
	polygon poly;
	for( auto contourIt = shape.getContours().begin(); contourIt != shape.getContours().end(); ++contourIt )
		includePathExtremeties( *contourIt, &poly );

	polygon result;
	boost::geometry::convex_hull( poly, result );

	return toPolyLine<float>( result );
}

PolyLine2f calcConvexHull( const Path2d &path )
{
	polygon poly;
	includePathExtremeties( path, &poly );

	polygon result;
	boost::geometry::convex_hull( poly, result );

	return toPolyLine<float>( result );
}

PolyLine2f calcConvexHull( const PolyLine2f &polyLine )
{
	polygon poly;
	for( auto ptIt = polyLine.begin(); ptIt != polyLine.end(); ++ptIt )
		poly.outer().push_back( boost::geometry::make<boost::geometry::model::d2::point_xy<double> >( ptIt->x, ptIt->y ) );

	polygon result;
	boost::geometry::convex_hull( poly, result );

	return toPolyLine<float>( result );
}

} // namespace cinder<|endoftext|>


<commit_before>// NavierStokesModel.cc
//
// Description: Implementation of the NavierStokesModel class
//
// Author(s):
// Clancy Rowley
//
// Date: 3 Jul 2008
//
// $Revision$
// $LastChangedDate$
// $LastChangedBy$
// $HeadURL$

#include "NavierStokesModel.h"

namespace ibpm {

	NavierStokesModel::NavierStokesModel(
	const Grid& grid,
	const Geometry& geometry,
	double Reynolds,
	const BaseFlow& q_potential
	) :
    _grid( grid ),
    _geometry( geometry ),
    _regularizer( grid, geometry ),
    _baseFlow( q_potential ),
    _ReynoldsNumber( Reynolds ),
    _poisson( grid ),
    _hasBeenInitialized( false )
	{}

    NavierStokesModel::NavierStokesModel(
    const Grid& grid,
    const Geometry& geometry,
    double Reynolds
    ) :
    _grid( grid ),
    _geometry( geometry ),
    _regularizer( grid, geometry ),
    _baseFlow( grid ),
    _ReynoldsNumber( Reynolds ),
    _poisson( grid ),
    _hasBeenInitialized( false )
    {
        _baseFlow.setFlux(0.);
    }

    NavierStokesModel::~NavierStokesModel() {}

    void NavierStokesModel::init() {
        if ( _hasBeenInitialized ) return;  // do only once
        // Update regularizer
        _regularizer.update();
        _hasBeenInitialized = true;
    }

    bool NavierStokesModel::isTimeDependent() const {
        bool flag = false;
        if( (!_geometry.isStationary()) || (!_baseFlow.isStationary()) ) flag = true;
        return flag;
    }

    bool NavierStokesModel::geTimeDependent() const {
        bool flag = false;
        if( (!_geometry.isStationary()) ) flag = true;
        return flag;
    }

    bool NavierStokesModel::bfTimeDependent() const {
        bool flag = false;
        if( (!_baseFlow.isStationary()) ) flag = true;
        return flag;
    }

    int NavierStokesModel::getNumPoints() const {
        return _geometry.getNumPoints();
    }

    double NavierStokesModel::getAlpha() const {
        return 1. / _ReynoldsNumber;
    }

    // Return the boundary velocities minus the base flow velocity at the boundary
    BoundaryVector NavierStokesModel::getConstraints() const {
        BoundaryVector b = _geometry.getVelocities();
        BoundaryVector b0 = getBaseFlowBoundaryVelocities();
        b -= b0;
        return b;
    }

    void NavierStokesModel::updateOperators( double time ) {
        _geometry.moveBodies(time);
        _baseFlow.moveFlow(time);
        _regularizer.update();
    }

    void NavierStokesModel::B(const BoundaryVector& f, Scalar& omega ) const {
        assert( _hasBeenInitialized );
        Flux q = _regularizer.toFlux( f );
        Curl( q, omega );
    }

    void NavierStokesModel::C(const Scalar& omega, BoundaryVector& f) const {
        assert( _hasBeenInitialized );
		Flux q(_grid);
		computeFluxWithoutBaseFlow( omega, q );
		f = _regularizer.toBoundary( q );
	}

	void NavierStokesModel::computeFluxWithoutBaseFlow(const Scalar& omega,
													   Flux& q ) const {
		assert( _hasBeenInitialized );
		Scalar streamfunction = vorticityToStreamfunction( omega );
		Curl( streamfunction, q );
	}

	void NavierStokesModel::computeFlux(const Scalar& omega, Flux& q ) const {
		assert( _hasBeenInitialized );
		computeFluxWithoutBaseFlow( omega, q );
		q += _baseFlow.getFlux();
	}

	void NavierStokesModel::refreshState( State& x ) const {
		computeFlux( x.omega, x.q );
	}

	// Convert vorticity omega into streamfunction psi:
	//    Laplacian psi = - omega
	Scalar NavierStokesModel::vorticityToStreamfunction( const Scalar& omega ) const {
		assert( _hasBeenInitialized );
		// Solve L psi = omega, with zero Dirichlet bc's
		Scalar psi = -1. * omega;
		psi.coarsify();
		_poisson.solve( psi, psi );
		return psi;
	}

	BoundaryVector NavierStokesModel::getBaseFlowBoundaryVelocities() const {
		assert( _hasBeenInitialized );
		BoundaryVector velocity = _regularizer.toBoundary( _baseFlow.getFlux() );
		return velocity;
	}

} // namespace ibpm

<commit_msg>[/branches/ibpm-ubf] Minor modification, fixed NavierStokesModel::updateOperators to keep track of geometry and baseflow motions separately<commit_after>// NavierStokesModel.cc
//
// Description: Implementation of the NavierStokesModel class
//
// Author(s):
// Clancy Rowley
//
// Date: 3 Jul 2008
//
// $Revision$
// $LastChangedDate$
// $LastChangedBy$
// $HeadURL$

#include "NavierStokesModel.h"

namespace ibpm {

	NavierStokesModel::NavierStokesModel(
	const Grid& grid,
	const Geometry& geometry,
	double Reynolds,
	const BaseFlow& q_potential
	) :
    _grid( grid ),
    _geometry( geometry ),
    _regularizer( grid, geometry ),
    _baseFlow( q_potential ),
    _ReynoldsNumber( Reynolds ),
    _poisson( grid ),
    _hasBeenInitialized( false )
	{}

    NavierStokesModel::NavierStokesModel(
    const Grid& grid,
    const Geometry& geometry,
    double Reynolds
    ) :
    _grid( grid ),
    _geometry( geometry ),
    _regularizer( grid, geometry ),
    _baseFlow( grid ),
    _ReynoldsNumber( Reynolds ),
    _poisson( grid ),
    _hasBeenInitialized( false )
    {
        _baseFlow.setFlux(0.);
    }

    NavierStokesModel::~NavierStokesModel() {}

    void NavierStokesModel::init() {
        if ( _hasBeenInitialized ) return;  // do only once
        // Update regularizer
        _regularizer.update();
        _hasBeenInitialized = true;
    }

    bool NavierStokesModel::isTimeDependent() const {
        bool flag = false;
        if( (!_geometry.isStationary()) || (!_baseFlow.isStationary()) ) flag = true;
        return flag;
    }

    bool NavierStokesModel::geTimeDependent() const {
        bool flag = false;
        if( (!_geometry.isStationary()) ) flag = true;
        return flag;
    }

    bool NavierStokesModel::bfTimeDependent() const {
        bool flag = false;
        if( (!_baseFlow.isStationary()) ) flag = true;
        return flag;
    }

    int NavierStokesModel::getNumPoints() const {
        return _geometry.getNumPoints();
    }

    double NavierStokesModel::getAlpha() const {
        return 1. / _ReynoldsNumber;
    }

    // Return the boundary velocities minus the base flow velocity at the boundary
    BoundaryVector NavierStokesModel::getConstraints() const {
        BoundaryVector b = _geometry.getVelocities();
        BoundaryVector b0 = getBaseFlowBoundaryVelocities();
        b -= b0;
        return b;
    }

    void NavierStokesModel::updateOperators( double time ) {
        if( bfTimeDependent() ) _baseFlow.moveFlow(time);
        if( geTimeDependent() ) {
            _geometry.moveBodies(time);
            _regularizer.update();
        }
    }

    void NavierStokesModel::B(const BoundaryVector& f, Scalar& omega ) const {
        assert( _hasBeenInitialized );
        Flux q = _regularizer.toFlux( f );
        Curl( q, omega );
    }

    void NavierStokesModel::C(const Scalar& omega, BoundaryVector& f) const {
        assert( _hasBeenInitialized );
		Flux q(_grid);
		computeFluxWithoutBaseFlow( omega, q );
		f = _regularizer.toBoundary( q );
	}

	void NavierStokesModel::computeFluxWithoutBaseFlow(const Scalar& omega,
													   Flux& q ) const {
		assert( _hasBeenInitialized );
		Scalar streamfunction = vorticityToStreamfunction( omega );
		Curl( streamfunction, q );
	}

	void NavierStokesModel::computeFlux(const Scalar& omega, Flux& q ) const {
		assert( _hasBeenInitialized );
		computeFluxWithoutBaseFlow( omega, q );
		q += _baseFlow.getFlux();
	}

	void NavierStokesModel::refreshState( State& x ) const {
		computeFlux( x.omega, x.q );
	}

	// Convert vorticity omega into streamfunction psi:
	//    Laplacian psi = - omega
	Scalar NavierStokesModel::vorticityToStreamfunction( const Scalar& omega ) const {
		assert( _hasBeenInitialized );
		// Solve L psi = omega, with zero Dirichlet bc's
		Scalar psi = -1. * omega;
		psi.coarsify();
		_poisson.solve( psi, psi );
		return psi;
	}

	BoundaryVector NavierStokesModel::getBaseFlowBoundaryVelocities() const {
		assert( _hasBeenInitialized );
		BoundaryVector velocity = _regularizer.toBoundary( _baseFlow.getFlux() );
		return velocity;
	}

} // namespace ibpm

<|endoftext|>