<commit_before>/* This file is part of Ingen.
 * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
 *
 * Ingen 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 2 of the License, or (at your option) any later
 * version.
 *
 * Ingen 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 details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include CONFIG_H_PATH
#include <cstdlib>
#include <pthread.h>
#include <dirent.h>
#include <float.h>
#include <cmath>
#include "module/World.hpp"
#include "NodeFactory.hpp"
#include "ThreadManager.hpp"
#include "MidiNoteNode.hpp"
#include "MidiTriggerNode.hpp"
#include "MidiControlNode.hpp"
#include "TransportNode.hpp"
#include "PatchImpl.hpp"
#include "InternalPlugin.hpp"
#ifdef HAVE_LADSPA
#include "LADSPANode.hpp"
#include "LADSPAPlugin.hpp"
#endif
#ifdef HAVE_SLV2
#include <slv2/slv2.h>
#include "LV2Plugin.hpp"
#include "LV2Node.hpp"
#endif

using namespace std;

namespace Ingen {

NodeFactory::NodeFactory(Ingen::Shared::World* world)
	: _world(world)
	, _has_loaded(false)
#ifdef HAVE_SLV2
	, _lv2_info(new LV2Info(world->slv2_world))
#endif
{
}

NodeFactory::~NodeFactory()
{
	for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i)
		if (i->second->type() != Plugin::Internal)
			delete i->second;

	_plugins.clear();
}

PluginImpl*
NodeFactory::plugin(const string& uri)
{
	const Plugins::const_iterator i = _plugins.find(uri);
	return ((i != _plugins.end()) ? i->second : NULL);
}

/** DEPRECATED: Find a plugin by type, lib, label.
 *
 * Slow.  Evil.  Do not use.
 */
PluginImpl*
NodeFactory::plugin(const string& type, const string& lib, const string& label)
{
	if (type != "LADSPA" || lib == "" || label == "")
		return NULL;

	for (Plugins::const_iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
		LADSPAPlugin* lp = dynamic_cast<LADSPAPlugin*>(i->second);
		if (lp && lp->type_string() == type
				&& lp->library_name() == lib
				&& lp->label() == label)
			return lp;
	}

	cerr << "ERROR: Failed to find " << type << " plugin " << lib << " / " << label << endl;

	return NULL;
}

void
NodeFactory::load_plugins()
{
	assert(ThreadManager::current_thread_id() == THREAD_PRE_PROCESS);

	// Only load if we havn't already, so every client connecting doesn't cause
	// this (expensive!) stuff to happen.  Not the best solution - would be nice
	// if clients could refresh plugins list for whatever reason :/
	if (!_has_loaded) {
		_plugins.clear(); // FIXME: assert empty?

		load_internal_plugins();

#ifdef HAVE_SLV2
		load_lv2_plugins();
#endif

#ifdef HAVE_LADSPA
		load_ladspa_plugins();
#endif

		_has_loaded = true;
	}

#if 0
	for (Plugins::const_iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
		assert(Path::is_valid_name(i->second->symbol()));
		cerr << "PLUGIN: " << i->second->uri() << " - " << i->second->symbol()
			<< " (" << i->second->name() << ")" << endl;
		PatchImpl* parent = new PatchImpl(*_world->local_engine, "dummy", 1, NULL, 1, 1, 1);
		NodeImpl* node = i->second->instantiate("foo", 0, parent, 48000, 512);
		if (node)
		for (uint32_t i=0; i < node->num_ports(); ++i) {
			cerr << "\t" << node->port(i)->name() << endl;
		}
		cerr << endl;
	}
#endif

	//cerr << "[NodeFactory] # Plugins: " << _plugins.size() << endl;
}

void
NodeFactory::load_internal_plugins()
{
	// This is a touch gross...

	PatchImpl* parent = new PatchImpl(*_world->local_engine, "dummy", 1, NULL, 1, 1, 1);

	NodeImpl* n = NULL;
	n = new MidiNoteNode("foo", 1, parent, 1, 1);
	_plugins.insert(make_pair(n->plugin_impl()->uri(), n->plugin_impl()));
	delete n;
	n = new MidiTriggerNode("foo", 1, parent, 1, 1);
	_plugins.insert(make_pair(n->plugin_impl()->uri(), n->plugin_impl()));
	delete n;
	n = new MidiControlNode("foo", 1, parent, 1, 1);
	_plugins.insert(make_pair(n->plugin_impl()->uri(), n->plugin_impl()));
	delete n;
	n = new TransportNode("foo", 1, parent, 1, 1);
	_plugins.insert(make_pair(n->plugin_impl()->uri(), n->plugin_impl()));
	delete n;

	delete parent;
}

#ifdef HAVE_SLV2
/** Loads information about all LV2 plugins into internal plugin database.
 */
void
NodeFactory::load_lv2_plugins()
{
	SLV2Plugins plugins = slv2_world_get_all_plugins(_world->slv2_world);

	//cerr << "[NodeFactory] Found " << slv2_plugins_size(plugins) << " LV2 plugins:" << endl;

	for (unsigned i=0; i < slv2_plugins_size(plugins); ++i) {

		SLV2Plugin lv2_plug = slv2_plugins_get_at(plugins, i);

		const string uri(slv2_value_as_uri(slv2_plugin_get_uri(lv2_plug)));

#ifndef NDEBUG
		assert(_plugins.find(uri) == _plugins.end());
#endif

		LV2Plugin* const plugin = new LV2Plugin(_lv2_info, uri);

		plugin->slv2_plugin(lv2_plug);
		plugin->library_path(slv2_uri_to_path(slv2_value_as_uri(
				slv2_plugin_get_library_uri(lv2_plug))));
		_plugins.insert(make_pair(uri, plugin));
	}

	slv2_plugins_free(_world->slv2_world, plugins);
}
#endif // HAVE_SLV2

#ifdef HAVE_LADSPA
/** Loads information about all LADSPA plugins into internal plugin database.
 */
void
NodeFactory::load_ladspa_plugins()
{
	char* env_ladspa_path = getenv("LADSPA_PATH");
	string ladspa_path;
	if (!env_ladspa_path) {
	 	cerr << "[NodeFactory] LADSPA_PATH is empty.  Assuming /usr/lib/ladspa:/usr/local/lib/ladspa:~/.ladspa" << endl;
		ladspa_path = string("/usr/lib/ladspa:/usr/local/lib/ladspa:").append(
			getenv("HOME")).append("/.ladspa");
	} else {
		ladspa_path = env_ladspa_path;
	}

	// Yep, this should use an sstream alright..
	while (ladspa_path != "") {
		const string dir = ladspa_path.substr(0, ladspa_path.find(':'));
		if (ladspa_path.find(':') != string::npos)
			ladspa_path = ladspa_path.substr(ladspa_path.find(':')+1);
		else
			ladspa_path = "";

		DIR* pdir = opendir(dir.c_str());
		if (pdir == NULL) {
			//cerr << "[NodeFactory] Unreadable directory in LADSPA_PATH: " << dir.c_str() << endl;
			continue;
		}

		struct dirent* pfile;
		while ((pfile = readdir(pdir))) {

			LADSPA_Descriptor_Function df         = NULL;
			LADSPA_Descriptor*         descriptor = NULL;

			if (!strcmp(pfile->d_name, ".") || !strcmp(pfile->d_name, ".."))
				continue;

			const string lib_path = dir +"/"+ pfile->d_name;

			// Ignore stupid libtool files.  Kludge alert.
			if (lib_path.substr(lib_path.length()-3) == ".la") {
				//cerr << "WARNING: Skipping stupid libtool file " << pfile->d_name << endl;
				continue;
			}

			Glib::Module* plugin_library = new Glib::Module(lib_path, Glib::MODULE_BIND_LOCAL);
			if (!plugin_library || !(*plugin_library)) {
				cerr << "WARNING: Failed to load LADSPA library " << lib_path << endl;
				continue;
			}

			bool found = plugin_library->get_symbol("ladspa_descriptor", (void*&)df);
			if (!found || !df) {
				cerr << "WARNING: Non-LADSPA library found in LADSPA path: " <<
					lib_path << endl;
				// Not a LADSPA plugin library
				delete plugin_library;
				continue;
			}

			for (unsigned long i=0; (descriptor = (LADSPA_Descriptor*)df(i)) != NULL; ++i) {
				char id_str[11];
				snprintf(id_str, 11, "%lu", descriptor->UniqueID);
				const string uri = string("ladspa:").append(id_str);

				const Plugins::const_iterator i = _plugins.find(uri);

				if (i == _plugins.end()) {
					LADSPAPlugin* plugin = new LADSPAPlugin(lib_path, uri,
						descriptor->UniqueID,
						descriptor->Label,
						descriptor->Name);

					_plugins.insert(make_pair(uri, plugin));

				} else {
					cerr << "Warning: Duplicate LADSPA plugin " << uri << " found." << endl;
					cerr << "\tUsing " << i->second->library_path() << " over " << lib_path << endl;
				}
			}

			delete plugin_library;
		}
		closedir(pdir);
	}
}
#endif // HAVE_LADSPA

} // namespace Ingen
<commit_msg>Fix building w/o LADSPA.<commit_after>/* This file is part of Ingen.
 * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
 *
 * Ingen 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 2 of the License, or (at your option) any later
 * version.
 *
 * Ingen 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 details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include CONFIG_H_PATH
#include <cstdlib>
#include <pthread.h>
#include <dirent.h>
#include <float.h>
#include <cmath>
#include "module/World.hpp"
#include "NodeFactory.hpp"
#include "ThreadManager.hpp"
#include "MidiNoteNode.hpp"
#include "MidiTriggerNode.hpp"
#include "MidiControlNode.hpp"
#include "TransportNode.hpp"
#include "PatchImpl.hpp"
#include "InternalPlugin.hpp"
#ifdef HAVE_LADSPA
#include "LADSPANode.hpp"
#include "LADSPAPlugin.hpp"
#endif
#ifdef HAVE_SLV2
#include <slv2/slv2.h>
#include "LV2Plugin.hpp"
#include "LV2Node.hpp"
#endif

using namespace std;

namespace Ingen {

NodeFactory::NodeFactory(Ingen::Shared::World* world)
	: _world(world)
	, _has_loaded(false)
#ifdef HAVE_SLV2
	, _lv2_info(new LV2Info(world->slv2_world))
#endif
{
}

NodeFactory::~NodeFactory()
{
	for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i)
		if (i->second->type() != Plugin::Internal)
			delete i->second;

	_plugins.clear();
}

PluginImpl*
NodeFactory::plugin(const string& uri)
{
	const Plugins::const_iterator i = _plugins.find(uri);
	return ((i != _plugins.end()) ? i->second : NULL);
}

/** DEPRECATED: Find a plugin by type, lib, label.
 *
 * Slow.  Evil.  Do not use.
 */
PluginImpl*
NodeFactory::plugin(const string& type, const string& lib, const string& label)
{
	if (type != "LADSPA" || lib == "" || label == "")
		return NULL;

#ifdef HAVE_LADSPA
	for (Plugins::const_iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
		LADSPAPlugin* lp = dynamic_cast<LADSPAPlugin*>(i->second);
		if (lp && lp->type_string() == type
				&& lp->library_name() == lib
				&& lp->label() == label)
			return lp;
	}
#endif

	cerr << "ERROR: Failed to find " << type << " plugin " << lib << " / " << label << endl;

	return NULL;
}

void
NodeFactory::load_plugins()
{
	assert(ThreadManager::current_thread_id() == THREAD_PRE_PROCESS);

	// Only load if we havn't already, so every client connecting doesn't cause
	// this (expensive!) stuff to happen.  Not the best solution - would be nice
	// if clients could refresh plugins list for whatever reason :/
	if (!_has_loaded) {
		_plugins.clear(); // FIXME: assert empty?

		load_internal_plugins();

#ifdef HAVE_SLV2
		load_lv2_plugins();
#endif

#ifdef HAVE_LADSPA
		load_ladspa_plugins();
#endif

		_has_loaded = true;
	}

#if 0
	for (Plugins::const_iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
		assert(Path::is_valid_name(i->second->symbol()));
		cerr << "PLUGIN: " << i->second->uri() << " - " << i->second->symbol()
			<< " (" << i->second->name() << ")" << endl;
		PatchImpl* parent = new PatchImpl(*_world->local_engine, "dummy", 1, NULL, 1, 1, 1);
		NodeImpl* node = i->second->instantiate("foo", 0, parent, 48000, 512);
		if (node)
		for (uint32_t i=0; i < node->num_ports(); ++i) {
			cerr << "\t" << node->port(i)->name() << endl;
		}
		cerr << endl;
	}
#endif

	//cerr << "[NodeFactory] # Plugins: " << _plugins.size() << endl;
}

void
NodeFactory::load_internal_plugins()
{
	// This is a touch gross...

	PatchImpl* parent = new PatchImpl(*_world->local_engine, "dummy", 1, NULL, 1, 1, 1);

	NodeImpl* n = NULL;
	n = new MidiNoteNode("foo", 1, parent, 1, 1);
	_plugins.insert(make_pair(n->plugin_impl()->uri(), n->plugin_impl()));
	delete n;
	n = new MidiTriggerNode("foo", 1, parent, 1, 1);
	_plugins.insert(make_pair(n->plugin_impl()->uri(), n->plugin_impl()));
	delete n;
	n = new MidiControlNode("foo", 1, parent, 1, 1);
	_plugins.insert(make_pair(n->plugin_impl()->uri(), n->plugin_impl()));
	delete n;
	n = new TransportNode("foo", 1, parent, 1, 1);
	_plugins.insert(make_pair(n->plugin_impl()->uri(), n->plugin_impl()));
	delete n;

	delete parent;
}

#ifdef HAVE_SLV2
/** Loads information about all LV2 plugins into internal plugin database.
 */
void
NodeFactory::load_lv2_plugins()
{
	SLV2Plugins plugins = slv2_world_get_all_plugins(_world->slv2_world);

	//cerr << "[NodeFactory] Found " << slv2_plugins_size(plugins) << " LV2 plugins:" << endl;

	for (unsigned i=0; i < slv2_plugins_size(plugins); ++i) {

		SLV2Plugin lv2_plug = slv2_plugins_get_at(plugins, i);

		const string uri(slv2_value_as_uri(slv2_plugin_get_uri(lv2_plug)));

#ifndef NDEBUG
		assert(_plugins.find(uri) == _plugins.end());
#endif

		LV2Plugin* const plugin = new LV2Plugin(_lv2_info, uri);

		plugin->slv2_plugin(lv2_plug);
		plugin->library_path(slv2_uri_to_path(slv2_value_as_uri(
				slv2_plugin_get_library_uri(lv2_plug))));
		_plugins.insert(make_pair(uri, plugin));
	}

	slv2_plugins_free(_world->slv2_world, plugins);
}
#endif // HAVE_SLV2

#ifdef HAVE_LADSPA
/** Loads information about all LADSPA plugins into internal plugin database.
 */
void
NodeFactory::load_ladspa_plugins()
{
	char* env_ladspa_path = getenv("LADSPA_PATH");
	string ladspa_path;
	if (!env_ladspa_path) {
	 	cerr << "[NodeFactory] LADSPA_PATH is empty.  Assuming /usr/lib/ladspa:/usr/local/lib/ladspa:~/.ladspa" << endl;
		ladspa_path = string("/usr/lib/ladspa:/usr/local/lib/ladspa:").append(
			getenv("HOME")).append("/.ladspa");
	} else {
		ladspa_path = env_ladspa_path;
	}

	// Yep, this should use an sstream alright..
	while (ladspa_path != "") {
		const string dir = ladspa_path.substr(0, ladspa_path.find(':'));
		if (ladspa_path.find(':') != string::npos)
			ladspa_path = ladspa_path.substr(ladspa_path.find(':')+1);
		else
			ladspa_path = "";

		DIR* pdir = opendir(dir.c_str());
		if (pdir == NULL) {
			//cerr << "[NodeFactory] Unreadable directory in LADSPA_PATH: " << dir.c_str() << endl;
			continue;
		}

		struct dirent* pfile;
		while ((pfile = readdir(pdir))) {

			LADSPA_Descriptor_Function df         = NULL;
			LADSPA_Descriptor*         descriptor = NULL;

			if (!strcmp(pfile->d_name, ".") || !strcmp(pfile->d_name, ".."))
				continue;

			const string lib_path = dir +"/"+ pfile->d_name;

			// Ignore stupid libtool files.  Kludge alert.
			if (lib_path.substr(lib_path.length()-3) == ".la") {
				//cerr << "WARNING: Skipping stupid libtool file " << pfile->d_name << endl;
				continue;
			}

			Glib::Module* plugin_library = new Glib::Module(lib_path, Glib::MODULE_BIND_LOCAL);
			if (!plugin_library || !(*plugin_library)) {
				cerr << "WARNING: Failed to load LADSPA library " << lib_path << endl;
				continue;
			}

			bool found = plugin_library->get_symbol("ladspa_descriptor", (void*&)df);
			if (!found || !df) {
				cerr << "WARNING: Non-LADSPA library found in LADSPA path: " <<
					lib_path << endl;
				// Not a LADSPA plugin library
				delete plugin_library;
				continue;
			}

			for (unsigned long i=0; (descriptor = (LADSPA_Descriptor*)df(i)) != NULL; ++i) {
				char id_str[11];
				snprintf(id_str, 11, "%lu", descriptor->UniqueID);
				const string uri = string("ladspa:").append(id_str);

				const Plugins::const_iterator i = _plugins.find(uri);

				if (i == _plugins.end()) {
					LADSPAPlugin* plugin = new LADSPAPlugin(lib_path, uri,
						descriptor->UniqueID,
						descriptor->Label,
						descriptor->Name);

					_plugins.insert(make_pair(uri, plugin));

				} else {
					cerr << "Warning: Duplicate LADSPA plugin " << uri << " found." << endl;
					cerr << "\tUsing " << i->second->library_path() << " over " << lib_path << endl;
				}
			}

			delete plugin_library;
		}
		closedir(pdir);
	}
}
#endif // HAVE_LADSPA

} // namespace Ingen
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkFollower.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1996 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include <stdlib.h>
#include <math.h>
#include "vtkMath.h"
#include "vtkFollower.h"
#include "vtkCamera.h"

// Description:
// Creates a follower with no camera set
vtkFollower::vtkFollower()
{
  this->Camera = NULL;
  this->Device = vtkActor::New();
}

vtkFollower::~vtkFollower()
{
  this->Device->Delete();
}

// Description:
// Copy the follower's composite 4x4 matrix into the matrix provided.
void vtkFollower::GetMatrix(vtkMatrix4x4& result)
{
  float *pos;
  vtkMatrix4x4 matrix;

  this->GetOrientation();
  this->Transform.Push();
  this->Transform.Identity();
  this->Transform.PreMultiply();

  // apply user defined matrix last if there is one
  if (this->UserMatrix)
    {
    this->Transform.Concatenate(*this->UserMatrix);
    }

  // first translate
  this->Transform.Translate(this->Position[0],
			    this->Position[1],
			    this->Position[2]);

  // shift to origin
  this->Transform.Translate(this->Origin[0],
			    this->Origin[1],
			    this->Origin[2]);

  // add the rotation to follow the camera
  if (this->Camera)
    {
    float distance, distance_old;
    float *vup;
    float twist = 0;
    float v1[3], v2[3], y_axis[3];
    double theta, dot, mag;
    double cosang;
    float vn[3];

    // calc the direction
    pos = this->Camera->GetPosition();
    vup = this->Camera->GetViewUp();

    // first rotate y
    distance = sqrt((this->Position[0]-pos[0])*(this->Position[0]-pos[0]) +
		    (this->Position[2]-pos[2])*(this->Position[2]-pos[2]));
    vn[0] = (pos[0] - this->Position[0])/distance;
    vn[1] = (pos[1] - this->Position[1])/distance;
    vn[2] = (pos[2] - this->Position[2])/distance;

    // rotate y
    if (distance > 0.0)
      {
      matrix[0][0] = (this->Position[2]-pos[2])/distance;
      matrix[0][2] = -1.0*(pos[0] - this->Position[0])/distance;
      }
    else
      {
      if (this->Position[1] < pos[1])
	{
	matrix[0][0] = -1.0;
	}
      else
	{
	matrix[0][0] = 1.0;
	}
      matrix[0][2] = 0.0;
      }
    matrix[0][1] = matrix[0][3] = 0.0;
    matrix[1][1] = 1.0;
    matrix[1][0] = matrix[1][2] = matrix[1][3] = 0.0;
    matrix[2][0] = -1.0*matrix[0][2];
    matrix[2][2] = matrix[0][0];
    matrix[2][3] = 0.0;
    matrix[2][1] = 0.0;
    matrix[3][3] = 1.0;
    matrix[3][0] = matrix[3][1] = matrix[3][2] = 0.0;
    this->Transform.Concatenate(matrix);

    // now rotate x
    distance_old = distance;
    distance = sqrt((this->Position[0]-pos[0])*(this->Position[0]-pos[0]) +
		    (this->Position[1]-pos[1])*(this->Position[1]-pos[1]) +
		    (this->Position[2]-pos[2])*(this->Position[2]-pos[2]));
    matrix[0][0] = 1.0;
    matrix[0][1] = matrix[0][2] = matrix[0][3] = 0.0;
    matrix[1][1] = distance_old/distance;
    matrix[1][2] = (this->Position[1] - pos[1])/distance;
    matrix[1][0] = matrix[1][3] = 0.0;
    matrix[2][1] = -1.0*matrix[1][2];
    matrix[2][2] = matrix[1][1];
    matrix[2][3] = 0.0;
    matrix[2][0] = 0.0;
    matrix[3][3] = 1.0;
    matrix[3][0] = matrix[3][1] = matrix[3][2] = 0.0;
    this->Transform.Concatenate(matrix);

    // calc the twist
    // compute: vn X ( vup X vn)
    // and:     vn X ( y-axis X vn)
    // then find the angle between the two projected vectors
    //
    y_axis[0] = y_axis[2] = 0.0; y_axis[1] = 1.0;

    // bump the view normal if it is parallel to the y-axis
    //
    if ((vn[0] == 0.0) && (vn[2] == 0.0))
      vn[2] = 0.01*vn[1];

    // first project the view_up onto the view_plane
    //
    vtkMath::Cross(vup, vn, v1);
    vtkMath::Cross(vn, v1, v1);

    // then project the y-axis onto the view plane
    //
    vtkMath::Cross(y_axis, vn, v2);
    vtkMath::Cross(vn, v2, v2);

    // then find the angle between the two projected vectors
    //
    dot = v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
    mag = sqrt((double)(v1[0]*v1[0] + v1[1]*v1[1] + v1[2]*v1[2]));
    mag *= sqrt((double)(v2[0]*v2[0] + v2[1]*v2[1] + v2[2]*v2[2]));

    // make sure we dont divide by 0
    if (mag != 0.0)
      {
      cosang = dot / mag;
      if (cosang < -1.0) cosang = -1.0;
      if (cosang > 1.0) cosang = 1.0;
      theta = acos(cosang);
      }
    else
      theta = 0.0;

    // now see if the angle is positive or negative
    //
    vtkMath::Cross(v1, v2, v1);
    dot = v1[0]*vn[0] + v1[1]*vn[1] + v1[2]*vn[2];

    twist = (theta);
    if (dot < 0.0)
      twist = -twist;

    // now rotate z (twist)
    matrix[0][0] = cos(-twist);
    matrix[0][1] = sin(-twist);
    matrix[0][2] = matrix[0][3] = 0.0;
    matrix[1][0] = -1.0*matrix[0][1];
    matrix[1][1] = matrix[0][0];
    matrix[1][2] = matrix[1][3] = 0.0;
    matrix[2][1] = 0.0;
    matrix[2][2] = 1.0;
    matrix[2][3] = 0.0;
    matrix[2][0] = 0.0;
    matrix[3][3] = 1.0;
    matrix[3][0] = matrix[3][1] = matrix[3][2] = 0.0;
    this->Transform.Concatenate(matrix);

    // rotate y by 180 to get the positive zaxis instead of negative
    this->Transform.RotateY(180);
    }

  // rotate
  this->Transform.RotateZ(this->Orientation[2]);
  this->Transform.RotateX(this->Orientation[0]);
  this->Transform.RotateY(this->Orientation[1]);

  // scale
  this->Transform.Scale(this->Scale[0],
			this->Scale[1],
			this->Scale[2]);

  // shift back from origin
  this->Transform.Translate(-this->Origin[0],
			    -this->Origin[1],
			    -this->Origin[2]);

  result = this->Transform.GetMatrix();

  this->Transform.Pop();
}

void vtkFollower::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkActor::PrintSelf(os,indent);

  if ( this->Camera )
    {
    os << indent << "Camera:\n";
    this->Camera->PrintSelf(os,indent.GetNextIndent());
    }
  else
    {
    os << indent << "Camera: (none)\n";
    }
}

// Description:
// This causes the actor to be rendered. It, in turn, will render the actor's
// property and then mapper.
void vtkFollower::Render(vtkRenderer *ren)
{
  vtkMatrix4x4 *matrix = vtkMatrix4x4::New();

  /* render the property */
  if (!this->Property)
    {
    // force creation of a property
    this->GetProperty();
    }
  this->Property->Render(this, ren);

  /* render the texture */
  if (this->Texture) this->Texture->Render(ren);

  // make sure the device has the same matrix
  this->GetMatrix(*matrix);
  this->Device->SetUserMatrix(matrix);

  this->Device->Render(ren,this->Mapper);

  delete matrix;
}
<commit_msg>ERR: Follower not handling property properly.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkFollower.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1996 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include <stdlib.h>
#include <math.h>
#include "vtkMath.h"
#include "vtkFollower.h"
#include "vtkCamera.h"

// Description:
// Creates a follower with no camera set
vtkFollower::vtkFollower()
{
  this->Camera = NULL;
  this->Device = vtkActor::New();
}

vtkFollower::~vtkFollower()
{
  this->Device->Delete();
}

// Description:
// Copy the follower's composite 4x4 matrix into the matrix provided.
void vtkFollower::GetMatrix(vtkMatrix4x4& result)
{
  float *pos;
  vtkMatrix4x4 matrix;

  this->GetOrientation();
  this->Transform.Push();
  this->Transform.Identity();
  this->Transform.PreMultiply();

  // apply user defined matrix last if there is one
  if (this->UserMatrix)
    {
    this->Transform.Concatenate(*this->UserMatrix);
    }

  // first translate
  this->Transform.Translate(this->Position[0],
			    this->Position[1],
			    this->Position[2]);

  // shift to origin
  this->Transform.Translate(this->Origin[0],
			    this->Origin[1],
			    this->Origin[2]);

  // add the rotation to follow the camera
  if (this->Camera)
    {
    float distance, distance_old;
    float *vup;
    float twist = 0;
    float v1[3], v2[3], y_axis[3];
    double theta, dot, mag;
    double cosang;
    float vn[3];

    // calc the direction
    pos = this->Camera->GetPosition();
    vup = this->Camera->GetViewUp();

    // first rotate y
    distance = sqrt((this->Position[0]-pos[0])*(this->Position[0]-pos[0]) +
		    (this->Position[2]-pos[2])*(this->Position[2]-pos[2]));
    vn[0] = (pos[0] - this->Position[0])/distance;
    vn[1] = (pos[1] - this->Position[1])/distance;
    vn[2] = (pos[2] - this->Position[2])/distance;

    // rotate y
    if (distance > 0.0)
      {
      matrix[0][0] = (this->Position[2]-pos[2])/distance;
      matrix[0][2] = -1.0*(pos[0] - this->Position[0])/distance;
      }
    else
      {
      if (this->Position[1] < pos[1])
	{
	matrix[0][0] = -1.0;
	}
      else
	{
	matrix[0][0] = 1.0;
	}
      matrix[0][2] = 0.0;
      }
    matrix[0][1] = matrix[0][3] = 0.0;
    matrix[1][1] = 1.0;
    matrix[1][0] = matrix[1][2] = matrix[1][3] = 0.0;
    matrix[2][0] = -1.0*matrix[0][2];
    matrix[2][2] = matrix[0][0];
    matrix[2][3] = 0.0;
    matrix[2][1] = 0.0;
    matrix[3][3] = 1.0;
    matrix[3][0] = matrix[3][1] = matrix[3][2] = 0.0;
    this->Transform.Concatenate(matrix);

    // now rotate x
    distance_old = distance;
    distance = sqrt((this->Position[0]-pos[0])*(this->Position[0]-pos[0]) +
		    (this->Position[1]-pos[1])*(this->Position[1]-pos[1]) +
		    (this->Position[2]-pos[2])*(this->Position[2]-pos[2]));
    matrix[0][0] = 1.0;
    matrix[0][1] = matrix[0][2] = matrix[0][3] = 0.0;
    matrix[1][1] = distance_old/distance;
    matrix[1][2] = (this->Position[1] - pos[1])/distance;
    matrix[1][0] = matrix[1][3] = 0.0;
    matrix[2][1] = -1.0*matrix[1][2];
    matrix[2][2] = matrix[1][1];
    matrix[2][3] = 0.0;
    matrix[2][0] = 0.0;
    matrix[3][3] = 1.0;
    matrix[3][0] = matrix[3][1] = matrix[3][2] = 0.0;
    this->Transform.Concatenate(matrix);

    // calc the twist
    // compute: vn X ( vup X vn)
    // and:     vn X ( y-axis X vn)
    // then find the angle between the two projected vectors
    //
    y_axis[0] = y_axis[2] = 0.0; y_axis[1] = 1.0;

    // bump the view normal if it is parallel to the y-axis
    //
    if ((vn[0] == 0.0) && (vn[2] == 0.0))
      vn[2] = 0.01*vn[1];

    // first project the view_up onto the view_plane
    //
    vtkMath::Cross(vup, vn, v1);
    vtkMath::Cross(vn, v1, v1);

    // then project the y-axis onto the view plane
    //
    vtkMath::Cross(y_axis, vn, v2);
    vtkMath::Cross(vn, v2, v2);

    // then find the angle between the two projected vectors
    //
    dot = v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
    mag = sqrt((double)(v1[0]*v1[0] + v1[1]*v1[1] + v1[2]*v1[2]));
    mag *= sqrt((double)(v2[0]*v2[0] + v2[1]*v2[1] + v2[2]*v2[2]));

    // make sure we dont divide by 0
    if (mag != 0.0)
      {
      cosang = dot / mag;
      if (cosang < -1.0) cosang = -1.0;
      if (cosang > 1.0) cosang = 1.0;
      theta = acos(cosang);
      }
    else
      theta = 0.0;

    // now see if the angle is positive or negative
    //
    vtkMath::Cross(v1, v2, v1);
    dot = v1[0]*vn[0] + v1[1]*vn[1] + v1[2]*vn[2];

    twist = (theta);
    if (dot < 0.0)
      twist = -twist;

    // now rotate z (twist)
    matrix[0][0] = cos(-twist);
    matrix[0][1] = sin(-twist);
    matrix[0][2] = matrix[0][3] = 0.0;
    matrix[1][0] = -1.0*matrix[0][1];
    matrix[1][1] = matrix[0][0];
    matrix[1][2] = matrix[1][3] = 0.0;
    matrix[2][1] = 0.0;
    matrix[2][2] = 1.0;
    matrix[2][3] = 0.0;
    matrix[2][0] = 0.0;
    matrix[3][3] = 1.0;
    matrix[3][0] = matrix[3][1] = matrix[3][2] = 0.0;
    this->Transform.Concatenate(matrix);

    // rotate y by 180 to get the positive zaxis instead of negative
    this->Transform.RotateY(180);
    }

  // rotate
  this->Transform.RotateZ(this->Orientation[2]);
  this->Transform.RotateX(this->Orientation[0]);
  this->Transform.RotateY(this->Orientation[1]);

  // scale
  this->Transform.Scale(this->Scale[0],
			this->Scale[1],
			this->Scale[2]);

  // shift back from origin
  this->Transform.Translate(-this->Origin[0],
			    -this->Origin[1],
			    -this->Origin[2]);

  result = this->Transform.GetMatrix();

  this->Transform.Pop();
}

void vtkFollower::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkActor::PrintSelf(os,indent);

  if ( this->Camera )
    {
    os << indent << "Camera:\n";
    this->Camera->PrintSelf(os,indent.GetNextIndent());
    }
  else
    {
    os << indent << "Camera: (none)\n";
    }
}

// Description:
// This causes the actor to be rendered. It, in turn, will render the actor's
// property and then mapper.
void vtkFollower::Render(vtkRenderer *ren)
{
  vtkMatrix4x4 *matrix = vtkMatrix4x4::New();

  /* render the property */
  if (!this->Property)
    {
    // force creation of a property
    this->GetProperty();
    }
  this->Device->SetProperty (this->Property);
  this->Property->Render(this, ren);

  /* render the texture */
  if (this->Texture) this->Texture->Render(ren);

  // make sure the device has the same matrix
  this->GetMatrix(*matrix);
  this->Device->SetUserMatrix(matrix);

  this->Device->Render(ren,this->Mapper);

  delete matrix;
}
<|endoftext|>


<commit_before>#include "HeaderModifier.hpp"
#include "../Core/Core.hpp"

namespace
{
	NETStringList& _getProperBankBy(NECodeType::CodeType codetype)
	{
		NEScriptEditor::Banks& banks = Editor::getInstance().getScriptEditor().getBanks();

		switch(codetype)
		{
		case NECodeType::NAME:		return banks.getNameBank();
		case NECodeType::SCRIPT:	return banks.getScriptBank();
		case NECodeType::GROUP:		return banks.getGroupBank();
		case NECodeType::PRIORITY:	return banks.getPriorityBank();
		}

		NETStringList* nullpointer = 0x00;
		return *nullpointer;
	}

	const NETStringList& _getProperBankBy(int index)
	{
		const NEScriptEditor::Banks& banks = Editor::getInstance().getScriptEditor().getBanks();

		switch(index)
		{
		case 0:	return banks.getNameBank();
		case 1: return banks.getScriptBank();
		case 2: return banks.getGroupBank();
		case 3: return banks.getPriorityBank();
		}

		NETStringList* nullpointer = 0x00;
		return *nullpointer;
	}
}

void HeaderModifier::CodePopUpMenu::onItemChoosed(type_index index, const NEString& chosen_content)
{
	if(	_codetype < NECodeType::NAME	||
		_codetype > NECodeType::PRIORITY)
	{
		::Core::pushMessage("ERROR: ߸ CodeTypeԴϴ.");
		delete_me = true;
		return;
	}
	NEScriptEditor& ed = Editor::getInstance().getScriptEditor();

	switch(index)
	{
	case 0:
		//	ο ڵ :
		if(_codetype == NECodeType::SCRIPT)
			_onModifyCodeName();
		else
			_onAddNewCode();
		break;

	case 1:	//	̸ ϱ
		_onModifyCodeName();
		break;

	case 2:	//	ڵ ϱ
		_onRemoveCode();
		break;

	default:
		::Core::pushMessage("ERROR: ׷  ϴ.");
		return;
	}
}

void HeaderModifier::CodePopUpMenu::_onModifyCodeName()
{
	NETStringList& bank = _getProperBankBy(_codetype);
	call(StringInputWindow(bank[_code]));
	delete_me = true;
}

void HeaderModifier::CodePopUpMenu::_onAddNewCode()
{
	if( ! _code)
	{
		::Core::pushMessage("ERROR: 0 ڵ ⺻ ڵԴϴ. ߰ /  Ұմϴ.");
		return;
	}

	NEScriptEditor& ed = Editor::getInstance().getScriptEditor();

	type_result result = 0;
	switch(_codetype)
	{
	case NECodeType::NAME:		result = ed.insertNameCode(_code);		break;
	case NECodeType::GROUP:		result = ed.insertGroupCode(_code);		break;
	case NECodeType::PRIORITY:	result = ed.insertPriorityCode(_code);	break;
	}

	if( ! NEResult::hasError(result))
		_onModifyCodeName();
}

void HeaderModifier::CodePopUpMenu::_onRemoveCode()
{
	if( ! _code)
	{
		::Core::pushMessage("ERROR: 0 ڵ ⺻ ڵԴϴ. ߰ /  Ұմϴ.");
		return;
	}
	NEScriptEditor& ed = Editor::getInstance().getScriptEditor();

	switch(_codetype)
	{
	case NECodeType::NAME:		ed.removeNameCode(_code);		break;
	case NECodeType::GROUP:		ed.removeGroupCode(_code);		break;
	case NECodeType::PRIORITY:	ed.removePriorityCode(_code);	break;
	}

	delete_me = true;
}

void HeaderModifier::onItemChoosed(type_index index, const NEString& chosen_content)
{
	NEScriptManager::ScriptHeader& h = Editor::getInstance().getScriptEditor().getScriptHeader();
	NECodeType::CodeType ct = NECodeType::UNDEFINED;
	switch(index)
	{
	case 0:	//	̸ ϱ
		call( StringInputWindow(h.getName()));
		break;

	case 1:
		call( StringInputWindow(h.getDeveloper()));
		break;

	case 2:
		::Core::pushMessage("Revision ڵ ˴ϴ.");
		break;

	case 3:
		call( StringInputWindow(h.getReleaseDate()));
		break;

	case 4:
		call( StringInputWindow(h.getComment()));
		break;

	case 5:
		call( StringInputWindow(h.getContact()));
		break;

	case 6:	//	Bank ý
		ct = NECodeType::NAME;
	case 7:
		if(ct == NECodeType::UNDEFINED)
			ct = NECodeType::SCRIPT;
	case 8:
		if(ct == NECodeType::UNDEFINED)
			ct = NECodeType::GROUP;
	case 9:
		if(ct == NECodeType::UNDEFINED)
			ct = NECodeType::PRIORITY;

		{
			type_code code = codes_display_indexes[index-6];
			if(code != -1)
				call(CodePopUpMenu(ct, code));
		}
		break;
	}
}

void HeaderModifier::_pushCodeLists()
{
	const NEScriptEditor::Banks& banks = Editor::getInstance().getScriptEditor().getBanks();

	for(int code_type_n=0; code_type_n < codes_display_indexes.getLength(); code_type_n++)
	{
		NEString to_show = (list.choosed == code_type_n + 6) ? "<-" : "  ";

		switch(code_type_n)
		{
		case 0:	to_show += "[NAME] "; break;
		case 1: to_show += "[SCRI] "; break;
		case 2: to_show += "[GROU] "; break;
		case 3: to_show += "[PRIO] "; break;
		}

		int index = codes_display_indexes[code_type_n];
		switch(index)
		{
		case -2:
			to_show += "NEW";
			break;

		case -1:
			to_show += _generateCodeListNames(code_type_n);
			break;

		default:
			{
				to_show += NEString(index) + "th: ";
				if(index >= 0)
					to_show += _getProperBankBy(code_type_n)[index];
			}
		}

		if(list.choosed == code_type_n + 6)
		to_show += "->";
		list.items.push(to_show);
	}
}

NE::NEString HeaderModifier::_generateCodeListNames(int index)
{
	NEString to_show = "CODES: ";
	const NETStringList& bank = _getProperBankBy(index);

	int n=0;
	for(const NETStringList::Iterator* i = bank.getIterator(0); i ;i = i->getNext())
	{
		to_show += i->getValue().extract(0, 4) + "[" + n++ + "] ";	//	5ھ

		if(to_show.getLength() > 23)								//	ִ 20ڱ
			break;
	}

	return to_show;
}

void HeaderModifier::onKeyPressed(char inputed)
{
	int codetype = list.choosed - 6;
	if(codetype >= 0 && codetype <= 3)
	{
		const NETStringList& bank = _getProperBankBy(codetype);

		switch(inputed)
		{
		case LEFT:
			if(codes_display_indexes[codetype] > -2)
				codes_display_indexes[codetype]--;
			break;

		case RIGHT:
			if(codes_display_indexes[codetype] < bank.getLengthLastIndex())
				codes_display_indexes[codetype]++;
			break;
		}
	}

	ListWindow::onKeyPressed(inputed);

	onUpdateData();
}<commit_msg>FIX: HeaderModifier의 Code 전체보기가 짤리는 UI 개선<commit_after>#include "HeaderModifier.hpp"
#include "../Core/Core.hpp"

namespace
{
	NETStringList& _getProperBankBy(NECodeType::CodeType codetype)
	{
		NEScriptEditor::Banks& banks = Editor::getInstance().getScriptEditor().getBanks();

		switch(codetype)
		{
		case NECodeType::NAME:		return banks.getNameBank();
		case NECodeType::SCRIPT:	return banks.getScriptBank();
		case NECodeType::GROUP:		return banks.getGroupBank();
		case NECodeType::PRIORITY:	return banks.getPriorityBank();
		}

		NETStringList* nullpointer = 0x00;
		return *nullpointer;
	}

	const NETStringList& _getProperBankBy(int index)
	{
		const NEScriptEditor::Banks& banks = Editor::getInstance().getScriptEditor().getBanks();

		switch(index)
		{
		case 0:	return banks.getNameBank();
		case 1: return banks.getScriptBank();
		case 2: return banks.getGroupBank();
		case 3: return banks.getPriorityBank();
		}

		NETStringList* nullpointer = 0x00;
		return *nullpointer;
	}
}

void HeaderModifier::CodePopUpMenu::onItemChoosed(type_index index, const NEString& chosen_content)
{
	if(	_codetype < NECodeType::NAME	||
		_codetype > NECodeType::PRIORITY)
	{
		::Core::pushMessage("ERROR: ߸ CodeTypeԴϴ.");
		delete_me = true;
		return;
	}
	NEScriptEditor& ed = Editor::getInstance().getScriptEditor();

	switch(index)
	{
	case 0:
		//	ο ڵ :
		if(_codetype == NECodeType::SCRIPT)
			_onModifyCodeName();
		else
			_onAddNewCode();
		break;

	case 1:	//	̸ ϱ
		_onModifyCodeName();
		break;

	case 2:	//	ڵ ϱ
		_onRemoveCode();
		break;

	default:
		::Core::pushMessage("ERROR: ׷  ϴ.");
		return;
	}
}

void HeaderModifier::CodePopUpMenu::_onModifyCodeName()
{
	NETStringList& bank = _getProperBankBy(_codetype);
	call(StringInputWindow(bank[_code]));
	delete_me = true;
}

void HeaderModifier::CodePopUpMenu::_onAddNewCode()
{
	if( ! _code)
	{
		::Core::pushMessage("ERROR: 0 ڵ ⺻ ڵԴϴ. ߰ /  Ұմϴ.");
		return;
	}

	NEScriptEditor& ed = Editor::getInstance().getScriptEditor();

	type_result result = 0;
	switch(_codetype)
	{
	case NECodeType::NAME:		result = ed.insertNameCode(_code);		break;
	case NECodeType::GROUP:		result = ed.insertGroupCode(_code);		break;
	case NECodeType::PRIORITY:	result = ed.insertPriorityCode(_code);	break;
	}

	if( ! NEResult::hasError(result))
		_onModifyCodeName();
}

void HeaderModifier::CodePopUpMenu::_onRemoveCode()
{
	if( ! _code)
	{
		::Core::pushMessage("ERROR: 0 ڵ ⺻ ڵԴϴ. ߰ /  Ұմϴ.");
		return;
	}
	NEScriptEditor& ed = Editor::getInstance().getScriptEditor();

	switch(_codetype)
	{
	case NECodeType::NAME:		ed.removeNameCode(_code);		break;
	case NECodeType::GROUP:		ed.removeGroupCode(_code);		break;
	case NECodeType::PRIORITY:	ed.removePriorityCode(_code);	break;
	}

	delete_me = true;
}

void HeaderModifier::onItemChoosed(type_index index, const NEString& chosen_content)
{
	NEScriptManager::ScriptHeader& h = Editor::getInstance().getScriptEditor().getScriptHeader();
	NECodeType::CodeType ct = NECodeType::UNDEFINED;
	switch(index)
	{
	case 0:	//	̸ ϱ
		call( StringInputWindow(h.getName()));
		break;

	case 1:
		call( StringInputWindow(h.getDeveloper()));
		break;

	case 2:
		::Core::pushMessage("Revision ڵ ˴ϴ.");
		break;

	case 3:
		call( StringInputWindow(h.getReleaseDate()));
		break;

	case 4:
		call( StringInputWindow(h.getComment()));
		break;

	case 5:
		call( StringInputWindow(h.getContact()));
		break;

	case 6:	//	Bank ý
		ct = NECodeType::NAME;
	case 7:
		if(ct == NECodeType::UNDEFINED)
			ct = NECodeType::SCRIPT;
	case 8:
		if(ct == NECodeType::UNDEFINED)
			ct = NECodeType::GROUP;
	case 9:
		if(ct == NECodeType::UNDEFINED)
			ct = NECodeType::PRIORITY;

		{
			type_code code = codes_display_indexes[index-6];
			if(code != -1)
				call(CodePopUpMenu(ct, code));
		}
		break;
	}
}

void HeaderModifier::_pushCodeLists()
{
	const NEScriptEditor::Banks& banks = Editor::getInstance().getScriptEditor().getBanks();

	for(int code_type_n=0; code_type_n < codes_display_indexes.getLength(); code_type_n++)
	{
		NEString to_show = (list.choosed == code_type_n + 6) ? "<-" : "  ";

		switch(code_type_n)
		{
		case 0:	to_show += "[NAME] "; break;
		case 1: to_show += "[SCRI] "; break;
		case 2: to_show += "[GROU] "; break;
		case 3: to_show += "[PRIO] "; break;
		}

		int index = codes_display_indexes[code_type_n];
		switch(index)
		{
		case -2:
			to_show += "NEW";
			break;

		case -1:
			to_show += _generateCodeListNames(code_type_n);
			break;

		default:
			{
				to_show += NEString(index) + "th: ";
				if(index >= 0)
					to_show += _getProperBankBy(code_type_n)[index];
			}
		}

		if(list.choosed == code_type_n + 6)
		to_show += "->";
		list.items.push(to_show);
	}
}

NE::NEString HeaderModifier::_generateCodeListNames(int index)
{
	NEString to_show = "CODES: ";
	const NETStringList& bank = _getProperBankBy(index);

	int n=0;
	for(const NETStringList::Iterator* i = bank.getIterator(0); i ;i = i->getNext())
	{
		to_show += i->getValue().extract(0, 4) + "[" + n++ + "] ";	//	5ھ

		if(to_show.getLength() > 40)
		{
			to_show += "...";
			break;
		}
	}

	return to_show;
}

void HeaderModifier::onKeyPressed(char inputed)
{
	int codetype = list.choosed - 6;
	if(codetype >= 0 && codetype <= 3)
	{
		const NETStringList& bank = _getProperBankBy(codetype);

		switch(inputed)
		{
		case LEFT:
			if(codes_display_indexes[codetype] > -2)
				codes_display_indexes[codetype]--;
			break;

		case RIGHT:
			if(codes_display_indexes[codetype] < bank.getLengthLastIndex())
				codes_display_indexes[codetype]++;
			break;
		}
	}

	ListWindow::onKeyPressed(inputed);

	onUpdateData();
}<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file ContractionState.cxx
 ** Manages visibility of lines for folding and wrapping.
 **/
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <string.h>

#include "Platform.h"

#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

ContractionState::ContractionState() : visible(0), expanded(0), heights(0), displayLines(0), linesInDocument(1) {
	//InsertLine(0);
}

ContractionState::~ContractionState() {
	Clear();
}

void ContractionState::EnsureData() {
	if (OneToOne()) {
		visible = new RunStyles();
		expanded = new RunStyles();
		heights = new RunStyles();
		displayLines = new Partitioning(4);
		InsertLines(0, linesInDocument);
	}
}

void ContractionState::Clear() {
	delete visible;
	visible = 0;
	delete expanded;
	expanded = 0;
	delete heights;
	heights = 0;
	delete displayLines;
	displayLines = 0;
	linesInDocument = 1;
}

int ContractionState::LinesInDoc() const {
	if (OneToOne()) {
		return linesInDocument;
	} else {
		return displayLines->Partitions() - 1;
	}
}

int ContractionState::LinesDisplayed() const {
	if (OneToOne()) {
		return linesInDocument;
	} else {
		return displayLines->PositionFromPartition(LinesInDoc());
	}
}

int ContractionState::DisplayFromDoc(int lineDoc) const {
	if (OneToOne()) {
		return lineDoc;
	} else {
		if (lineDoc > displayLines->Partitions())
			lineDoc = displayLines->Partitions();
		return displayLines->PositionFromPartition(lineDoc);
	}
}

int ContractionState::DocFromDisplay(int lineDisplay) const {
	if (OneToOne()) {
		return lineDisplay;
	} else {
		if (lineDisplay <= 0) {
			return 0;
		}
		if (lineDisplay > LinesDisplayed()) {
			return displayLines->PartitionFromPosition(LinesDisplayed());
		}
		int lineDoc = displayLines->PartitionFromPosition(lineDisplay);
		PLATFORM_ASSERT(GetVisible(lineDoc));
		return lineDoc;
	}
}

void ContractionState::InsertLine(int lineDoc) {
	if (OneToOne()) {
		linesInDocument++;
	} else {
		visible->InsertSpace(lineDoc, 1);
		visible->SetValueAt(lineDoc, 1);
		expanded->InsertSpace(lineDoc, 1);
		expanded->SetValueAt(lineDoc, 1);
		heights->InsertSpace(lineDoc, 1);
		heights->SetValueAt(lineDoc, 1);
		int lineDisplay = DisplayFromDoc(lineDoc);
		displayLines->InsertPartition(lineDoc, lineDisplay);
		displayLines->InsertText(lineDoc, 1);
	}
}

void ContractionState::InsertLines(int lineDoc, int lineCount) {
	for (int l = 0; l < lineCount; l++) {
		InsertLine(lineDoc + l);
	}
	Check();
}

void ContractionState::DeleteLine(int lineDoc) {
	if (OneToOne()) {
		linesInDocument--;
	} else {
		if (GetVisible(lineDoc)) {
			displayLines->InsertText(lineDoc, -heights->ValueAt(lineDoc));
		}
		displayLines->RemovePartition(lineDoc);
		visible->DeleteRange(lineDoc, 1);
		expanded->DeleteRange(lineDoc, 1);
		heights->DeleteRange(lineDoc, 1);
	}
}

void ContractionState::DeleteLines(int lineDoc, int lineCount) {
	for (int l = 0; l < lineCount; l++) {
		DeleteLine(lineDoc);
	}
	Check();
}

bool ContractionState::GetVisible(int lineDoc) const {
	if (OneToOne()) {
		return true;
	} else {
		if (lineDoc >= visible->Length())
			return true;
		return visible->ValueAt(lineDoc) == 1;
	}
}

bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible_) {
	if (OneToOne() && visible_) {
		return false;
	} else {
		EnsureData();
		int delta = 0;
		Check();
		if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < LinesInDoc())) {
			for (int line = lineDocStart; line <= lineDocEnd; line++) {
				if (GetVisible(line) != visible_) {
					int difference = visible_ ? heights->ValueAt(line) : -heights->ValueAt(line);
					visible->SetValueAt(line, visible_ ? 1 : 0);
					displayLines->InsertText(line, difference);
					delta += difference;
				}
			}
		} else {
			return false;
		}
		Check();
		return delta != 0;
	}
}

bool ContractionState::GetExpanded(int lineDoc) const {
	if (OneToOne()) {
		return true;
	} else {
		Check();
		return expanded->ValueAt(lineDoc) == 1;
	}
}

bool ContractionState::SetExpanded(int lineDoc, bool expanded_) {
	if (OneToOne() && expanded_) {
		return false;
	} else {
		EnsureData();
		if (expanded_ != (expanded->ValueAt(lineDoc) == 1)) {
			expanded->SetValueAt(lineDoc, expanded_ ? 1 : 0);
			Check();
			return true;
		} else {
			Check();
			return false;
		}
	}
}

int ContractionState::GetHeight(int lineDoc) const {
	if (OneToOne()) {
		return 1;
	} else {
		return heights->ValueAt(lineDoc);
	}
}

// Set the number of display lines needed for this line.
// Return true if this is a change.
bool ContractionState::SetHeight(int lineDoc, int height) {
	if (OneToOne() && (height == 1)) {
		return false;
	} else {
		EnsureData();
		if (GetHeight(lineDoc) != height) {
			if (GetVisible(lineDoc)) {
				displayLines->InsertText(lineDoc, height - GetHeight(lineDoc));
			}
			heights->SetValueAt(lineDoc, height);
			Check();
			return true;
		} else {
			Check();
			return false;
		}
	}
}

void ContractionState::ShowAll() {
	Clear();
}

// Debugging checks

void ContractionState::Check() const {
#ifdef CHECK_CORRECTNESS
	for (int vline = 0;vline < LinesDisplayed(); vline++) {
		const int lineDoc = DocFromDisplay(vline);
		PLATFORM_ASSERT(GetVisible(lineDoc));
	}
	for (int lineDoc = 0;lineDoc < LinesInDoc(); lineDoc++) {
		const int displayThis = DisplayFromDoc(lineDoc);
		const int displayNext = DisplayFromDoc(lineDoc + 1);
		const int height = displayNext - displayThis;
		PLATFORM_ASSERT(height >= 0);
		if (GetVisible(lineDoc)) {
			PLATFORM_ASSERT(GetHeight(lineDoc) == height);
		} else {
			PLATFORM_ASSERT(0 == height);
		}
	}
#endif
}
<commit_msg>Fixed bug when ShowAll called where linesInDocument was always reset to 1 which hid most of the file.<commit_after>// Scintilla source code edit control
/** @file ContractionState.cxx
 ** Manages visibility of lines for folding and wrapping.
 **/
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <string.h>

#include "Platform.h"

#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

ContractionState::ContractionState() : visible(0), expanded(0), heights(0), displayLines(0), linesInDocument(1) {
	//InsertLine(0);
}

ContractionState::~ContractionState() {
	Clear();
}

void ContractionState::EnsureData() {
	if (OneToOne()) {
		visible = new RunStyles();
		expanded = new RunStyles();
		heights = new RunStyles();
		displayLines = new Partitioning(4);
		InsertLines(0, linesInDocument);
	}
}

void ContractionState::Clear() {
	delete visible;
	visible = 0;
	delete expanded;
	expanded = 0;
	delete heights;
	heights = 0;
	delete displayLines;
	displayLines = 0;
}

int ContractionState::LinesInDoc() const {
	if (OneToOne()) {
		return linesInDocument;
	} else {
		return displayLines->Partitions() - 1;
	}
}

int ContractionState::LinesDisplayed() const {
	if (OneToOne()) {
		return linesInDocument;
	} else {
		return displayLines->PositionFromPartition(LinesInDoc());
	}
}

int ContractionState::DisplayFromDoc(int lineDoc) const {
	if (OneToOne()) {
		return lineDoc;
	} else {
		if (lineDoc > displayLines->Partitions())
			lineDoc = displayLines->Partitions();
		return displayLines->PositionFromPartition(lineDoc);
	}
}

int ContractionState::DocFromDisplay(int lineDisplay) const {
	if (OneToOne()) {
		return lineDisplay;
	} else {
		if (lineDisplay <= 0) {
			return 0;
		}
		if (lineDisplay > LinesDisplayed()) {
			return displayLines->PartitionFromPosition(LinesDisplayed());
		}
		int lineDoc = displayLines->PartitionFromPosition(lineDisplay);
		PLATFORM_ASSERT(GetVisible(lineDoc));
		return lineDoc;
	}
}

void ContractionState::InsertLine(int lineDoc) {
	if (OneToOne()) {
		linesInDocument++;
	} else {
		visible->InsertSpace(lineDoc, 1);
		visible->SetValueAt(lineDoc, 1);
		expanded->InsertSpace(lineDoc, 1);
		expanded->SetValueAt(lineDoc, 1);
		heights->InsertSpace(lineDoc, 1);
		heights->SetValueAt(lineDoc, 1);
		int lineDisplay = DisplayFromDoc(lineDoc);
		displayLines->InsertPartition(lineDoc, lineDisplay);
		displayLines->InsertText(lineDoc, 1);
	}
}

void ContractionState::InsertLines(int lineDoc, int lineCount) {
	for (int l = 0; l < lineCount; l++) {
		InsertLine(lineDoc + l);
	}
	Check();
}

void ContractionState::DeleteLine(int lineDoc) {
	if (OneToOne()) {
		linesInDocument--;
	} else {
		if (GetVisible(lineDoc)) {
			displayLines->InsertText(lineDoc, -heights->ValueAt(lineDoc));
		}
		displayLines->RemovePartition(lineDoc);
		visible->DeleteRange(lineDoc, 1);
		expanded->DeleteRange(lineDoc, 1);
		heights->DeleteRange(lineDoc, 1);
	}
}

void ContractionState::DeleteLines(int lineDoc, int lineCount) {
	for (int l = 0; l < lineCount; l++) {
		DeleteLine(lineDoc);
	}
	Check();
}

bool ContractionState::GetVisible(int lineDoc) const {
	if (OneToOne()) {
		return true;
	} else {
		if (lineDoc >= visible->Length())
			return true;
		return visible->ValueAt(lineDoc) == 1;
	}
}

bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible_) {
	if (OneToOne() && visible_) {
		return false;
	} else {
		EnsureData();
		int delta = 0;
		Check();
		if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < LinesInDoc())) {
			for (int line = lineDocStart; line <= lineDocEnd; line++) {
				if (GetVisible(line) != visible_) {
					int difference = visible_ ? heights->ValueAt(line) : -heights->ValueAt(line);
					visible->SetValueAt(line, visible_ ? 1 : 0);
					displayLines->InsertText(line, difference);
					delta += difference;
				}
			}
		} else {
			return false;
		}
		Check();
		return delta != 0;
	}
}

bool ContractionState::GetExpanded(int lineDoc) const {
	if (OneToOne()) {
		return true;
	} else {
		Check();
		return expanded->ValueAt(lineDoc) == 1;
	}
}

bool ContractionState::SetExpanded(int lineDoc, bool expanded_) {
	if (OneToOne() && expanded_) {
		return false;
	} else {
		EnsureData();
		if (expanded_ != (expanded->ValueAt(lineDoc) == 1)) {
			expanded->SetValueAt(lineDoc, expanded_ ? 1 : 0);
			Check();
			return true;
		} else {
			Check();
			return false;
		}
	}
}

int ContractionState::GetHeight(int lineDoc) const {
	if (OneToOne()) {
		return 1;
	} else {
		return heights->ValueAt(lineDoc);
	}
}

// Set the number of display lines needed for this line.
// Return true if this is a change.
bool ContractionState::SetHeight(int lineDoc, int height) {
	if (OneToOne() && (height == 1)) {
		return false;
	} else {
		EnsureData();
		if (GetHeight(lineDoc) != height) {
			if (GetVisible(lineDoc)) {
				displayLines->InsertText(lineDoc, height - GetHeight(lineDoc));
			}
			heights->SetValueAt(lineDoc, height);
			Check();
			return true;
		} else {
			Check();
			return false;
		}
	}
}

void ContractionState::ShowAll() {
	int lines = LinesInDoc();
	Clear();
	linesInDocument = lines;
}

// Debugging checks

void ContractionState::Check() const {
#ifdef CHECK_CORRECTNESS
	for (int vline = 0;vline < LinesDisplayed(); vline++) {
		const int lineDoc = DocFromDisplay(vline);
		PLATFORM_ASSERT(GetVisible(lineDoc));
	}
	for (int lineDoc = 0;lineDoc < LinesInDoc(); lineDoc++) {
		const int displayThis = DisplayFromDoc(lineDoc);
		const int displayNext = DisplayFromDoc(lineDoc + 1);
		const int height = displayNext - displayThis;
		PLATFORM_ASSERT(height >= 0);
		if (GetVisible(lineDoc)) {
			PLATFORM_ASSERT(GetHeight(lineDoc) == height);
		} else {
			PLATFORM_ASSERT(0 == height);
		}
	}
#endif
}
<|endoftext|>


<commit_before>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/c/experimental/gradients/math_grad.h"

#include "tensorflow/c/eager/c_api_test_util.h"
#include "tensorflow/c/eager/c_api_unified_experimental_internal.h"
#include "tensorflow/c/eager/unified_api_testutil.h"
#include "tensorflow/c/experimental/gradients/grad_test_helper.h"
#include "tensorflow/c/experimental/gradients/tape/tape_context.h"
#include "tensorflow/c/experimental/ops/math_ops.h"
#include "tensorflow/c/tf_status_helper.h"
#include "tensorflow/core/platform/test.h"

namespace tensorflow {
namespace gradients {
namespace internal {
namespace {

using tensorflow::TF_StatusPtr;

Status AddModel(AbstractContext* ctx,
                absl::Span<AbstractTensorHandle* const> inputs,
                absl::Span<AbstractTensorHandle*> outputs) {
  return ops::Add(ctx, inputs, outputs, "Add");
}

Status AddGradModel(AbstractContext* ctx,
                    absl::Span<AbstractTensorHandle* const> inputs,
                    absl::Span<AbstractTensorHandle*> outputs) {
  GradientRegistry registry;
  TF_RETURN_IF_ERROR(registry.Register("AddV2", AddRegisterer));

  Tape tape(/*persistent=*/false);
  tape.Watch(inputs[0]);
  tape.Watch(inputs[1]);
  std::vector<AbstractTensorHandle*> temp_outputs(1);
  AbstractContextPtr tape_ctx(new TapeContext(ctx, &tape, registry));
  TF_RETURN_IF_ERROR(ops::Add(tape_ctx.get(), inputs,
                              absl::MakeSpan(temp_outputs), "AddGrad"));

  TF_RETURN_IF_ERROR(tape.ComputeGradient(ctx, /*targets=*/temp_outputs,
                                          /*sources=*/inputs,
                                          /*output_gradients=*/{}, outputs));
  for (auto temp_output : temp_outputs) {
    temp_output->Unref();
  }
  return Status::OK();
}

class CppGradients
    : public ::testing::TestWithParam<std::tuple<const char*, bool, bool>> {
 protected:
  void SetUp() override {
    TF_StatusPtr status(TF_NewStatus());
    TF_SetTracingImplementation(std::get<0>(GetParam()), status.get());
    Status s = StatusFromTF_Status(status.get());
    ASSERT_EQ(errors::OK, s.code()) << s.error_message();

    {
      AbstractContext* ctx_raw = nullptr;
      Status s =
          BuildImmediateExecutionContext(std::get<1>(GetParam()), &ctx_raw);
      ASSERT_EQ(errors::OK, s.code()) << s.error_message();
      ctx_.reset(ctx_raw);
    }
  }

  AbstractContextPtr ctx_;

 public:
  bool UseMlir() const { return strcmp(std::get<0>(GetParam()), "mlir") == 0; }
  bool UseFunction() const { return std::get<2>(GetParam()); }
};

TEST_P(CppGradients, TestAddGrad) {
  AbstractTensorHandlePtr x;
  {
    AbstractTensorHandle* x_raw = nullptr;
    Status s = TestScalarTensorHandle(ctx_.get(), 2.0f, &x_raw);
    ASSERT_EQ(errors::OK, s.code()) << s.error_message();
    x.reset(x_raw);
  }

  AbstractTensorHandlePtr y;
  {
    AbstractTensorHandle* y_raw = nullptr;
    Status s = TestScalarTensorHandle(ctx_.get(), 2.0f, &y_raw);
    ASSERT_EQ(errors::OK, s.code()) << s.error_message();
    y.reset(y_raw);
  }

  ASSERT_NO_FATAL_FAILURE(CompareNumericalAndAutodiffGradients(
      AddModel, AddGradModel, ctx_.get(), {x.get(), y.get()}, UseFunction()));
}

#ifdef PLATFORM_GOOGLE
INSTANTIATE_TEST_SUITE_P(
    UnifiedCAPI, CppGradients,
    ::testing::Combine(::testing::Values("graphdef", "mlir"),
                       /*tfrt*/ ::testing::Values(false),
                       /*use_function*/ ::testing::Values(true, false)));
#else
INSTANTIATE_TEST_SUITE_P(
    UnifiedCAPI, CppGradients,
    ::testing::Combine(::testing::Values("graphdef", "mlir"),
                       /*tfrt*/ ::testing::Values(false),
                       /*use_function*/ ::testing::Values(true, false)));
#endif
}  // namespace
}  // namespace internal
}  // namespace gradients
}  // namespace tensorflow
<commit_msg>add `TestExpGrad` to `math_grad_test`<commit_after>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/c/experimental/gradients/math_grad.h"

#include "tensorflow/c/eager/c_api_test_util.h"
#include "tensorflow/c/eager/c_api_unified_experimental_internal.h"
#include "tensorflow/c/eager/unified_api_testutil.h"
#include "tensorflow/c/experimental/gradients/grad_test_helper.h"
#include "tensorflow/c/experimental/gradients/tape/tape_context.h"
#include "tensorflow/c/experimental/ops/math_ops.h"
#include "tensorflow/c/tf_status_helper.h"
#include "tensorflow/core/platform/test.h"

namespace tensorflow {
namespace gradients {
namespace internal {
namespace {

using tensorflow::TF_StatusPtr;

Status AddModel(AbstractContext* ctx,
                absl::Span<AbstractTensorHandle* const> inputs,
                absl::Span<AbstractTensorHandle*> outputs) {
  return ops::Add(ctx, inputs, outputs, "Add");
}

Status AddGradModel(AbstractContext* ctx,
                    absl::Span<AbstractTensorHandle* const> inputs,
                    absl::Span<AbstractTensorHandle*> outputs) {
  GradientRegistry registry;
  TF_RETURN_IF_ERROR(registry.Register("AddV2", AddRegisterer));

  Tape tape(/*persistent=*/false);
  tape.Watch(inputs[0]);
  tape.Watch(inputs[1]);
  std::vector<AbstractTensorHandle*> temp_outputs(1);
  AbstractContextPtr tape_ctx(new TapeContext(ctx, &tape, registry));
  TF_RETURN_IF_ERROR(ops::Add(tape_ctx.get(), inputs,
                              absl::MakeSpan(temp_outputs), "AddGrad"));

  TF_RETURN_IF_ERROR(tape.ComputeGradient(ctx, /*targets=*/temp_outputs,
                                          /*sources=*/inputs,
                                          /*output_gradients=*/{}, outputs));
  for (auto temp_output : temp_outputs) {
    temp_output->Unref();
  }
  return Status::OK();
}

Status ExpModel(AbstractContext* ctx,
                absl::Span<AbstractTensorHandle* const> inputs,
                absl::Span<AbstractTensorHandle*> outputs) {
  return ops::Exp(ctx, inputs, outputs, "Exp");
}

Status ExpGradModel(AbstractContext* ctx,
                    absl::Span<AbstractTensorHandle* const> inputs,
                    absl::Span<AbstractTensorHandle*> outputs) {
  GradientRegistry registry;
  TF_RETURN_IF_ERROR(registry.Register("Exp", ExpRegisterer));

  Tape tape(/*persistent=*/false);
  tape.Watch(inputs[0]);
  std::vector<AbstractTensorHandle*> temp_outputs(1);
  AbstractContextPtr tape_ctx(new TapeContext(ctx, &tape, registry));
  TF_RETURN_IF_ERROR(ops::Exp(tape_ctx.get(), inputs,
                              absl::MakeSpan(temp_outputs), "ExpGrad"));

  TF_RETURN_IF_ERROR(tape.ComputeGradient(ctx, /*targets=*/temp_outputs,
                                          /*sources=*/inputs,
                                          /*output_gradients=*/{}, outputs));
  for (auto temp_output : temp_outputs) {
    temp_output->Unref();
  }
  return Status::OK();
}

class CppGradients
    : public ::testing::TestWithParam<std::tuple<const char*, bool, bool>> {
 protected:
  void SetUp() override {
    TF_StatusPtr status(TF_NewStatus());
    TF_SetTracingImplementation(std::get<0>(GetParam()), status.get());
    Status s = StatusFromTF_Status(status.get());
    ASSERT_EQ(errors::OK, s.code()) << s.error_message();

    {
      AbstractContext* ctx_raw = nullptr;
      Status s =
          BuildImmediateExecutionContext(std::get<1>(GetParam()), &ctx_raw);
      ASSERT_EQ(errors::OK, s.code()) << s.error_message();
      ctx_.reset(ctx_raw);
    }
  }

  AbstractContextPtr ctx_;

 public:
  bool UseMlir() const { return strcmp(std::get<0>(GetParam()), "mlir") == 0; }
  bool UseFunction() const { return std::get<2>(GetParam()); }
};

TEST_P(CppGradients, TestAddGrad) {
  AbstractTensorHandlePtr x;
  {
    AbstractTensorHandle* x_raw = nullptr;
    Status s = TestScalarTensorHandle(ctx_.get(), 2.0f, &x_raw);
    ASSERT_EQ(errors::OK, s.code()) << s.error_message();
    x.reset(x_raw);
  }

  AbstractTensorHandlePtr y;
  {
    AbstractTensorHandle* y_raw = nullptr;
    Status s = TestScalarTensorHandle(ctx_.get(), 2.0f, &y_raw);
    ASSERT_EQ(errors::OK, s.code()) << s.error_message();
    y.reset(y_raw);
  }

  ASSERT_NO_FATAL_FAILURE(CompareNumericalAndAutodiffGradients(
      AddModel, AddGradModel, ctx_.get(), {x.get(), y.get()}, UseFunction()));
}

TEST_P(CppGradients, TestExpGrad) {
  AbstractTensorHandlePtr x;
  {
    AbstractTensorHandle* x_raw = nullptr;
    Status s = TestScalarTensorHandle(ctx_.get(), 2.0f, &x_raw);
    ASSERT_EQ(errors::OK, s.code()) << s.error_message();
    x.reset(x_raw);
  }

  ASSERT_NO_FATAL_FAILURE(CompareNumericalAndAutodiffGradients(
      ExpModel, ExpGradModel, ctx_.get(), {x.get()}, UseFunction()));
}

#ifdef PLATFORM_GOOGLE
INSTANTIATE_TEST_SUITE_P(
    UnifiedCAPI, CppGradients,
    ::testing::Combine(::testing::Values("graphdef", "mlir"),
                       /*tfrt*/ ::testing::Values(false),
                       /*use_function*/ ::testing::Values(true, false)));
#else
INSTANTIATE_TEST_SUITE_P(
    UnifiedCAPI, CppGradients,
    ::testing::Combine(::testing::Values("graphdef", "mlir"),
                       /*tfrt*/ ::testing::Values(false),
                       /*use_function*/ ::testing::Values(true, false)));
#endif
}  // namespace
}  // namespace internal
}  // namespace gradients
}  // namespace tensorflow
<|endoftext|>


<commit_before>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
//

#include "mfem.hpp"
#include "catch.hpp"
#include <cmath>

using namespace mfem;

TEST_CASE("First order ODE methods",
          "[ODE1]")
{
    double tol = 0.1;

   /** Class for simple linear first order ODE.
    *
    *     du/dt  + a u = 0
    *
    */
   class ODE : public TimeDependentOperator
   {
   protected:
      DenseMatrix A;
   public:
      ODE(double a00,double a01,double a10,double a11) : TimeDependentOperator(2, 0.0)
      {
         A.SetSize(2,2);
         A(0,0) = a00;
         A(0,1) = a01;
         A(1,0) = a10;
         A(1,1) = a11;
      };

      virtual void Mult(const Vector &u, Vector &dudt)  const
      {
         A.Mult(u,dudt);
         dudt.Neg();
      }

      virtual void ImplicitSolve(const double dt, const Vector &u, Vector &dudt)
      {
         DenseMatrix I(2,2),T(2,2);
         I =  0.0;
         I(0,0) = I(1,1) = 1.0;
         Add(I,A,dt,T);
         T.Invert();

         Vector r(2);
         A.Mult(u,r);
         r.Neg();
         T.Mult(r,dudt);
      }

      virtual ~ODE() {};
   };

   /** Class for checking order of convergence of first order ODE.
    */
   class CheckODE
   {
   protected:
      int ti_steps,levels;
      Vector u0;
      double t_final,dt;
      ODE *oper;
   public:
      CheckODE()
      {
         oper = new ODE(0.0, 1.0, -1.0, 0.0);
         ti_steps = 100;
         levels   = 6;

         u0.SetSize(2);
         u0    = 1.0;

         t_final = M_PI;
         dt = t_final/double(ti_steps);
      };

      double order(ODESolver* ode_solver)
      {
         ode_solver->Init(*oper);

         double dt,t;
         Vector u(2);
         Vector err(levels);
         int steps = ti_steps;

         t = 0.0;
         dt = t_final/double(steps);
         u = u0;
         for (int ti = 0; ti< steps; ti++)
         {
            ode_solver->Step(u, t, dt);
         }
         u +=u0;
         err[0] = u.Norml2();

         std::cout<<std::setw(12)<<"Error"
                  <<std::setw(12)<<"Ratio"
                  <<std::setw(12)<<"Order"<<std::endl;
         std::cout<<std::setw(12)<<err[0]<<std::endl;

         for (int l = 1; l< levels; l++)
         {
            t = 0.0;
            steps *=2;
            dt = t_final/double(steps);
            u = u0;
            for (int ti = 0; ti< steps; ti++)
            {
               ode_solver->Step(u, t, dt);
            }
            u +=u0;
            err[l] = u.Norml2();
            std::cout<<std::setw(12)<<err[l]
                     <<std::setw(12)<<err[l-1]/err[l]
                     <<std::setw(12)<<log(err[l-1]/err[l])/log(2) <<std::endl;
         }
         delete ode_solver;

         return log(err[levels-2]/err[levels-1])/log(2);
      }
      virtual ~CheckODE() {delete oper;};
   };
   CheckODE check;

   // Implicit L-stable methods
   SECTION("BackwardEuler")
   {
      std::cout <<"\nTesting BackwardEuler" << std::endl;
      REQUIRE(check.order(new BackwardEulerSolver) + tol > 1.0 );
   }

   SECTION("SDIRK23Solver(2)")
   {
      std::cout <<"\nTesting SDIRK23Solver(2)" << std::endl;
      REQUIRE(check.order(new SDIRK23Solver(2)) + tol > 2.0 );
   }

   SECTION("SDIRK33Solver")
   {
      std::cout <<"\nTesting SDIRK33Solver" << std::endl;
      REQUIRE(check.order(new SDIRK33Solver) + tol > 3.0 );
   }

   SECTION("ForwardEulerSolver")
   {
      std::cout <<"\nTesting ForwardEulerSolver" << std::endl;
      REQUIRE(check.order(new ForwardEulerSolver) + tol > 1.0 );
   }

   SECTION("RK2Solver(0.5)")
   {
      std::cout <<"\nTesting RK2Solver(0.5)" << std::endl;
      REQUIRE(check.order(new RK2Solver(0.5))+ tol > 2.0 );
   }

   SECTION("RK3SSPSolver")
   {
      std::cout <<"\nTesting RK3SSPSolver" << std::endl;
      REQUIRE(check.order(new RK3SSPSolver) + tol > 3.0 );
   }

   SECTION("RK4Solver")
   {
      std::cout <<"\nTesting RK4Solver" << std::endl;
      REQUIRE(check.order(new RK4Solver) + tol > 4.0 );
   }

   SECTION("ImplicitMidpointSolver")
   {
      std::cout <<"\nTesting ImplicitMidpointSolver" << std::endl;
      REQUIRE(check.order(new ImplicitMidpointSolver) + tol > 2.0 );
   }

   SECTION("SDIRK23Solver")
   {
      std::cout <<"\nTesting SDIRK23Solver" << std::endl;
      REQUIRE(check.order(new SDIRK23Solver) + tol > 3.0 );
   }

   SECTION("SDIRK34Solver")
   {
      std::cout <<"\nTesting SDIRK34Solver" << std::endl;
      REQUIRE(check.order(new SDIRK34Solver) + tol > 4.0 );
   }

   /*SECTION("GeneralizedAlphaSolver(0.0)")
   {
      std::cout <<"\nTesting GeneralizedAlphaSolver(0.0)" << std::endl;
      REQUIRE(check.order(new GeneralizedAlphaSolver(0.0)) + tol > 2.0 );
   }*/

  /* SECTION("GeneralizedAlphaSolver(0.5)")
   {
      std::cout <<"\nTesting GeneralizedAlphaSolver(0.5)" << std::endl;
      REQUIRE(check.order(new GeneralizedAlphaSolver(0.5)) + tol > 2.0 );
   }*/

   SECTION("GeneralizedAlphaSolver(1.0)")
   {
      std::cout <<"\nTesting GeneralizedAlphaSolver(1.0)" << std::endl;
      REQUIRE(check.order(new GeneralizedAlphaSolver(1.0)) + tol > 2.0 );
   }

   SECTION("AdamsBashforthSolver(1)")
   {
      std::cout <<"\nTesting AdamsBashforthSolver(1)" << std::endl;
      REQUIRE(check.order(new AdamsBashforthSolver(1)) + tol > 1.0 );
   }

   SECTION("AdamsBashforthSolver(2)")
   {
      std::cout <<"\nTesting AdamsBashforthSolver(2)" << std::endl;
      REQUIRE(check.order(new AdamsBashforthSolver(2)) + tol > 2.0 );
   }

   SECTION("AdamsBashforthSolver(3)")
   {
      std::cout <<"\nTesting AdamsBashforthSolver(3)" << std::endl;
      REQUIRE(check.order(new AdamsBashforthSolver(3)) + tol > 3.0 );
   }

   SECTION("AdamsBashforthSolver(4)")
   {
      std::cout <<"\nTesting AdamsBashforthSolver(4)" << std::endl;
      REQUIRE(check.order(new AdamsBashforthSolver(4)) + tol > 4.0 );
   }

   SECTION("AdamsBashforthSolver(5)")
   {
      std::cout <<"\nTesting AdamsBashforthSolver(5)" << std::endl;
      REQUIRE(check.order(new AdamsBashforthSolver(5)) + tol > 5.0 );
   }

   SECTION("AdamsMoultonSolver(1)")
   {
      std::cout <<"\nTesting AdamsMoultonSolver(1)" << std::endl;
      REQUIRE(check.order(new AdamsMoultonSolver(1)) + tol > 1.0 );
   }

   SECTION("AdamsMoultonSolver(2)")
   {
      std::cout <<"\nTesting AdamsMoultonSolver(2)" << std::endl;
      REQUIRE(check.order(new AdamsMoultonSolver(2)) + tol > 2.0 );
   }

   SECTION("AdamsMoultonSolver(3)")
   {
      std::cout <<"\nTesting AdamsMoultonSolver(3)" << std::endl;
      REQUIRE(check.order(new AdamsMoultonSolver(3)) + tol > 3.0 );
   }

   SECTION("AdamsMoultonSolver(4)")
   {
      std::cout <<"\nTesting AdamsMoultonSolver(4)" << std::endl;
      REQUIRE(check.order(new AdamsMoultonSolver(4)) + tol > 4.0 );
   }
}

<commit_msg>Small corrections to unit test<commit_after>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
//

#include "mfem.hpp"
#include "catch.hpp"
#include <cmath>

using namespace mfem;

TEST_CASE("First order ODE methods",
          "[ODE1]")
{
    double tol = 0.1;

   /** Class for simple linear first order ODE.
    *
    *     du/dt  + a u = 0
    *
    */
   class ODE : public TimeDependentOperator
   {
   protected:
      DenseMatrix A,I,T;
      Vector r;
   public:
      ODE(double a00,double a01,double a10,double a11) : TimeDependentOperator(2, 0.0)
      {
         A.SetSize(2,2);
         I.SetSize(2,2);
         T.SetSize(2,2);
         r.SetSize(2);

         A(0,0) = a00;
         A(0,1) = a01;
         A(1,0) = a10;
         A(1,1) = a11;

         I =  0.0;
         I(0,0) = I(1,1) = 1.0;
      };

      virtual void Mult(const Vector &u, Vector &dudt)  const
      {
         A.Mult(u,dudt);
         dudt.Neg();
      }

      virtual void ImplicitSolve(const double dt, const Vector &u, Vector &dudt)
      {
         // Residual
         A.Mult(u,r);
         r.Neg();

         // Jacobian
         Add(I,A,dt,T);

         // Solve
         T.Invert();
         T.Mult(r,dudt);
      }

      virtual ~ODE() {};
   };

   /** Class for checking order of convergence of first order ODE.
    */
   class CheckODE
   {
   protected:
      int ti_steps,levels;
      Vector u0;
      double t_final,dt;
      ODE *oper;
   public:
      CheckODE()
      {
         oper = new ODE(0.0, 1.0, -1.0, 0.0);
         ti_steps = 2;
         levels   = 6;

         u0.SetSize(2);
         u0    = 1.0;

         t_final = M_PI;
         dt = t_final/double(ti_steps);
      };

      double order(ODESolver* ode_solver)
      {
         double dt,t;
         Vector u(2);
         Vector err(levels);
         int steps = ti_steps;

         t = 0.0;
         dt = t_final/double(steps);
         u = u0;
         ode_solver->Init(*oper);
         for (int ti = 0; ti< steps; ti++)
         {
            ode_solver->Step(u, t, dt);
         }
         u +=u0;
         err[0] = u.Norml2();

         std::cout<<std::setw(12)<<"Error"
                  <<std::setw(12)<<"Ratio"
                  <<std::setw(12)<<"Order"<<std::endl;
         std::cout<<std::setw(12)<<err[0]<<std::endl;

         for (int l = 1; l< levels; l++)
         {
            t = 0.0;
            steps *=2;
            dt = t_final/double(steps);
            u = u0;
            ode_solver->Init(*oper);
            for (int ti = 0; ti< steps; ti++)
            {
               ode_solver->Step(u, t, dt);
            }
            u +=u0;
            err[l] = u.Norml2();
            std::cout<<std::setw(12)<<err[l]
                     <<std::setw(12)<<err[l-1]/err[l]
                     <<std::setw(12)<<log(err[l-1]/err[l])/log(2) <<std::endl;
         }
         delete ode_solver;

         return log(err[levels-2]/err[levels-1])/log(2);
      }
      virtual ~CheckODE() {delete oper;};
   };
   CheckODE check;

   // Implicit L-stable methods
   SECTION("BackwardEuler")
   {
      std::cout <<"\nTesting BackwardEuler" << std::endl;
      REQUIRE(check.order(new BackwardEulerSolver) + tol > 1.0 );
   }

   SECTION("SDIRK23Solver(2)")
   {
      std::cout <<"\nTesting SDIRK23Solver(2)" << std::endl;
      REQUIRE(check.order(new SDIRK23Solver(2)) + tol > 2.0 );
   }

   SECTION("SDIRK33Solver")
   {
      std::cout <<"\nTesting SDIRK33Solver" << std::endl;
      REQUIRE(check.order(new SDIRK33Solver) + tol > 3.0 );
   }

   SECTION("ForwardEulerSolver")
   {
      std::cout <<"\nTesting ForwardEulerSolver" << std::endl;
      REQUIRE(check.order(new ForwardEulerSolver) + tol > 1.0 );
   }

   SECTION("RK2Solver(0.5)")
   {
      std::cout <<"\nTesting RK2Solver(0.5)" << std::endl;
      REQUIRE(check.order(new RK2Solver(0.5))+ tol > 2.0 );
   }

   SECTION("RK3SSPSolver")
   {
      std::cout <<"\nTesting RK3SSPSolver" << std::endl;
      REQUIRE(check.order(new RK3SSPSolver) + tol > 3.0 );
   }

   SECTION("RK4Solver")
   {
      std::cout <<"\nTesting RK4Solver" << std::endl;
      REQUIRE(check.order(new RK4Solver) + tol > 4.0 );
   }

   SECTION("ImplicitMidpointSolver")
   {
      std::cout <<"\nTesting ImplicitMidpointSolver" << std::endl;
      REQUIRE(check.order(new ImplicitMidpointSolver) + tol > 2.0 );
   }

   SECTION("SDIRK23Solver")
   {
      std::cout <<"\nTesting SDIRK23Solver" << std::endl;
      REQUIRE(check.order(new SDIRK23Solver) + tol > 3.0 );
   }

   SECTION("SDIRK34Solver")
   {
      std::cout <<"\nTesting SDIRK34Solver" << std::endl;
      REQUIRE(check.order(new SDIRK34Solver) + tol > 4.0 );
   }

   // Generalized-alpha
   SECTION("GeneralizedAlphaSolver(1.0)")
   {
      std::cout <<"\nTesting GeneralizedAlphaSolver(1.0)" << std::endl;
      REQUIRE(check.order(new GeneralizedAlphaSolver(1.0)) + tol > 2.0 );
   }

   SECTION("GeneralizedAlphaSolver(0.5)")
   {
      std::cout <<"\nTesting GeneralizedAlphaSolver(0.5)" << std::endl;
      REQUIRE(check.order(new GeneralizedAlphaSolver(0.5)) + tol > 2.0 );
   }

   SECTION("GeneralizedAlphaSolver(0.0)")
   {
      std::cout <<"\nTesting GeneralizedAlphaSolver(0.0)" << std::endl;
      REQUIRE(check.order(new GeneralizedAlphaSolver(0.0)) + tol > 2.0 );
   }

   // Adams-Bashforth
 /*  SECTION("AdamsBashforthSolver(1)")
   {
      std::cout <<"\nTesting AdamsBashforthSolver(1)" << std::endl;
      REQUIRE(check.order(new AdamsBashforthSolver(1)) + tol > 1.0 );
   }

   SECTION("AdamsBashforthSolver(2)")
   {
      std::cout <<"\nTesting AdamsBashforthSolver(2)" << std::endl;
      REQUIRE(check.order(new AdamsBashforthSolver(2)) + tol > 2.0 );
   }

   SECTION("AdamsBashforthSolver(3)")
   {
      std::cout <<"\nTesting AdamsBashforthSolver(3)" << std::endl;
      REQUIRE(check.order(new AdamsBashforthSolver(3)) + tol > 3.0 );
   }

   SECTION("AdamsBashforthSolver(4)")
   {
      std::cout <<"\nTesting AdamsBashforthSolver(4)" << std::endl;
      REQUIRE(check.order(new AdamsBashforthSolver(4)) + tol > 4.0 );
   }

   SECTION("AdamsBashforthSolver(5)")
   {
      std::cout <<"\nTesting AdamsBashforthSolver(5)" << std::endl;
      REQUIRE(check.order(new AdamsBashforthSolver(5)) + tol > 5.0 );
   }*/

 /*  //AdamsMoulton
   SECTION("AdamsMoultonSolver(0)")
   {
      std::cout <<"\nTesting AdamsMoultonSolver(0)" << std::endl;
      REQUIRE(check.order(new AdamsMoultonSolver(0)) + tol > 1.0 );
   }

   SECTION("AdamsMoultonSolver(1)")
   {
      std::cout <<"\nTesting AdamsMoultonSolver(1)" << std::endl;
      REQUIRE(check.order(new AdamsMoultonSolver(1)) + tol > 2.0 );
   }

   SECTION("AdamsMoultonSolver(2)")
   {
      std::cout <<"\nTesting AdamsMoultonSolver(2)" << std::endl;
      REQUIRE(check.order(new AdamsMoultonSolver(2)) + tol > 3.0 );
   }

   SECTION("AdamsMoultonSolver(3)")
   {
      std::cout <<"\nTesting AdamsMoultonSolver(3)" << std::endl;
      REQUIRE(check.order(new AdamsMoultonSolver(3)) + tol > 4.0 );
   }

   SECTION("AdamsMoultonSolver(4)")
   {
      std::cout <<"\nTesting AdamsMoultonSolver(4)" << std::endl;
      REQUIRE(check.order(new AdamsMoultonSolver(4)) + tol > 5.0 );
   }*/
}

<|endoftext|>


<commit_before>/*********************************************************************************
* Copyright (c) 2014 David D. Marshall <ddmarsha@calpoly.edu>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*    David D. Marshall - initial code and implementation
********************************************************************************/

#ifndef eli_geom_surface_piecewise_body_of_revolution_creator_hpp
#define eli_geom_surface_piecewise_body_of_revolution_creator_hpp

#include <list>
#include <iterator>

#include "eli/code_eli.hpp"

#include "eli/util/tolerance.hpp"

#include "eli/geom/curve/bezier.hpp"
#include "eli/geom/curve/piecewise.hpp"

#include "eli/geom/surface/bezier.hpp"
#include "eli/geom/surface/piecewise.hpp"

namespace eli
{
  namespace geom
  {
    namespace surface
    {
      template<typename data__, unsigned short dim__, typename tol__>
      class capped_surface_creator : public piecewise_creator_base<data__, dim__, tol__>
      {
        public:
          enum edge_split_identifier
          {
            SPLIT_NONE,
            SPLIT_UMIN,
            SPLIT_UMAX,
            SPLIT_VMIN,
            SPLIT_VMAX
          };

          typedef piecewise_creator_base<data__, dim__, tol__> base_class_type;
          typedef typename base_class_type::data_type data_type;
          typedef typename base_class_type::point_type point_type;
          typedef typename base_class_type::index_type index_type;
          typedef typename base_class_type::tolerance_type tolerance_type;
          typedef typename base_class_type::piecewise_surface_type piecewise_surface_type;

          capped_surface_creator()
            : piecewise_creator_base<data__, dim__, tol__>(0, 0), split_param(0), edge_to_split(SPLIT_NONE)
          {
          }
          capped_surface_creator(const data_type &uu0, const data_type &sp, edge_split_identifier esi)
            : piecewise_creator_base<data__, dim__, tol__>(0, 0), edge_curve
          {
          }
          capped_surface_creator(const general_skinning_surface_creator<data_type, dim__, tolerance_type> & gs)
            : piecewise_creator_base<data_type, dim__, tolerance_type>(gs), ribs(gs.ribs),
              max_degree(gs.max_degree), closed(gs.closed)
          {
          }
          virtual ~capped_surface_creator()
          {
          }

          bool set_conditions(const piecewise_curve_type &rbs, const std::vector<index_type> &maxd, bool cl=false)
          {
          }

          virtual bool create(piecewise_surface_type &ps) const
          {
            typedef typename eli::geom::curve::piecewise<eli::geom::curve::bezier, data_type, dim__, tolerance_type> piecewise_curve_type;
            // need to implement
            assert(false);

            return false;
          }
#if 0
          {
            typedef piecewise<bezier, data_type, dim__, tolerance_type> piecewise_surface_type;
            typedef typename piecewise_surface_type::surface_type surface_type;

            index_type nribs(this->get_number_u_segments()+1), i, j;
            std::vector<index_type> seg_degree(nribs-1);
            std::vector<rib_data_type> rib_states(ribs);
            tolerance_type tol;

            // FIX: Should be able to handle closed surfaces
            assert(!closed);

            // FIX: Need to be able to handle v-direction discontinuous fu and fuu specifications

            // reset the incoming piecewise surface
            ps.clear();

            // split ribs so have same number of curves (with same joint parameters) for all ribs and get degree
            index_type njoints(this->get_number_v_segments()+1);
            std::vector<data_type> joints(njoints);
            std::vector<index_type> max_jdegs(njoints-1,0);

            joints[0]=this->get_v0();
            for (j=0; j<(njoints-1); ++j)
            {
              joints[j+1]=joints[j]+this->get_segment_dv(j);
            }

            for (i=0; i<nribs; ++i)
            {
              std::vector<index_type> jdegs;
              rib_states[i].split(joints.begin(), joints.end(), std::back_inserter(jdegs));
              for (j=0; j<(njoints-1); ++j)
              {
                if (jdegs[j]>max_jdegs[j])
                {
                  max_jdegs[j]=jdegs[j];
                }
              }
            }

            // set degree in u-direction for each rib segment strip
            for (i=0; i<nribs; ++i)
            {
              rib_states[i].promote(max_jdegs.begin(), max_jdegs.end());
            }

            // resize the piecewise surface
            index_type u, v, nu(nribs-1), nv(njoints-1);

            ps.init_uv(this->du_begin(), this->du_end(), this->dv_begin(), this->dv_end(), this->get_u0(), this->get_v0());

            // build segments based on rib information
            // here should have everything to make an nribs x njoints piecewise surface with all
            // of the j-degrees matching in the u-direction so that can use general curve creator
            // techniques to create control points
            for (v=0; v<nv; ++v)
            {
              typedef eli::geom::curve::piecewise_general_creator<data_type, dim__, tolerance_type> piecewise_curve_creator_type;
              typedef eli::geom::curve::piecewise<eli::geom::curve::bezier, data_type, dim__, tolerance_type> piecewise_curve_type;
              typedef typename piecewise_curve_type::curve_type curve_type;

              std::vector<typename piecewise_curve_creator_type::joint_data> joints(nu+1);
              piecewise_curve_creator_type gc;
              piecewise_curve_type c;

              std::vector<surface_type> surfs(nu);

              for (j=0; j<=max_jdegs[v]; ++j)
              {
                // cycle through each rib to set corresponding joint info
                for (u=0; u<=nu; ++u)
                {
                  curve_type jcrv;

                  joints[u].set_continuity(static_cast<typename piecewise_curve_creator_type::joint_continuity>(rib_states[u].get_continuity()));

                  rib_states[u].get_f().get(jcrv, v);
                  joints[u].set_f(jcrv.get_control_point(j));
                  if (rib_states[u].use_left_fp())
                  {
                    rib_states[u].get_left_fp().get(jcrv, v);
                    joints[u].set_left_fp(jcrv.get_control_point(j));
                  }
                  if (rib_states[u].use_right_fp())
                  {
                    rib_states[u].get_right_fp().get(jcrv, v);
                    joints[u].set_right_fp(jcrv.get_control_point(j));
                  }
                  if (rib_states[u].use_left_fpp())
                  {
                    rib_states[u].get_left_fpp().get(jcrv, v);
                    joints[u].set_left_fpp(jcrv.get_control_point(j));
                  }
                  if (rib_states[u].use_right_fpp())
                  {
                    rib_states[u].get_right_fpp().get(jcrv, v);
                    joints[u].set_right_fpp(jcrv.get_control_point(j));
                  }
                }

                // set the conditions for the curve creator
                bool rtn_flag(gc.set_conditions(joints, max_degree, closed));
                if (!rtn_flag)
                {
                  return false;
                }

                // set the parameterizations and create curve
                gc.set_t0(this->get_u0());
                for (u=0; u<nu; ++u)
                {
                  gc.set_segment_dt(this->get_segment_du(u), u);
                }
                rtn_flag=gc.create(c);
                if (!rtn_flag)
                {
                  return false;
                }

                // extract the control points from piecewise curve and set the surface control points
                for (u=0; u<nu; ++u)
                {
                  curve_type crv;

                  c.get(crv, u);

                  // resize the temp surface
                  if (j==0)
                  {
                    surfs[u].resize(crv.degree(), max_jdegs[v]);
                  }

                  for (i=0; i<=crv.degree(); ++i)
                  {
                    surfs[u].set_control_point(crv.get_control_point(i), i, j);
                  }
                }
              }

              // put these surfaces into piecewise surface
              typename piecewise_surface_type::error_code ec;
              for (u=0; u<nu; ++u)
              {
                ec=ps.set(surfs[u], u, v);
                if (ec!=piecewise_surface_type::NO_ERRORS)
                {
                  assert(false);
                  return false;
                }
              }
            }

            return true;
          }
#endif

        private:
          piecewise_surface_type orig_surface;
          data_type split_param;
          edge_split_identifier edge_to_split;
      };
    }
  }
}
#endif
<commit_msg>Cleaned up naming and other code issues.<commit_after>/*********************************************************************************
* Copyright (c) 2014 David D. Marshall <ddmarsha@calpoly.edu>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*    David D. Marshall - initial code and implementation
********************************************************************************/

#ifndef eli_geom_surface_piecewise_capped_surface_creator_hpp
#define eli_geom_surface_piecewise_capped_surface_creator_hpp

#include <list>
#include <iterator>

#include "eli/code_eli.hpp"

#include "eli/util/tolerance.hpp"

#include "eli/geom/curve/bezier.hpp"
#include "eli/geom/curve/piecewise.hpp"

#include "eli/geom/surface/bezier.hpp"
#include "eli/geom/surface/piecewise.hpp"

namespace eli
{
  namespace geom
  {
    namespace surface
    {
      template<typename data__, unsigned short dim__, typename tol__>
      class piecewise_capped_surface_creator : public piecewise_creator_base<data__, dim__, tol__>
      {
        public:
          enum edge_split_identifier
          {
            SPLIT_NONE,
            SPLIT_UMIN,
            SPLIT_UMAX,
            SPLIT_VMIN,
            SPLIT_VMAX
          };

          typedef piecewise_creator_base<data__, dim__, tol__> base_class_type;
          typedef typename base_class_type::data_type data_type;
          typedef typename base_class_type::point_type point_type;
          typedef typename base_class_type::index_type index_type;
          typedef typename base_class_type::tolerance_type tolerance_type;
          typedef typename base_class_type::piecewise_surface_type piecewise_surface_type;

          piecewise_capped_surface_creator()
            : piecewise_creator_base<data__, dim__, tol__>(0, 0), split_param(0), edge_to_split(SPLIT_NONE)
          {
          }
          piecewise_capped_surface_creator(const piecewise_surface_type &os, const data_type &sp, edge_split_identifier esi)
            : piecewise_creator_base<data__, dim__, tol__>(0, 0), orig_surface(os), split_param(sp), edge_to_split(esi)
          {
          }
          piecewise_capped_surface_creator(const piecewise_capped_surface_creator<data_type, dim__, tolerance_type> & gs)
            : piecewise_creator_base<data_type, dim__, tolerance_type>(gs), orig_surface(gs.orig_surface),
              split_param(gs.split_param), edge_to_split(gs.edge_to_split)
          {
          }
          virtual ~piecewise_capped_surface_creator()
          {
          }

          bool set_conditions(const piecewise_surface_type &os, const data_type &sp, edge_split_identifier esi)
          {
            // before setting things, make sure that the split parameter is within the edges min and max
            orig_surface = os;
            split_param = sp;
            edge_to_split = esi;
          }

          virtual bool create(piecewise_surface_type &ps) const
          {
            typedef typename eli::geom::curve::piecewise<eli::geom::curve::bezier, data_type, dim__, tolerance_type> piecewise_curve_type;

            // need to implement
            assert(false);

            return false;
          }
#if 0
          {
            typedef piecewise<bezier, data_type, dim__, tolerance_type> piecewise_surface_type;
            typedef typename piecewise_surface_type::surface_type surface_type;

            index_type nribs(this->get_number_u_segments()+1), i, j;
            std::vector<index_type> seg_degree(nribs-1);
            std::vector<rib_data_type> rib_states(ribs);
            tolerance_type tol;

            // FIX: Should be able to handle closed surfaces
            assert(!closed);

            // FIX: Need to be able to handle v-direction discontinuous fu and fuu specifications

            // reset the incoming piecewise surface
            ps.clear();

            // split ribs so have same number of curves (with same joint parameters) for all ribs and get degree
            index_type njoints(this->get_number_v_segments()+1);
            std::vector<data_type> joints(njoints);
            std::vector<index_type> max_jdegs(njoints-1,0);

            joints[0]=this->get_v0();
            for (j=0; j<(njoints-1); ++j)
            {
              joints[j+1]=joints[j]+this->get_segment_dv(j);
            }

            for (i=0; i<nribs; ++i)
            {
              std::vector<index_type> jdegs;
              rib_states[i].split(joints.begin(), joints.end(), std::back_inserter(jdegs));
              for (j=0; j<(njoints-1); ++j)
              {
                if (jdegs[j]>max_jdegs[j])
                {
                  max_jdegs[j]=jdegs[j];
                }
              }
            }

            // set degree in u-direction for each rib segment strip
            for (i=0; i<nribs; ++i)
            {
              rib_states[i].promote(max_jdegs.begin(), max_jdegs.end());
            }

            // resize the piecewise surface
            index_type u, v, nu(nribs-1), nv(njoints-1);

            ps.init_uv(this->du_begin(), this->du_end(), this->dv_begin(), this->dv_end(), this->get_u0(), this->get_v0());

            // build segments based on rib information
            // here should have everything to make an nribs x njoints piecewise surface with all
            // of the j-degrees matching in the u-direction so that can use general curve creator
            // techniques to create control points
            for (v=0; v<nv; ++v)
            {
              typedef eli::geom::curve::piecewise_general_creator<data_type, dim__, tolerance_type> piecewise_curve_creator_type;
              typedef eli::geom::curve::piecewise<eli::geom::curve::bezier, data_type, dim__, tolerance_type> piecewise_curve_type;
              typedef typename piecewise_curve_type::curve_type curve_type;

              std::vector<typename piecewise_curve_creator_type::joint_data> joints(nu+1);
              piecewise_curve_creator_type gc;
              piecewise_curve_type c;

              std::vector<surface_type> surfs(nu);

              for (j=0; j<=max_jdegs[v]; ++j)
              {
                // cycle through each rib to set corresponding joint info
                for (u=0; u<=nu; ++u)
                {
                  curve_type jcrv;

                  joints[u].set_continuity(static_cast<typename piecewise_curve_creator_type::joint_continuity>(rib_states[u].get_continuity()));

                  rib_states[u].get_f().get(jcrv, v);
                  joints[u].set_f(jcrv.get_control_point(j));
                  if (rib_states[u].use_left_fp())
                  {
                    rib_states[u].get_left_fp().get(jcrv, v);
                    joints[u].set_left_fp(jcrv.get_control_point(j));
                  }
                  if (rib_states[u].use_right_fp())
                  {
                    rib_states[u].get_right_fp().get(jcrv, v);
                    joints[u].set_right_fp(jcrv.get_control_point(j));
                  }
                  if (rib_states[u].use_left_fpp())
                  {
                    rib_states[u].get_left_fpp().get(jcrv, v);
                    joints[u].set_left_fpp(jcrv.get_control_point(j));
                  }
                  if (rib_states[u].use_right_fpp())
                  {
                    rib_states[u].get_right_fpp().get(jcrv, v);
                    joints[u].set_right_fpp(jcrv.get_control_point(j));
                  }
                }

                // set the conditions for the curve creator
                bool rtn_flag(gc.set_conditions(joints, max_degree, closed));
                if (!rtn_flag)
                {
                  return false;
                }

                // set the parameterizations and create curve
                gc.set_t0(this->get_u0());
                for (u=0; u<nu; ++u)
                {
                  gc.set_segment_dt(this->get_segment_du(u), u);
                }
                rtn_flag=gc.create(c);
                if (!rtn_flag)
                {
                  return false;
                }

                // extract the control points from piecewise curve and set the surface control points
                for (u=0; u<nu; ++u)
                {
                  curve_type crv;

                  c.get(crv, u);

                  // resize the temp surface
                  if (j==0)
                  {
                    surfs[u].resize(crv.degree(), max_jdegs[v]);
                  }

                  for (i=0; i<=crv.degree(); ++i)
                  {
                    surfs[u].set_control_point(crv.get_control_point(i), i, j);
                  }
                }
              }

              // put these surfaces into piecewise surface
              typename piecewise_surface_type::error_code ec;
              for (u=0; u<nu; ++u)
              {
                ec=ps.set(surfs[u], u, v);
                if (ec!=piecewise_surface_type::NO_ERRORS)
                {
                  assert(false);
                  return false;
                }
              }
            }

            return true;
          }
#endif

        private:
          piecewise_surface_type orig_surface;
          data_type split_param;
          edge_split_identifier edge_to_split;
      };
    }
  }
}
#endif
<|endoftext|>