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

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

Copyright (c) 1993-2000 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

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

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

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

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

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

=========================================================================*/
#include "vtkLight.h"
#include "vtkGraphicsFactory.h"

// Create a light with the focal point at the origin and its position
// set to (0,0,1). The lights color is white, intensity=1, and the light
// is turned on.
vtkLight::vtkLight()
{
  this->FocalPoint[0] = 0.0;
  this->FocalPoint[1] = 0.0;
  this->FocalPoint[2] = 0.0;

  this->Position[0] = 0.0;
  this->Position[1] = 0.0;
  this->Position[2] = 1.0;

  this->Color[0] = 1.0;
  this->Color[1] = 1.0;
  this->Color[2] = 1.0;

  this->Switch = 1;

  this->Intensity = 1.0;
  this->Positional = 0;
  this->ConeAngle = 30;
  this->AttenuationValues[0] = 1;
  this->AttenuationValues[1] = 0;
  this->AttenuationValues[2] = 0;
  this->Exponent = 1;

  this->TransformMatrix = (vtkMatrix4x4 *)NULL;
}

// return the correct type of light
vtkLight *vtkLight::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkGraphicsFactory::CreateInstance("vtkLight");
  return (vtkLight*)ret;
}

void vtkLight::GetTransformedPosition(float a[3])
{
  float f[4];

  f[0] = this->Position[0];
  f[1] = this->Position[1];
  f[2] = this->Position[2];
  f[3] = 1.0;

  if(this->TransformMatrix) {
    this->TransformMatrix->MultiplyPoint(f, f);
  }

  a[0] = f[0];
  a[1] = f[1];
  a[2] = f[2];
}

void vtkLight::GetTransformedPosition(float &x, float &y, float &z)
{
  float a[3];

  this->GetTransformedPosition(a);
  x = a[0];
  y = a[1];
  z = a[2];
}

float *vtkLight::GetTransformedPosition()
{
    this->GetTransformedPosition(this->TransformedPositionReturn);
    return this->TransformedPositionReturn;
}

void vtkLight::GetTransformedFocalPoint(float a[3])
{
  float f[3];

  f[0] = this->FocalPoint[0];
  f[1] = this->FocalPoint[1];
  f[2] = this->FocalPoint[2];
  f[3] = 1.0;

  if(this->TransformMatrix) {
    this->TransformMatrix->MultiplyPoint(f, f);
  }

  a[0] = f[0];
  a[1] = f[1];
  a[2] = f[2];
}

void vtkLight::GetTransformedFocalPoint(float &x, float &y, float &z)
{
  float a[3];

  this->GetTransformedFocalPoint(a);
  x = a[0];
  y = a[1];
  z = a[2];
}

float *vtkLight::GetTransformedFocalPoint()
{
  this->GetTransformedFocalPoint(this->TransformedFocalPointReturn);
  return this->TransformedFocalPointReturn;
}

void vtkLight::DeepCopy(vtkLight *light)
{
  this->SetFocalPoint(light->GetFocalPoint());
  this->SetPosition(light->GetPosition());
  this->SetIntensity(light->GetIntensity());
  this->SetColor(light->GetColor());
  this->SetSwitch(light->GetSwitch());
  this->SetPositional(light->GetPositional());
  this->SetExponent(light->GetExponent());
  this->SetConeAngle(light->GetConeAngle());
  this->SetAttenuationValues(light->GetAttenuationValues());
}

void vtkLight::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkObject::PrintSelf(os,indent);

  os << indent << "AttenuationValues: (" << this->AttenuationValues[0] << ", "
    << this->AttenuationValues[1] << ", " << this->AttenuationValues[2] << ")\n";
  os << indent << "Color: (" << this->Color[0] << ", "
    << this->Color[1] << ", " << this->Color[2] << ")\n";
  os << indent << "Cone Angle: " << this->ConeAngle << "\n";
  os << indent << "Exponent: " << this->Exponent << "\n";
  os << indent << "Focal Point: (" << this->FocalPoint[0] << ", "
    << this->FocalPoint[1] << ", " << this->FocalPoint[2] << ")\n";
  os << indent << "Intensity: " << this->Intensity << "\n";
  os << indent << "Position: (" << this->Position[0] << ", "
    << this->Position[1] << ", " << this->Position[2] << ")\n";
  os << indent << "Positional: " << (this->Positional ? "On\n" : "Off\n");
  os << indent << "Switch: " << (this->Switch ? "On\n" : "Off\n");

  os << indent << "TransformMatrix: ";
  if(this->TransformMatrix != NULL)
    {
      os << this->TransformMatrix << "\n";
    }
  else
    {
      os << "(none)\n";
    }
}

void vtkLight::WriteSelf(ostream& os)
{
  os << this->FocalPoint[0] << " " << this->FocalPoint[1] << " "
     << this->FocalPoint[2] << " ";
  os << this->Position[0] << " " << this->Position[1] << " "
     << this->Position[2] << " ";
  os << this->Intensity << " ";
  os << this->Color[0] << " " << this->Color[1] << " "
     << this->Color[2] << " ";
  os << this->Switch << " ";
  os << this->Positional << " ";
  os << this->Exponent << " ";
  os << this->ConeAngle << " ";
  os << this->AttenuationValues[0] << " " << this->AttenuationValues[1] << " "
     << this->AttenuationValues[2] << " ";
  // XXX - TransformMatrix ???
}

void vtkLight::ReadSelf(istream& is)
{
  is >> this->FocalPoint[0] >> this->FocalPoint[1] >> this->FocalPoint[2] ;
  is >> this->Position[0] >> this->Position[1] >> this->Position[2];
  is >> this->Intensity;
  is >> this->Color[0] >> this->Color[1] >> this->Color[2];
  is >> this->Switch;
  is >> this->Positional;
  is >> this->Exponent;
  is >> this->ConeAngle;
  is >> this->AttenuationValues[0] >> this->AttenuationValues[1]
     >> this->AttenuationValues[2];
  // XXX - TransformMatrix ???
}

<commit_msg>Fixed out-of-range array reference.<commit_after>/*=========================================================================

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

Copyright (c) 1993-2000 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

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

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

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

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

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

=========================================================================*/
#include "vtkLight.h"
#include "vtkGraphicsFactory.h"

// Create a light with the focal point at the origin and its position
// set to (0,0,1). The lights color is white, intensity=1, and the light
// is turned on.
vtkLight::vtkLight()
{
  this->FocalPoint[0] = 0.0;
  this->FocalPoint[1] = 0.0;
  this->FocalPoint[2] = 0.0;

  this->Position[0] = 0.0;
  this->Position[1] = 0.0;
  this->Position[2] = 1.0;

  this->Color[0] = 1.0;
  this->Color[1] = 1.0;
  this->Color[2] = 1.0;

  this->Switch = 1;

  this->Intensity = 1.0;
  this->Positional = 0;
  this->ConeAngle = 30;
  this->AttenuationValues[0] = 1;
  this->AttenuationValues[1] = 0;
  this->AttenuationValues[2] = 0;
  this->Exponent = 1;

  this->TransformMatrix = (vtkMatrix4x4 *)NULL;
}

// return the correct type of light
vtkLight *vtkLight::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkGraphicsFactory::CreateInstance("vtkLight");
  return (vtkLight*)ret;
}

void vtkLight::GetTransformedPosition(float a[3])
{
  float f[4];

  f[0] = this->Position[0];
  f[1] = this->Position[1];
  f[2] = this->Position[2];
  f[3] = 1.0;

  if(this->TransformMatrix) {
    this->TransformMatrix->MultiplyPoint(f, f);
  }

  a[0] = f[0];
  a[1] = f[1];
  a[2] = f[2];
}

void vtkLight::GetTransformedPosition(float &x, float &y, float &z)
{
  float a[3];

  this->GetTransformedPosition(a);
  x = a[0];
  y = a[1];
  z = a[2];
}

float *vtkLight::GetTransformedPosition()
{
    this->GetTransformedPosition(this->TransformedPositionReturn);
    return this->TransformedPositionReturn;
}

void vtkLight::GetTransformedFocalPoint(float a[3])
{
  float f[4];

  f[0] = this->FocalPoint[0];
  f[1] = this->FocalPoint[1];
  f[2] = this->FocalPoint[2];
  f[3] = 1.0;

  if(this->TransformMatrix) {
    this->TransformMatrix->MultiplyPoint(f, f);
  }

  a[0] = f[0];
  a[1] = f[1];
  a[2] = f[2];
}

void vtkLight::GetTransformedFocalPoint(float &x, float &y, float &z)
{
  float a[3];

  this->GetTransformedFocalPoint(a);
  x = a[0];
  y = a[1];
  z = a[2];
}

float *vtkLight::GetTransformedFocalPoint()
{
  this->GetTransformedFocalPoint(this->TransformedFocalPointReturn);
  return this->TransformedFocalPointReturn;
}

void vtkLight::DeepCopy(vtkLight *light)
{
  this->SetFocalPoint(light->GetFocalPoint());
  this->SetPosition(light->GetPosition());
  this->SetIntensity(light->GetIntensity());
  this->SetColor(light->GetColor());
  this->SetSwitch(light->GetSwitch());
  this->SetPositional(light->GetPositional());
  this->SetExponent(light->GetExponent());
  this->SetConeAngle(light->GetConeAngle());
  this->SetAttenuationValues(light->GetAttenuationValues());
}

void vtkLight::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkObject::PrintSelf(os,indent);

  os << indent << "AttenuationValues: (" << this->AttenuationValues[0] << ", "
    << this->AttenuationValues[1] << ", " << this->AttenuationValues[2] << ")\n";
  os << indent << "Color: (" << this->Color[0] << ", "
    << this->Color[1] << ", " << this->Color[2] << ")\n";
  os << indent << "Cone Angle: " << this->ConeAngle << "\n";
  os << indent << "Exponent: " << this->Exponent << "\n";
  os << indent << "Focal Point: (" << this->FocalPoint[0] << ", "
    << this->FocalPoint[1] << ", " << this->FocalPoint[2] << ")\n";
  os << indent << "Intensity: " << this->Intensity << "\n";
  os << indent << "Position: (" << this->Position[0] << ", "
    << this->Position[1] << ", " << this->Position[2] << ")\n";
  os << indent << "Positional: " << (this->Positional ? "On\n" : "Off\n");
  os << indent << "Switch: " << (this->Switch ? "On\n" : "Off\n");

  os << indent << "TransformMatrix: ";
  if(this->TransformMatrix != NULL)
    {
      os << this->TransformMatrix << "\n";
    }
  else
    {
      os << "(none)\n";
    }
}

void vtkLight::WriteSelf(ostream& os)
{
  os << this->FocalPoint[0] << " " << this->FocalPoint[1] << " "
     << this->FocalPoint[2] << " ";
  os << this->Position[0] << " " << this->Position[1] << " "
     << this->Position[2] << " ";
  os << this->Intensity << " ";
  os << this->Color[0] << " " << this->Color[1] << " "
     << this->Color[2] << " ";
  os << this->Switch << " ";
  os << this->Positional << " ";
  os << this->Exponent << " ";
  os << this->ConeAngle << " ";
  os << this->AttenuationValues[0] << " " << this->AttenuationValues[1] << " "
     << this->AttenuationValues[2] << " ";
  // XXX - TransformMatrix ???
}

void vtkLight::ReadSelf(istream& is)
{
  is >> this->FocalPoint[0] >> this->FocalPoint[1] >> this->FocalPoint[2] ;
  is >> this->Position[0] >> this->Position[1] >> this->Position[2];
  is >> this->Intensity;
  is >> this->Color[0] >> this->Color[1] >> this->Color[2];
  is >> this->Switch;
  is >> this->Positional;
  is >> this->Exponent;
  is >> this->ConeAngle;
  is >> this->AttenuationValues[0] >> this->AttenuationValues[1]
     >> this->AttenuationValues[2];
  // XXX - TransformMatrix ???
}

<|endoftext|>


<commit_before>#include "DirectedGraph.h"

#include <cassert>
#include <iostream>

#include "RawStatistics.h"

using namespace std;

DirectedGraph::DirectedGraph(int _id) : Graph(_id) {

}

DirectedGraph::DirectedGraph(const DirectedGraph & other) : Graph(other) {

}

std::shared_ptr<Graph>
DirectedGraph::createSimilar() const {
  std::shared_ptr<Graph> graph(new DirectedGraph(getId()));
  graph->setLocationGraphValid(false);
  graph->setNodeVisibility(getNodeVisibility());
  graph->setEdgeVisibility(getEdgeVisibility());
  graph->setFaceVisibility(getFaceVisibility());
  graph->setLabelVisibility(getLabelVisibility());
  graph->setLineWidth(getLineWidth());
  graph->setNodeArray(nodes);

  return graph;
}

void
DirectedGraph::breakNodePair(int node_id) {
  auto it = node_pairs.find(node_id);
  if (it != node_pairs.end()) {
    removeChild(node_id);
    int other_id = it->second;
    node_pairs.erase(it);

    auto it2 = node_pairs.find(other_id);
    assert(it2 != node_pairs.end());
    if (it2 != node_pairs.end()) {
      removeChild(other_id);
      node_pairs.erase(it2);

      // if a pair is broken, we add the other node to first one's group
      int o = getNodeArray().getOneDegreeNode(node_id);
      addChild(o, other_id);
      onedegree_nodes[other_id] = node_id;
    }
  }
}

void
DirectedGraph::breakOneDegreeNode(int node_id) {
  auto it = onedegree_nodes.find(node_id);
  if (it != onedegree_nodes.end()) {
    removeChild(node_id);
    onedegree_nodes.erase(it);
  }
}

void
DirectedGraph::breakZeroDegreeNode(int node_id) {
  auto it = zerodegree_nodes.find(node_id);
  if (it != zerodegree_nodes.end()) {
    removeChild(node_id);
    zerodegree_nodes.erase(it);
  }
}

bool
DirectedGraph::updateData(time_t start_time, time_t end_time, float start_sentiment, float end_sentiment, Graph & source_graph, RawStatistics & stats, bool is_first_level, Graph * base_graph) {
  if (getNodeArray().hasTemporalCoverage() && !(end_time > start_time)) {
    cerr << "invalid time range for updateData: " << start_time << " - " << end_time << endl;
    return false;
  }

  auto & sid = source_graph.getNodeArray().getTable()["source"];
  auto & soid = source_graph.getNodeArray().getTable()["id"];
  auto & user_type = source_graph.getNodeArray().getTable()["type"];
  auto & political_party = source_graph.getNodeArray().getTable()["party"];
  auto & name_column = source_graph.getNodeArray().getTable()["name"];
  auto & uname_column = source_graph.getNodeArray().getTable()["uname"];

  auto begin = source_graph.begin_edges();
  auto end = source_graph.end_edges();
  auto it = begin;

  if (current_pos == -1) {
    clear();
    edge_attributes.clear();
    current_pos = 0;
    cerr << "restarting update, begin = " << begin.get() << ", cp = " << current_pos << ", end = " << end.get() << ", source = " << &source_graph << ", edges = " << source_graph.getEdgeCount() << endl;
  } else {
    cerr << "continuing update, begin = " << begin.get() << ", cp = " << current_pos << ", end = " << end.get() << ", source = " << &source_graph << ", edges = " << source_graph.getEdgeCount() << endl;
    for (int i = 0; i < current_pos; i++) ++it;
  }

  auto & nodes = getNodeArray();

  unsigned int skipped_count = 0;
  bool is_changed = false;
  unsigned int num_edges_processed = 0;
  for ( ; it != end; ++it, current_pos++) {
    num_edges_processed++;

    time_t t = 0;
    float se = 0;
    short lang = 0;
    long long app_id = -1, filter_id = -1;
    bool is_first = false;

    assert(it->face != -1);
    if (it->face != -1) {
      auto & fd = source_graph.getFaceAttributes(it->face);
      t = fd.timestamp;
      se = fd.sentiment;
      lang = fd.lang;
      app_id = fd.app_id;
      filter_id = fd.filter_id;
      is_first = fd.first_edge == current_pos;
    }

    if (it->tail < 0 || it->head < 0 || it->tail >= nodes.size() || it->head >= nodes.size()) {
      cerr << "invalid values: tail = " << it->tail << ", head = " << it->head << ", t = " << t << ", count = " << nodes.size() << ", n = " << num_edges_processed << endl;
      assert(0);
    }

    if ((!start_time || t >= start_time) && (!end_time || t < end_time) &&
	se >= start_sentiment && se <= end_sentiment) {
      if (t < min_time || min_time == 0) min_time = t;
      if (t > max_time) max_time = t;

      pair<int, int> np(it->tail, it->head);
      short first_user_sid = sid.getInt(np.first);
      short target_user_sid = sid.getInt(np.second);
      long long first_user_soid = soid.getInt64(np.first);
      long long target_user_soid = soid.getInt64(np.second);

      auto & td1 = base_graph->getNodeTertiaryData(np.first);
      auto & td2 = base_graph->getNodeTertiaryData(np.second);

      if (!is_first_level) {
	if (td1.indegree < getMinSignificance()) {
	  skipped_count++;
	  continue;
	}
	if (td2.indegree < getMinSignificance()) {
	  skipped_count++;
	  continue;
	}
      }

      is_changed = true;

      auto & target_nd_old = nodes.getNodeData(np.second);
      NodeType target_type = target_nd_old.type;

      if (is_first_level && is_first) {
	stats.addActivity(t, first_user_sid, first_user_soid, lang, app_id, filter_id, PoliticalParty(political_party.getInt(np.first)));
      }

      if (is_first_level && !seen_nodes.count(np.second)) {
	seen_nodes.insert(np.second);
	if (target_type == NODE_HASHTAG) {
	  stats.addHashtag(name_column.getText(np.second));
	  num_hashtags++;
	} else if (target_type == NODE_URL) {
	  stats.addLink(name_column.getText(np.second), uname_column.getText(np.second));
	  num_links++;
	} else {
	  UserType ut = UserType(user_type.getInt(np.second));
	  if (ut != UNKNOWN_TYPE) stats.addUserType(ut);
	  // stats.addPoliticalParty(PoliticalParty(political_party.getInt(np.first)));
	}
      }

      if (target_type != NODE_URL && target_type != NODE_HASHTAG) {
	if (is_first_level && target_type == NODE_ANY) {
	  stats.addReceivedActivity(t, target_user_sid, target_user_soid, app_id, filter_id);
	}

	long long coverage = 0;
	if (getNodeArray().hasTemporalCoverage()) {
	  assert(end_time > start_time);
	  int time_pos = 63LL * (t - start_time) / (end_time - start_time);
	  assert(time_pos >= 0 && time_pos < 64);
	  coverage |= 1 << time_pos;
	}

	unordered_map<int, unordered_map<int, int> >::iterator it1;
	unordered_map<int, int>::iterator it2;
	if ((it1 = seen_edges.find(np.first)) != seen_edges.end() &&
	    (it2 = it1->second.find(np.second)) != it1->second.end()) {
#if 0
	  updateOutdegree(np.first, 1.0f);
	  updateIndegree(np.second, 1.0f);
	  updateNodeSize(np.first);
	  updateNodeSize(np.second);
#endif
	  if (getNodeArray().hasTemporalCoverage()) {
	    auto & ed = getEdgeAttributes(it2->second);
	    ed.coverage |= coverage;
	    float new_weight = 0;
	    for (int i = 0; i < 64; i++) {
	      if (ed.coverage & (1 << i)) new_weight += 1.0f;
	    }
	    new_weight /= 64.0f;
	    updateEdgeWeight(it2->second, new_weight - ed.weight);
	  }
	} else {
	  if (td1.indegree == 0 && td1.outdegree == 0) {
	    bool has_zero = zerodegree_nodes.count(np.first) != 0;
	    if (np.first == np.second && !has_zero) {
	      int z = nodes.getZeroDegreeNode();
	      cerr << "DEBUG: adding node " << np.first << " to zero degree node (id = " << z << ")\n";
	      addChild(z, np.first);
	      zerodegree_nodes.insert(np.first);
	    } else if (np.first != np.second && has_zero) {
	      cerr << "DEBUG: removing node " << np.first << " from zero degree node (A)\n";
	      removeChild(np.first);
	      zerodegree_nodes.erase(np.first);
	    }
	    if (np.first != np.second) {
	      if (td2.indegree == 0 && td2.outdegree == 0) {
		if (zerodegree_nodes.count(np.second) != 0) {
		  removeChild(np.second);
		  zerodegree_nodes.erase(np.second);
		}
		assert(node_pairs.find(np.first) == node_pairs.end());
		assert(node_pairs.find(np.second) == node_pairs.end());
		int o = nodes.getPairsNode();
		cerr << "adding to pairs node\n";
		addChild(o, np.first);
		addChild(o, np.second);
		node_pairs[np.first] = np.second;
		node_pairs[np.second] = np.first;
	      } else if (!onedegree_nodes.count(np.first)) {
		cerr << "adding to onedegree node (A)\n";
		assert(node_pairs.find(np.first) == node_pairs.end());
		breakOneDegreeNode(np.second);
		breakNodePair(np.second);
		int o = nodes.getOneDegreeNode(np.second);
		addChild(o, np.first);
		onedegree_nodes[np.first] = np.second;
	      }
	    }
	  } else {
	    breakNodePair(np.first);
	  }
	  if (np.first != np.second) {
	    if (td2.indegree == 0 && td2.outdegree == 0) {
	      if (zerodegree_nodes.count(np.second) != 0) {
		cerr << "DEBUG: removing node " << np.second << " from zero degree node (B)\n";
		removeChild(np.second);
		zerodegree_nodes.erase(np.second);
	      }
	      if (td1.indegree == 0 && td1.outdegree == 0) {
		// pair was created
	      } else if (!onedegree_nodes.count(np.second)) {
		if (node_pairs.count(np.second)) {
		  cerr << "ERROR!\n";
		} else {
		  cerr << "adding child " << np.second << " to onedegree node (B) [td1.i = " << td1.indegree << ", td1.o = " << td1.outdegree << "]\n";
		  assert(node_pairs.find(np.second) == node_pairs.end());
		  breakOneDegreeNode(np.first);
		  breakNodePair(np.first);
		  int o = nodes.getOneDegreeNode(np.first);
		  addChild(o, np.second);
		  onedegree_nodes[np.second] = np.first;
		}
	      }
	    } else {
	      breakNodePair(np.second);
	    }

	    auto it1 = onedegree_nodes.find(np.first);
	    auto it2 = onedegree_nodes.find(np.second);
	    if (it1 != onedegree_nodes.end() && np.second != it1->second && (td1.indegree != 0 || td2.outdegree != 0)) {
	      removeChild(np.first);
	      onedegree_nodes.erase(it1);
	    }
	    if (it2 != onedegree_nodes.end() && np.first != it2->second && (td2.indegree != 0 || td2.outdegree != 0)) {
	      removeChild(np.second);
	      onedegree_nodes.erase(it2);
	    }
	  }
	  seen_edges[np.first][np.second] = addEdge(np.first, np.second, -1, 1.0f / 64.0f, 0, getNodeArray().hasTemporalCoverage() ? coverage : 1.0f);
	}
      }
    }
  }

  cerr << "updated graph data, nodes = " << nodes.size() << ", edges = " << getEdgeCount() << ", min_sig = " << getMinSignificance() << ", skipped = " << skipped_count << ", first = " << is_first_level << endl;

  if (is_first_level) {
    stats.setTimeRange(min_time, max_time);
    stats.setNumRawNodes(nodes.size());
    stats.setNumRawEdges(source_graph.getEdgeCount());
    // stats.setNumPosts(num_posts);
    // stats.setNumActiveUsers(num_active_users);
  }

  return is_changed;
}
<commit_msg>fix bugs in simplification<commit_after>#include "DirectedGraph.h"

#include <cassert>
#include <iostream>

#include "RawStatistics.h"

using namespace std;

DirectedGraph::DirectedGraph(int _id) : Graph(_id) {

}

DirectedGraph::DirectedGraph(const DirectedGraph & other) : Graph(other) {

}

std::shared_ptr<Graph>
DirectedGraph::createSimilar() const {
  std::shared_ptr<Graph> graph(new DirectedGraph(getId()));
  graph->setLocationGraphValid(false);
  graph->setNodeVisibility(getNodeVisibility());
  graph->setEdgeVisibility(getEdgeVisibility());
  graph->setFaceVisibility(getFaceVisibility());
  graph->setLabelVisibility(getLabelVisibility());
  graph->setLineWidth(getLineWidth());
  graph->setNodeArray(nodes);

  return graph;
}

void
DirectedGraph::breakNodePair(int node_id) {
  auto it = node_pairs.find(node_id);
  if (it != node_pairs.end()) {
    removeChild(node_id);
    int other_id = it->second;
    node_pairs.erase(it);

    auto it2 = node_pairs.find(other_id);
    assert(it2 != node_pairs.end());
    if (it2 != node_pairs.end()) {
      removeChild(other_id);
      node_pairs.erase(it2);

      // if a pair is broken, we add the other node to first one's group
      int o = getNodeArray().getOneDegreeNode(node_id);
      addChild(o, other_id);
      onedegree_nodes[other_id] = node_id;
    }
  }
}

void
DirectedGraph::breakOneDegreeNode(int node_id) {
  auto it = onedegree_nodes.find(node_id);
  if (it != onedegree_nodes.end()) {
    removeChild(node_id);
    onedegree_nodes.erase(it);
  }
}

void
DirectedGraph::breakZeroDegreeNode(int node_id) {
  auto it = zerodegree_nodes.find(node_id);
  if (it != zerodegree_nodes.end()) {
    removeChild(node_id);
    zerodegree_nodes.erase(it);
  }
}

bool
DirectedGraph::updateData(time_t start_time, time_t end_time, float start_sentiment, float end_sentiment, Graph & source_graph, RawStatistics & stats, bool is_first_level, Graph * base_graph) {
  if (getNodeArray().hasTemporalCoverage() && !(end_time > start_time)) {
    cerr << "invalid time range for updateData: " << start_time << " - " << end_time << endl;
    return false;
  }

  auto & sid = source_graph.getNodeArray().getTable()["source"];
  auto & soid = source_graph.getNodeArray().getTable()["id"];
  auto & user_type = source_graph.getNodeArray().getTable()["type"];
  auto & political_party = source_graph.getNodeArray().getTable()["party"];
  auto & name_column = source_graph.getNodeArray().getTable()["name"];
  auto & uname_column = source_graph.getNodeArray().getTable()["uname"];

  auto begin = source_graph.begin_edges();
  auto end = source_graph.end_edges();
  auto it = begin;

  if (current_pos == -1) {
    clear();
    edge_attributes.clear();
    current_pos = 0;
    cerr << "restarting update, begin = " << begin.get() << ", cp = " << current_pos << ", end = " << end.get() << ", source = " << &source_graph << ", edges = " << source_graph.getEdgeCount() << endl;
  } else {
    cerr << "continuing update, begin = " << begin.get() << ", cp = " << current_pos << ", end = " << end.get() << ", source = " << &source_graph << ", edges = " << source_graph.getEdgeCount() << endl;
    for (int i = 0; i < current_pos; i++) ++it;
  }

  auto & nodes = getNodeArray();

  unsigned int skipped_count = 0;
  bool is_changed = false;
  unsigned int num_edges_processed = 0;
  for ( ; it != end; ++it, current_pos++) {
    num_edges_processed++;

    time_t t = 0;
    float se = 0;
    short lang = 0;
    long long app_id = -1, filter_id = -1;
    bool is_first = false;

    assert(it->face != -1);
    if (it->face != -1) {
      auto & fd = source_graph.getFaceAttributes(it->face);
      t = fd.timestamp;
      se = fd.sentiment;
      lang = fd.lang;
      app_id = fd.app_id;
      filter_id = fd.filter_id;
      is_first = fd.first_edge == current_pos;
    }

    if (it->tail < 0 || it->head < 0 || it->tail >= nodes.size() || it->head >= nodes.size()) {
      cerr << "invalid values: tail = " << it->tail << ", head = " << it->head << ", t = " << t << ", count = " << nodes.size() << ", n = " << num_edges_processed << endl;
      assert(0);
    }

    if ((!start_time || t >= start_time) && (!end_time || t < end_time) &&
	se >= start_sentiment && se <= end_sentiment) {
      if (t < min_time || min_time == 0) min_time = t;
      if (t > max_time) max_time = t;

      pair<int, int> np(it->tail, it->head);
      short first_user_sid = sid.getInt(np.first);
      short target_user_sid = sid.getInt(np.second);
      long long first_user_soid = soid.getInt64(np.first);
      long long target_user_soid = soid.getInt64(np.second);

      auto & td1 = base_graph->getNodeTertiaryData(np.first);
      auto & td2 = base_graph->getNodeTertiaryData(np.second);

      if (!is_first_level) {
	if (td1.indegree < getMinSignificance()) {
	  skipped_count++;
	  continue;
	}
	if (td2.indegree < getMinSignificance()) {
	  skipped_count++;
	  continue;
	}
      }

      is_changed = true;

      auto & target_nd_old = nodes.getNodeData(np.second);
      NodeType target_type = target_nd_old.type;

      if (is_first_level && is_first) {
	stats.addActivity(t, first_user_sid, first_user_soid, lang, app_id, filter_id, PoliticalParty(political_party.getInt(np.first)));
      }

      if (is_first_level && !seen_nodes.count(np.second)) {
	seen_nodes.insert(np.second);
	if (target_type == NODE_HASHTAG) {
	  stats.addHashtag(name_column.getText(np.second));
	  num_hashtags++;
	} else if (target_type == NODE_URL) {
	  stats.addLink(name_column.getText(np.second), uname_column.getText(np.second));
	  num_links++;
	} else {
	  UserType ut = UserType(user_type.getInt(np.second));
	  if (ut != UNKNOWN_TYPE) stats.addUserType(ut);
	  // stats.addPoliticalParty(PoliticalParty(political_party.getInt(np.first)));
	}
      }

      if (target_type != NODE_URL && target_type != NODE_HASHTAG) {
	if (is_first_level && target_type == NODE_ANY) {
	  stats.addReceivedActivity(t, target_user_sid, target_user_soid, app_id, filter_id);
	}

	long long coverage = 0;
	if (getNodeArray().hasTemporalCoverage()) {
	  assert(end_time > start_time);
	  int time_pos = 63LL * (t - start_time) / (end_time - start_time);
	  assert(time_pos >= 0 && time_pos < 64);
	  coverage |= 1 << time_pos;
	}

	unordered_map<int, unordered_map<int, int> >::iterator it1;
	unordered_map<int, int>::iterator it2;
	if ((it1 = seen_edges.find(np.first)) != seen_edges.end() &&
	    (it2 = it1->second.find(np.second)) != it1->second.end()) {
#if 0
	  updateOutdegree(np.first, 1.0f);
	  updateIndegree(np.second, 1.0f);
	  updateNodeSize(np.first);
	  updateNodeSize(np.second);
#endif
	  if (getNodeArray().hasTemporalCoverage()) {
	    auto & ed = getEdgeAttributes(it2->second);
	    ed.coverage |= coverage;
	    float new_weight = 0;
	    for (int i = 0; i < 64; i++) {
	      if (ed.coverage & (1 << i)) new_weight += 1.0f;
	    }
	    new_weight /= 64.0f;
	    updateEdgeWeight(it2->second, new_weight - ed.weight);
	  }
	} else {
	  if (td1.indegree == 0 && td1.outdegree == 0) {
	    bool has_zero = zerodegree_nodes.count(np.first) != 0;
	    if (np.first == np.second && !has_zero) {
	      int z = nodes.getZeroDegreeNode();
	      cerr << "DEBUG: adding node " << np.first << " to zero degree node (id = " << z << ")\n";
	      addChild(z, np.first);
	      zerodegree_nodes.insert(np.first);
	    } else if (np.first != np.second && has_zero) {
	      cerr << "DEBUG: removing node " << np.first << " from zero degree node (A)\n";
	      removeChild(np.first);
	      zerodegree_nodes.erase(np.first);
	    }
	    if (np.first != np.second) {
	      if (td2.indegree == 0 && td2.outdegree == 0) {
		breakZeroDegreeNode(np.second);
		assert(node_pairs.find(np.first) == node_pairs.end());
		assert(node_pairs.find(np.second) == node_pairs.end());
		int o = nodes.getPairsNode();
		cerr << "adding to pairs node\n";
		addChild(o, np.first);
		addChild(o, np.second);
		node_pairs[np.first] = np.second;
		node_pairs[np.second] = np.first;
	      } else if (!onedegree_nodes.count(np.first)) {
		cerr << "adding to onedegree node (A)\n";
		assert(node_pairs.find(np.first) == node_pairs.end());
		breakOneDegreeNode(np.second);
		breakNodePair(np.second);
		int o = nodes.getOneDegreeNode(np.second);
		addChild(o, np.first);
		onedegree_nodes[np.first] = np.second;
	      }
	    }
	  } else {
	    breakNodePair(np.first);
	  }
	  if (np.first != np.second) {
	    if (td2.indegree == 0 && td2.outdegree == 0) {
	      breakZeroDegreeNode(np.second);
	      if (td1.indegree == 0 && td1.outdegree == 0) {
		// pair was created
	      } else if (!onedegree_nodes.count(np.second)) {
		if (node_pairs.count(np.second)) {
		  cerr << "ERROR!\n";
		} else {
		  cerr << "adding child " << np.second << " to onedegree node (B) [td1.i = " << td1.indegree << ", td1.o = " << td1.outdegree << "]\n";
		  assert(node_pairs.find(np.second) == node_pairs.end());
		  breakOneDegreeNode(np.first);
		  breakNodePair(np.first);
		  int o = nodes.getOneDegreeNode(np.first);
		  addChild(o, np.second);
		  onedegree_nodes[np.second] = np.first;
		}
	      }
	    } else {
	      breakNodePair(np.second);
	    }

	    if (td1.indegree != 0 || td1.outdegree != 0) {
	      breakOneDegreeNode(np.first);
	    }
	    if (td2.indegree != 0 || td2.outdegree != 0) {
	      breakOneDegreeNode(np.second);
	    }
	  }
	  seen_edges[np.first][np.second] = addEdge(np.first, np.second, -1, 1.0f / 64.0f, 0, getNodeArray().hasTemporalCoverage() ? coverage : 1.0f);
	}
      }
    }
  }

  cerr << "updated graph data, nodes = " << nodes.size() << ", edges = " << getEdgeCount() << ", min_sig = " << getMinSignificance() << ", skipped = " << skipped_count << ", first = " << is_first_level << endl;

  if (is_first_level) {
    stats.setTimeRange(min_time, max_time);
    stats.setNumRawNodes(nodes.size());
    stats.setNumRawEdges(source_graph.getEdgeCount());
    // stats.setNumPosts(num_posts);
    // stats.setNumActiveUsers(num_active_users);
  }

  return is_changed;
}
<|endoftext|>


<commit_before><commit_msg>Added a lighterweight alternative to std::thread.<commit_after><|endoftext|>


<commit_before>#include <glob.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
#include <dlfcn.h>
#include <Driver.h>
#include "DriverManager.h"
//#include "canopen_priv.h"
//#include "PlutoExcept.h"

#define MAX_PROFILE_NR 0xffff

int verbose = 0;

using namespace std;

//-----------------------------------------------------------------------------
// Private functions
//-----------------------------------------------------------------------------
int DriverManager::getdir(const string& dir, vector<string> &files)
{
    string fullpath = dir + "/*.so";
    glob_t globbuf;

    glob(fullpath.c_str(), 0, NULL, &globbuf);

    for(int i = 0; i < globbuf.gl_pathc; i++)
        files.push_back(globbuf.gl_pathv[i]);

    globfree(&globbuf);

    return 0;
}

std::string& DriverManager::getDriverPath()
{
    if(!_driverPath.empty())
        return _driverPath;

    char* env_path = getenv("CANOPEN_DRIVER_PATH");
    if(env_path)
        _driverPath = env_path;
    else
        _driverPath = "/usr/lib/canmaster/drivers";

    return _driverPath;
}

//-----------------------------------------------------------------------------
// Public functions
//-----------------------------------------------------------------------------

DriverManager::DriverManager()
{
    unsigned int i;
    string path = getDriverPath();

    vector<string> files;
    files.reserve(64);

    getdir( path, files );

    defaultDriver = NULL;

    if (files.size() == 0)
    {
        if (verbose)
        {
            printf("No CAN drivers available in %s\n", path.c_str());
        }
        return;
    }

    for (i = 0; i < files.size(); i++)
    {
        ostringstream error_ss;
        string file = files[i];
        try
        {
            if (verbose)
            {
                printf("%-15s%-55s", "Loading driver ", file.c_str());
            }

            Driver *dr = new Driver(file.c_str());
            if (!dr)
            {
                continue;
            }
            if (defaultDriver == NULL && file.find("can_iom_generic") != string::npos)
            {
                defaultDriver = dr;
            }
            else
            {
                drivers[dr->getFilename()] = dr;
            }
            if (!verbose)
            {
                continue;
            }
            printf("[  OK  ]\n");
            int supportingProfile = -1;
            int profile = dr->getFirstProfile();
            printf("Supported profile(s):");
            while (profile >= 0)
            {
                supportingProfile = 1;
                if (profile == 0)
                {
                    printf(" All");
                    break;
                }
                else
                    printf(" %d", profile);
                if (profile > MAX_PROFILE_NR)
                {
                    printf("(invalid)");
                    break;
                }
                profile = dr->getNextProfile();
            }
            if (supportingProfile == -1)
                printf(" None, using node name only\n");
            else
                printf("\n");
        }
        catch( std::exception& exp )
        {
            if (verbose)
            {
                printf("[FAILED]\n");
            }
            printf("%s", exp.what());
        }
    }
}
DriverManager::~DriverManager()
{
    if (verbose && defaultDriver)
    {
        printf("Unloading driver %-53s[  OK  ]\n", defaultDriver->getFilename().c_str());
    }
    delete defaultDriver;

    driver_t::iterator it;
    for (it = drivers.begin(); it != drivers.end(); ++it)
    {
        Driver *dr = it->second;
        if (verbose)
        {
            printf("Unloading driver %-53s[  OK  ]\n", dr->getFilename().c_str());
        }
        delete dr;
    }
}

int DriverManager::createHandler(const char* nodeName, int profileNr,
        CanIOMapDriver::CanMasterInterface *cmi,
        CanIOMapDriver::CanIOHandlerInterface** chi )
{
    driver_t::iterator it;
    for (it = drivers.begin(); it != drivers.end(); ++it)
    {
        if (0 == it->second->createHandler( nodeName, profileNr, cmi, chi ))
        {
            if (verbose)
            {
                printf("Successful using driver %s for node %s\n", it->second->getFilename().c_str(), nodeName);
            }
            chi2driver[*chi] = it->second;
            return 0;
        }
    }

    if (defaultDriver)
    {
        if (0 == defaultDriver->createHandler( nodeName, profileNr, cmi, chi ))
        {
            if (verbose)
            {
                printf("Successful using driver %s for node %s\n", defaultDriver->getFilename().c_str(), nodeName);
            }
            chi2driver[*chi] = defaultDriver;
            return 0;
        }
    }
    return -1;
}

int DriverManager::deleteHandler(int /*profileNr*/,
        CanIOMapDriver::CanIOHandlerInterface* chi )
{
    Driver *dr = chi2driver[chi];
    if (dr)
    {
        dr->deleteHandler(chi);
        chi2driver.erase(chi);
        return 0;
    }
    return -1;
}

<commit_msg>legacy-driver: Add missing header<commit_after>#include <stdlib.h>
#include <glob.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
#include <dlfcn.h>
#include <Driver.h>
#include "DriverManager.h"
//#include "canopen_priv.h"
//#include "PlutoExcept.h"

#define MAX_PROFILE_NR 0xffff

int verbose = 0;

using namespace std;

//-----------------------------------------------------------------------------
// Private functions
//-----------------------------------------------------------------------------
int DriverManager::getdir(const string& dir, vector<string> &files)
{
    string fullpath = dir + "/*.so";
    glob_t globbuf;

    glob(fullpath.c_str(), 0, NULL, &globbuf);

    for(int i = 0; i < globbuf.gl_pathc; i++)
        files.push_back(globbuf.gl_pathv[i]);

    globfree(&globbuf);

    return 0;
}

std::string& DriverManager::getDriverPath()
{
    if(!_driverPath.empty())
        return _driverPath;

    char* env_path = getenv("CANOPEN_DRIVER_PATH");
    if(env_path)
        _driverPath = env_path;
    else
        _driverPath = "/usr/lib/canmaster/drivers";

    return _driverPath;
}

//-----------------------------------------------------------------------------
// Public functions
//-----------------------------------------------------------------------------

DriverManager::DriverManager()
{
    unsigned int i;
    string path = getDriverPath();

    vector<string> files;
    files.reserve(64);

    getdir( path, files );

    defaultDriver = NULL;

    if (files.size() == 0)
    {
        if (verbose)
        {
            printf("No CAN drivers available in %s\n", path.c_str());
        }
        return;
    }

    for (i = 0; i < files.size(); i++)
    {
        ostringstream error_ss;
        string file = files[i];
        try
        {
            if (verbose)
            {
                printf("%-15s%-55s", "Loading driver ", file.c_str());
            }

            Driver *dr = new Driver(file.c_str());
            if (!dr)
            {
                continue;
            }
            if (defaultDriver == NULL && file.find("can_iom_generic") != string::npos)
            {
                defaultDriver = dr;
            }
            else
            {
                drivers[dr->getFilename()] = dr;
            }
            if (!verbose)
            {
                continue;
            }
            printf("[  OK  ]\n");
            int supportingProfile = -1;
            int profile = dr->getFirstProfile();
            printf("Supported profile(s):");
            while (profile >= 0)
            {
                supportingProfile = 1;
                if (profile == 0)
                {
                    printf(" All");
                    break;
                }
                else
                    printf(" %d", profile);
                if (profile > MAX_PROFILE_NR)
                {
                    printf("(invalid)");
                    break;
                }
                profile = dr->getNextProfile();
            }
            if (supportingProfile == -1)
                printf(" None, using node name only\n");
            else
                printf("\n");
        }
        catch( std::exception& exp )
        {
            if (verbose)
            {
                printf("[FAILED]\n");
            }
            printf("%s", exp.what());
        }
    }
}
DriverManager::~DriverManager()
{
    if (verbose && defaultDriver)
    {
        printf("Unloading driver %-53s[  OK  ]\n", defaultDriver->getFilename().c_str());
    }
    delete defaultDriver;

    driver_t::iterator it;
    for (it = drivers.begin(); it != drivers.end(); ++it)
    {
        Driver *dr = it->second;
        if (verbose)
        {
            printf("Unloading driver %-53s[  OK  ]\n", dr->getFilename().c_str());
        }
        delete dr;
    }
}

int DriverManager::createHandler(const char* nodeName, int profileNr,
        CanIOMapDriver::CanMasterInterface *cmi,
        CanIOMapDriver::CanIOHandlerInterface** chi )
{
    driver_t::iterator it;
    for (it = drivers.begin(); it != drivers.end(); ++it)
    {
        if (0 == it->second->createHandler( nodeName, profileNr, cmi, chi ))
        {
            if (verbose)
            {
                printf("Successful using driver %s for node %s\n", it->second->getFilename().c_str(), nodeName);
            }
            chi2driver[*chi] = it->second;
            return 0;
        }
    }

    if (defaultDriver)
    {
        if (0 == defaultDriver->createHandler( nodeName, profileNr, cmi, chi ))
        {
            if (verbose)
            {
                printf("Successful using driver %s for node %s\n", defaultDriver->getFilename().c_str(), nodeName);
            }
            chi2driver[*chi] = defaultDriver;
            return 0;
        }
    }
    return -1;
}

int DriverManager::deleteHandler(int /*profileNr*/,
        CanIOMapDriver::CanIOHandlerInterface* chi )
{
    Driver *dr = chi2driver[chi];
    if (dr)
    {
        dr->deleteHandler(chi);
        chi2driver.erase(chi);
        return 0;
    }
    return -1;
}

<|endoftext|>


<commit_before>/***********************************/
/* Kicad: Common plot DXF Routines */
/***********************************/

#include "fctsys.h"
#include "gr_basic.h"
#include "trigo.h"
#include "wxstruct.h"
#include "base_struct.h"
#include "plot_common.h"
#include "macros.h"
#include "kicad_string.h"

/* Set the plot offset for the current plotting
 */
void DXF_PLOTTER::set_viewport( wxPoint offset,
                                double aScale, int orient )
{
    wxASSERT( !output_file );
    plot_offset  = offset;
    plot_scale   = aScale;
    device_scale = 1;
    set_default_line_width( 0 );    /* No line width on DXF */
    plot_orient_options = 0;        /* No mirroring on DXF */
    current_color = BLACK;
}

void DXF_PLOTTER::start_plot( FILE* fout )
{
    wxASSERT( !output_file );
    output_file = fout;
    /* DXF HEADER - Boilerplate */
    fputs( "0\nSECTION\n2\nHEADER\n9\n$ANGBASE\n50\n0.0\n9\n$ANGDIR\n70\n0\n0\nENDSEC\n0\nSECTION\n2\nTABLES\n0\nTABLE\n2\nLTYPE\n70\n1\n0\nLTYPE\n2\nCONTINUOUS\n70\n0\n3\nSolid line\n72\n65\n73\n0\n40\n0.0\n0\nENDTAB\n",
           output_file );
    /* Layer table - one layer per color */
    fprintf( output_file, "0\nTABLE\n2\nLAYER\n70\n%d\n", NBCOLOR );
    for( int i = 0; i<NBCOLOR; i++ )
    {
        wxString cname = ColorRefs[i].m_Name;
        fprintf( output_file, "0\nLAYER\n2\n%s\n70\n0\n62\n%d\n6\nCONTINUOUS\n",
                 CONV_TO_UTF8( cname ), i + 1 );
    }

    /* End of layer table, begin entities */
    fputs( "0\nENDTAB\n0\nENDSEC\n0\nSECTION\n2\nENTITIES\n", output_file );
}

void DXF_PLOTTER::end_plot()
{
    wxASSERT( output_file );
    /* DXF FOOTER */
    fputs( "0\nENDSEC\n0\nEOF\n", output_file );
    fclose( output_file );
    output_file = 0;
}

/*
 * color = color index in ColorRefs[]
 */
void DXF_PLOTTER::set_color( int color )
{
    wxASSERT( output_file );
    if( ( color >= 0 && color_mode )
       || ( color == BLACK )
       || ( color == WHITE ) )
    {
        current_color = color;
    }
}

void DXF_PLOTTER::rect( wxPoint p1, wxPoint p2, FILL_T fill, int width )
{
    wxASSERT( output_file );
    move_to( p1 );
    line_to( wxPoint( p1.x, p2.y ) );
    line_to( wxPoint( p2.x, p2.y ) );
    line_to( wxPoint( p2.x, p1.y ) );
    finish_to( wxPoint( p1.x, p1.y ) );
}

void DXF_PLOTTER::circle( wxPoint centre, int diameter, FILL_T fill, int width )
{
    wxASSERT( output_file );
    double radius = user_to_device_size( diameter / 2 );
    user_to_device_coordinates( centre );
    if( radius > 0 )
    {
        wxString cname = ColorRefs[current_color].m_Name;
        fprintf( output_file, "0\nCIRCLE\n8\n%s\n10\n%d.0\n20\n%d.0\n40\n%g\n",
                 CONV_TO_UTF8( cname ),
                 centre.x, centre.y, radius );
    }
}

/* Draw a polygon (closed if completed) in DXF format
 * coord = coord table tops
 * nb = number of coord (coord 1 = 2 elements: X and Y table)
 * fill: if != 0 filled polygon
 */
void DXF_PLOTTER::poly( int nb, int* coord, FILL_T fill, int width )
{
    wxASSERT( output_file );
    if( nb <= 1 )
        return;

    move_to( wxPoint( coord[0], coord[1] ) );
    for( int ii = 1; ii < nb; ii++ )
        line_to( wxPoint( coord[ii * 2], coord[(ii * 2) + 1] ) );

    /* Close polygon. */
    if( fill )
    {
        int ii = (nb - 1) * 2;
        if( ( coord[ii] != coord[0] ) || ( coord[ii + 1] != coord[1] ) )
            line_to( wxPoint( coord[0], coord[1] ) );
    }
    pen_finish();
}

/*
 * Move the pen up (pen = 'U') or down (feather = 'D') at position x, y
 * Unit to unit DRAWING
 * If pen = 'Z' without lifting pen displacement
 */
void DXF_PLOTTER::pen_to( wxPoint pos, char plume )
{
    wxASSERT( output_file );
    if( plume == 'Z' )
    {
        return;
    }
    user_to_device_coordinates( pos );

    if( pen_lastpos != pos && plume == 'D' )
    {
        /* DXF LINE */
        wxString cname = ColorRefs[current_color].m_Name;
        fprintf( output_file, "0\nLINE\n8\n%s\n10\n%d.0\n20\n%d.0\n11\n%d.0\n21\n%d.0\n",
                 CONV_TO_UTF8( cname ),
                 pen_lastpos.x, pen_lastpos.y, pos.x, pos.y );
    }
    pen_lastpos = pos;
}

void DXF_PLOTTER::set_dash( bool dashed )
{
    /* NOP for now */
    wxASSERT( output_file );
}

/** Function Plot a filled segment (track)
 * @param start = starting point
 * @param end = ending point
 * @param aWidth = segment width (thickness)
 * @param aPlotMode = FILLED, SKETCH ..
 */
void DXF_PLOTTER::thick_segment( wxPoint start, wxPoint end, int width,
                                 GRTraceMode tracemode )
{
    wxASSERT( output_file );

    if( tracemode == FILAIRE )  /* just a line is Ok */
    {
        move_to( start );
        finish_to( end );
    }
    else
        segment_as_oval( start, end, width, tracemode );
}

/* Plot an arc in DXF format.
 * center = center coord
 * StAngle, EndAngle = angle of beginning and end
 * Radius = radius of the arc
 */
void DXF_PLOTTER::arc( wxPoint centre, int StAngle, int EndAngle, int radius,
                       FILL_T fill, int width )
{
    wxASSERT( output_file );

    if( radius <= 0 )
        return;

    user_to_device_coordinates( centre );
    radius = wxRound( user_to_device_size( radius ) );

    /* DXF ARC */
    wxString cname = ColorRefs[current_color].m_Name;
    fprintf( output_file,
             "0\nARC\n8\n%s\n10\n%d.0\n20\n%d.0\n40\n%d.0\n50\n%d.0\n51\n%d.0\n",
             CONV_TO_UTF8( cname ),
             centre.x, centre.y, radius,
             StAngle / 10, EndAngle / 10 );
}

/* Plot oval pad at position. */
void DXF_PLOTTER::flash_pad_oval( wxPoint pos, wxSize size, int orient,
                                  GRTraceMode trace_mode )
{
    wxASSERT( output_file );

    /* The chip is reduced to an oval tablet with size.y > size.x
     * (Oval vertical orientation 0) */
    if( size.x > size.y )
    {
        EXCHG( size.x, size.y );
        orient += 900;
        if( orient >= 3600 )
            orient -= 3600;
    }
    sketch_oval( pos, size, orient, -1 );
}

/* Plot round pad or via. */
void DXF_PLOTTER::flash_pad_circle( wxPoint pos, int diametre,
                                    GRTraceMode trace_mode )
{
    wxASSERT( output_file );
    circle( pos, diametre, NO_FILL );
}

/*
 * Plot rectangular pad vertical or horizontal (rectangular Pad)
 */
void DXF_PLOTTER::flash_pad_rect( wxPoint pos, wxSize padsize,
                                  int orient, GRTraceMode trace_mode )
{
    wxASSERT( output_file );
    wxSize size;
    int    ox, oy, fx, fy;

    size.x = padsize.x / 2;  size.y = padsize.y / 2;

    if( size.x < 0 )
        size.x = 0;
    if( size.y < 0 )
        size.y = 0;

    /* If a dimension is zero, the trace is reduced to 1 line. */
    if( size.x == 0 )
    {
        ox = pos.x;
        oy = pos.y - size.y;
        RotatePoint( &ox, &oy, pos.x, pos.y, orient );
        fx = pos.x;
        fy = pos.y + size.y;
        RotatePoint( &fx, &fy, pos.x, pos.y, orient );
        move_to( wxPoint( ox, oy ) );
        finish_to( wxPoint( fx, fy ) );
        return;
    }
    if( size.y == 0 )
    {
        ox = pos.x - size.x;
        oy = pos.y;
        RotatePoint( &ox, &oy, pos.x, pos.y, orient );
        fx = pos.x + size.x;
        fy = pos.y;
        RotatePoint( &fx, &fy, pos.x, pos.y, orient );
        move_to( wxPoint( ox, oy ) );
        finish_to( wxPoint( fx, fy ) );
        return;
    }

    ox = pos.x - size.x;
    oy = pos.y - size.y;
    RotatePoint( &ox, &oy, pos.x, pos.y, orient );
    move_to( wxPoint( ox, oy ) );

    fx = pos.x - size.x;
    fy = pos.y + size.y;
    RotatePoint( &fx, &fy, pos.x, pos.y, orient );
    line_to( wxPoint( fx, fy ) );

    fx = pos.x + size.x;
    fy = pos.y + size.y;
    RotatePoint( &fx, &fy, pos.x, pos.y, orient );
    line_to( wxPoint( fx, fy ) );

    fx = pos.x + size.x;
    fy = pos.y - size.y;
    RotatePoint( &fx, &fy, pos.x, pos.y, orient );
    line_to( wxPoint( fx, fy ) );

    finish_to( wxPoint( ox, oy ) );
}

/*
 * Plot trapezoidal pad.
 * pos  its center, pos.y
 * Dimensions dim X and dimy
 * DeltaX and variations deltaY
 * Orientation and 0.1 degrees east
 * Plot mode (FILLED, SKETCH, WIRED)
 * The evidence is that a trapezoid, ie that deltaX or deltaY
 * = 0.
 *
 * The rating of the vertexes are (vis a vis the plotter)
 *      0 ------------- 3
 *        .            .
 *          .         .
 *           .       .
 *            1 --- 2
 */

void DXF_PLOTTER::flash_pad_trapez( wxPoint pos, wxSize size, wxSize delta,
                                    int orient, GRTraceMode trace_mode )
{
    wxASSERT( output_file );
    wxPoint polygone[4];    /* coord of vertex or center of the pad */
    wxPoint coord[4];       /* coord actual corners of a trapezoidal trace */
    int     moveX, moveY;   /* change pen position by X and Y axis to
                             * fill the trapezoid */
    moveX = moveY = 0;

    size.x /= 2;
    size.y /= 2;
    delta.x /= 2;
    delta.y /= 2;

    polygone[0].x = -size.x - delta.y;
    polygone[0].y = +size.y + delta.x;
    polygone[1].x = -size.x + delta.y;
    polygone[1].y = -size.y - delta.x;
    polygone[2].x = +size.x - delta.y;
    polygone[2].y = -size.y + delta.x;
    polygone[3].x = +size.x + delta.y;
    polygone[3].y = +size.y - delta.x;

    for( int ii = 0; ii < 4; ii++ )
    {
        coord[ii].x = polygone[ii].x + pos.x;
        coord[ii].y = polygone[ii].y + pos.y;
        RotatePoint( &coord[ii], pos, orient );
    }

    // Plot edge:
    move_to( coord[0] );
    line_to( coord[1] );
    line_to( coord[2] );
    line_to( coord[3] );
    finish_to( coord[0] );
}
<commit_msg>Added filling of junctions circles to EEschema DXF export<commit_after>/***********************************/
/* Kicad: Common plot DXF Routines */
/***********************************/

#include "fctsys.h"
#include "gr_basic.h"
#include "trigo.h"
#include "wxstruct.h"
#include "base_struct.h"
#include "plot_common.h"
#include "macros.h"
#include "kicad_string.h"

/* Set the plot offset for the current plotting
 */
void DXF_PLOTTER::set_viewport( wxPoint offset,
                                double aScale, int orient )
{
    wxASSERT( !output_file );
    plot_offset  = offset;
    plot_scale   = aScale;
    device_scale = 1;
    set_default_line_width( 0 );    /* No line width on DXF */
    plot_orient_options = 0;        /* No mirroring on DXF */
    current_color = BLACK;
}

void DXF_PLOTTER::start_plot( FILE* fout )
{
    wxASSERT( !output_file );
    output_file = fout;
    /* DXF HEADER - Boilerplate */
    fputs( "0\nSECTION\n2\nHEADER\n9\n$ANGBASE\n50\n0.0\n9\n$ANGDIR\n70\n0\n0\nENDSEC\n0\nSECTION\n2\nTABLES\n0\nTABLE\n2\nLTYPE\n70\n1\n0\nLTYPE\n2\nCONTINUOUS\n70\n0\n3\nSolid line\n72\n65\n73\n0\n40\n0.0\n0\nENDTAB\n",
           output_file );
    /* Layer table - one layer per color */
    fprintf( output_file, "0\nTABLE\n2\nLAYER\n70\n%d\n", NBCOLOR );
    for( int i = 0; i<NBCOLOR; i++ )
    {
        wxString cname = ColorRefs[i].m_Name;
        fprintf( output_file, "0\nLAYER\n2\n%s\n70\n0\n62\n%d\n6\nCONTINUOUS\n",
                 CONV_TO_UTF8( cname ), i + 1 );
    }

    /* End of layer table, begin entities */
    fputs( "0\nENDTAB\n0\nENDSEC\n0\nSECTION\n2\nENTITIES\n", output_file );
}

void DXF_PLOTTER::end_plot()
{
    wxASSERT( output_file );
    /* DXF FOOTER */
    fputs( "0\nENDSEC\n0\nEOF\n", output_file );
    fclose( output_file );
    output_file = 0;
}

/*
 * color = color index in ColorRefs[]
 */
void DXF_PLOTTER::set_color( int color )
{
    wxASSERT( output_file );
    if( ( color >= 0 && color_mode )
       || ( color == BLACK )
       || ( color == WHITE ) )
    {
        current_color = color;
    }
}

void DXF_PLOTTER::rect( wxPoint p1, wxPoint p2, FILL_T fill, int width )
{
    wxASSERT( output_file );
    move_to( p1 );
    line_to( wxPoint( p1.x, p2.y ) );
    line_to( wxPoint( p2.x, p2.y ) );
    line_to( wxPoint( p2.x, p1.y ) );
    finish_to( wxPoint( p1.x, p1.y ) );
}

void DXF_PLOTTER::circle( wxPoint centre, int diameter, FILL_T fill, int width )
{
    wxASSERT( output_file );
    double radius = user_to_device_size( diameter / 2 );
    user_to_device_coordinates( centre );
    if( radius > 0 )
    {
        wxString cname = ColorRefs[current_color].m_Name;
        if (!fill) {
          fprintf( output_file, "0\nCIRCLE\n8\n%s\n10\n%d.0\n20\n%d.0\n40\n%g\n",
                  CONV_TO_UTF8( cname ),
                  centre.x, centre.y, radius );
        }
        if (fill == FILLED_SHAPE) {
            int r = (int)(radius*0.5);
            fprintf( output_file, "0\nPOLYLINE\n");
            fprintf( output_file, "8\n%s\n66\n1\n70\n1\n", CONV_TO_UTF8( cname ));
            fprintf( output_file, "40\n%g\n41\n%g\n", radius,radius);
            fprintf( output_file, "0\nVERTEX\n8\n%s\n", CONV_TO_UTF8( cname ));
            fprintf( output_file, "10\n%d.0\n 20\n%d.0\n42\n1.0\n", centre.x-r,centre.y);
            fprintf( output_file, "0\nVERTEX\n8\n%s\n", CONV_TO_UTF8( cname ));
            fprintf( output_file, "10\n%d.0\n 20\n%d.0\n42\n1.0\n", centre.x+r,centre.y);
            fprintf( output_file, "0\nSEQEND\n");
	}
     }
}

/* Draw a polygon (closed if completed) in DXF format
 * coord = coord table tops
 * nb = number of coord (coord 1 = 2 elements: X and Y table)
 * fill: if != 0 filled polygon
 */
void DXF_PLOTTER::poly( int nb, int* coord, FILL_T fill, int width )
{
    wxASSERT( output_file );
    if( nb <= 1 )
        return;

    move_to( wxPoint( coord[0], coord[1] ) );
    for( int ii = 1; ii < nb; ii++ )
        line_to( wxPoint( coord[ii * 2], coord[(ii * 2) + 1] ) );

    /* Close polygon. */
    if( fill )
    {
        int ii = (nb - 1) * 2;
        if( ( coord[ii] != coord[0] ) || ( coord[ii + 1] != coord[1] ) )
            line_to( wxPoint( coord[0], coord[1] ) );
    }
    pen_finish();
}

/*
 * Move the pen up (pen = 'U') or down (feather = 'D') at position x, y
 * Unit to unit DRAWING
 * If pen = 'Z' without lifting pen displacement
 */
void DXF_PLOTTER::pen_to( wxPoint pos, char plume )
{
    wxASSERT( output_file );
    if( plume == 'Z' )
    {
        return;
    }
    user_to_device_coordinates( pos );

    if( pen_lastpos != pos && plume == 'D' )
    {
        /* DXF LINE */
        wxString cname = ColorRefs[current_color].m_Name;
        fprintf( output_file, "0\nLINE\n8\n%s\n10\n%d.0\n20\n%d.0\n11\n%d.0\n21\n%d.0\n",
                 CONV_TO_UTF8( cname ),
                 pen_lastpos.x, pen_lastpos.y, pos.x, pos.y );
    }
    pen_lastpos = pos;
}

void DXF_PLOTTER::set_dash( bool dashed )
{
    /* NOP for now */
    wxASSERT( output_file );
}

/** Function Plot a filled segment (track)
 * @param start = starting point
 * @param end = ending point
 * @param aWidth = segment width (thickness)
 * @param aPlotMode = FILLED, SKETCH ..
 */
void DXF_PLOTTER::thick_segment( wxPoint start, wxPoint end, int width,
                                 GRTraceMode tracemode )
{
    wxASSERT( output_file );

    if( tracemode == FILAIRE )  /* just a line is Ok */
    {
        move_to( start );
        finish_to( end );
    }
    else
        segment_as_oval( start, end, width, tracemode );
}

/* Plot an arc in DXF format.
 * center = center coord
 * StAngle, EndAngle = angle of beginning and end
 * Radius = radius of the arc
 */
void DXF_PLOTTER::arc( wxPoint centre, int StAngle, int EndAngle, int radius,
                       FILL_T fill, int width )
{
    wxASSERT( output_file );

    if( radius <= 0 )
        return;

    user_to_device_coordinates( centre );
    radius = wxRound( user_to_device_size( radius ) );

    /* DXF ARC */
    wxString cname = ColorRefs[current_color].m_Name;
    fprintf( output_file,
             "0\nARC\n8\n%s\n10\n%d.0\n20\n%d.0\n40\n%d.0\n50\n%d.0\n51\n%d.0\n",
             CONV_TO_UTF8( cname ),
             centre.x, centre.y, radius,
             StAngle / 10, EndAngle / 10 );
}

/* Plot oval pad at position. */
void DXF_PLOTTER::flash_pad_oval( wxPoint pos, wxSize size, int orient,
                                  GRTraceMode trace_mode )
{
    wxASSERT( output_file );

    /* The chip is reduced to an oval tablet with size.y > size.x
     * (Oval vertical orientation 0) */
    if( size.x > size.y )
    {
        EXCHG( size.x, size.y );
        orient += 900;
        if( orient >= 3600 )
            orient -= 3600;
    }
    sketch_oval( pos, size, orient, -1 );
}

/* Plot round pad or via. */
void DXF_PLOTTER::flash_pad_circle( wxPoint pos, int diametre,
                                    GRTraceMode trace_mode )
{
    wxASSERT( output_file );
    circle( pos, diametre, NO_FILL );
}

/*
 * Plot rectangular pad vertical or horizontal (rectangular Pad)
 */
void DXF_PLOTTER::flash_pad_rect( wxPoint pos, wxSize padsize,
                                  int orient, GRTraceMode trace_mode )
{
    wxASSERT( output_file );
    wxSize size;
    int    ox, oy, fx, fy;

    size.x = padsize.x / 2;  size.y = padsize.y / 2;

    if( size.x < 0 )
        size.x = 0;
    if( size.y < 0 )
        size.y = 0;

    /* If a dimension is zero, the trace is reduced to 1 line. */
    if( size.x == 0 )
    {
        ox = pos.x;
        oy = pos.y - size.y;
        RotatePoint( &ox, &oy, pos.x, pos.y, orient );
        fx = pos.x;
        fy = pos.y + size.y;
        RotatePoint( &fx, &fy, pos.x, pos.y, orient );
        move_to( wxPoint( ox, oy ) );
        finish_to( wxPoint( fx, fy ) );
        return;
    }
    if( size.y == 0 )
    {
        ox = pos.x - size.x;
        oy = pos.y;
        RotatePoint( &ox, &oy, pos.x, pos.y, orient );
        fx = pos.x + size.x;
        fy = pos.y;
        RotatePoint( &fx, &fy, pos.x, pos.y, orient );
        move_to( wxPoint( ox, oy ) );
        finish_to( wxPoint( fx, fy ) );
        return;
    }

    ox = pos.x - size.x;
    oy = pos.y - size.y;
    RotatePoint( &ox, &oy, pos.x, pos.y, orient );
    move_to( wxPoint( ox, oy ) );

    fx = pos.x - size.x;
    fy = pos.y + size.y;
    RotatePoint( &fx, &fy, pos.x, pos.y, orient );
    line_to( wxPoint( fx, fy ) );

    fx = pos.x + size.x;
    fy = pos.y + size.y;
    RotatePoint( &fx, &fy, pos.x, pos.y, orient );
    line_to( wxPoint( fx, fy ) );

    fx = pos.x + size.x;
    fy = pos.y - size.y;
    RotatePoint( &fx, &fy, pos.x, pos.y, orient );
    line_to( wxPoint( fx, fy ) );

    finish_to( wxPoint( ox, oy ) );
}

/*
 * Plot trapezoidal pad.
 * pos  its center, pos.y
 * Dimensions dim X and dimy
 * DeltaX and variations deltaY
 * Orientation and 0.1 degrees east
 * Plot mode (FILLED, SKETCH, WIRED)
 * The evidence is that a trapezoid, ie that deltaX or deltaY
 * = 0.
 *
 * The rating of the vertexes are (vis a vis the plotter)
 *      0 ------------- 3
 *        .            .
 *          .         .
 *           .       .
 *            1 --- 2
 */

void DXF_PLOTTER::flash_pad_trapez( wxPoint pos, wxSize size, wxSize delta,
                                    int orient, GRTraceMode trace_mode )
{
    wxASSERT( output_file );
    wxPoint polygone[4];    /* coord of vertex or center of the pad */
    wxPoint coord[4];       /* coord actual corners of a trapezoidal trace */
    int     moveX, moveY;   /* change pen position by X and Y axis to
                             * fill the trapezoid */
    moveX = moveY = 0;

    size.x /= 2;
    size.y /= 2;
    delta.x /= 2;
    delta.y /= 2;

    polygone[0].x = -size.x - delta.y;
    polygone[0].y = +size.y + delta.x;
    polygone[1].x = -size.x + delta.y;
    polygone[1].y = -size.y - delta.x;
    polygone[2].x = +size.x - delta.y;
    polygone[2].y = -size.y + delta.x;
    polygone[3].x = +size.x + delta.y;
    polygone[3].y = +size.y - delta.x;

    for( int ii = 0; ii < 4; ii++ )
    {
        coord[ii].x = polygone[ii].x + pos.x;
        coord[ii].y = polygone[ii].y + pos.y;
        RotatePoint( &coord[ii], pos, orient );
    }

    // Plot edge:
    move_to( coord[0] );
    line_to( coord[1] );
    line_to( coord[2] );
    line_to( coord[3] );
    finish_to( coord[0] );
}
<|endoftext|>


<commit_before>/**
 * Copyright (C) 2015 Virgil Security Inc.
 *
 * Lead Maintainer: Virgil Security Inc. <support@virgilsecurity.com>
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     (1) Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *     (2) Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *     (3) Neither the name of the copyright holder nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef INI_HPP
#define INI_HPP

#include <cassert>
#include <map>
#include <list>
#include <stdexcept>
#include <string>
#include <cstring>
#include <iostream>
#include <fstream>

namespace INI {

struct Level {
    Level() : parent(NULL), depth(0) {
    }
    Level(Level* p) : parent(p), depth(0) {
    }

    typedef std::map<std::string, std::string> value_map_t;
    typedef std::map<std::string, Level> section_map_t;
    typedef std::list<value_map_t::const_iterator> values_t;
    typedef std::list<section_map_t::const_iterator> sections_t;
    value_map_t values;
    section_map_t sections;
    values_t ordered_values; // original order in the ini file
    sections_t ordered_sections;
    Level* parent;
    size_t depth;

    const std::string& operator[](const std::string& name) {
        return values[name];
    }
    Level& operator()(const std::string& name) {
        return sections[name];
    }
};

class Parser {
public:
    Parser(const char* fn);
    Parser(std::istream& f) : f_(&f), ln_(0) {
        parse(top_);
    }
    Level& top() {
        return top_;
    }
    void dump(std::ostream& s) {
        dump(s, top(), "");
    }

private:
    void dump(std::ostream& s, const Level& l, const std::string& sname);
    void parse(Level& l);
    void parseSLine(std::string& sname, size_t& depth);
    void err(const char* s);

private:
    Level top_;
    std::ifstream f0_;
    std::istream* f_;
    std::string line_;
    size_t ln_;
};

inline void Parser::err(const char* s) {
    char buf[256];
    sprintf(buf, "%s on line #%ld", s, ln_);
    throw std::runtime_error(buf);
}

inline std::string trim(const std::string& s) {
    char p[] = " \t\r\n";
    long sp = 0;
    long ep = s.length() - 1;
    for (; sp <= ep; ++sp)
        if (!strchr(p, s[sp]))
            break;
    for (; ep >= 0; --ep)
        if (!strchr(p, s[ep]))
            break;
    return s.substr(sp, ep - sp + 1);
}

inline Parser::Parser(const char* fn) : f0_(fn), f_(&f0_), ln_(0) {
    if (!f0_)
        throw std::runtime_error(std::string("failed to open file: ") + fn);

    parse(top_);
}

inline void Parser::parseSLine(std::string& sname, size_t& depth) {
    depth = 0;
    for (; depth < line_.length(); ++depth)
        if (line_[depth] != '[')
            break;

    sname = line_.substr(depth, line_.length() - 2 * depth);
}

inline void Parser::parse(Level& l) {
    while (std::getline(*f_, line_)) {
        ++ln_;
        if (line_[0] == '#' || line_[0] == ';')
            continue;
        line_ = trim(line_);
        if (line_.empty())
            continue;
        if (line_[0] == '[') {
            size_t depth;
            std::string sname;
            parseSLine(sname, depth);
            Level* lp = NULL;
            Level* parent = &l;
            if (depth > l.depth + 1)
                err("section with wrong depth");
            if (l.depth == depth - 1)
                lp = &l.sections[sname];
            else {
                lp = l.parent;
                size_t n = l.depth - depth;
                for (size_t i = 0; i < n; ++i)
                    lp = lp->parent;
                parent = lp;
                lp = &lp->sections[sname];
            }
            if (lp->depth != 0)
                err("duplicate section name on the same level");
            if (!lp->parent) {
                lp->depth = depth;
                lp->parent = parent;
            }
            parent->ordered_sections.push_back(parent->sections.find(sname));
            parse(*lp);
        } else {
            size_t n = line_.find('=');
            if (n == std::string::npos)
                err("no '=' found");
            std::pair<Level::value_map_t::const_iterator, bool> res = l.values.insert(
                std::make_pair(trim(line_.substr(0, n)), trim(line_.substr(n + 1, line_.length() - n - 1))));
            if (!res.second)
                err("duplicated key found");
            l.ordered_values.push_back(res.first);
        }
    }
}

inline void Parser::dump(std::ostream& s, const Level& l, const std::string& sname) {
    if (!sname.empty())
        s << '\n';
    for (size_t i = 0; i < l.depth; ++i)
        s << '[';
    if (!sname.empty())
        s << sname;
    for (size_t i = 0; i < l.depth; ++i)
        s << ']';
    if (!sname.empty())
        s << std::endl;
    for (Level::values_t::const_iterator it = l.ordered_values.begin(); it != l.ordered_values.end(); ++it)
        s << (*it)->first << '=' << (*it)->second << std::endl;
    for (Level::sections_t::const_iterator it = l.ordered_sections.begin(); it != l.ordered_sections.end(); ++it) {
        assert((*it)->second.depth == l.depth + 1);
        dump(s, (*it)->second, (*it)->first);
    }
}
}

#endif // INI_HPP
<commit_msg>Fix wrong licence for .ini parser<commit_after>/**
 * The MIT License (MIT)
 * Copyright (c) <2015> <carriez.md@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
  *
  */

#ifndef INI_HPP
#define INI_HPP

#include <cassert>
#include <map>
#include <list>
#include <stdexcept>
#include <string>
#include <cstring>
#include <iostream>
#include <fstream>

namespace INI {

struct Level {
    Level() : parent(NULL), depth(0) {
    }
    Level(Level* p) : parent(p), depth(0) {
    }

    typedef std::map<std::string, std::string> value_map_t;
    typedef std::map<std::string, Level> section_map_t;
    typedef std::list<value_map_t::const_iterator> values_t;
    typedef std::list<section_map_t::const_iterator> sections_t;
    value_map_t values;
    section_map_t sections;
    values_t ordered_values; // original order in the ini file
    sections_t ordered_sections;
    Level* parent;
    size_t depth;

    const std::string& operator[](const std::string& name) {
        return values[name];
    }
    Level& operator()(const std::string& name) {
        return sections[name];
    }
};

class Parser {
public:
    Parser(const char* fn);
    Parser(std::istream& f) : f_(&f), ln_(0) {
        parse(top_);
    }
    Level& top() {
        return top_;
    }
    void dump(std::ostream& s) {
        dump(s, top(), "");
    }

private:
    void dump(std::ostream& s, const Level& l, const std::string& sname);
    void parse(Level& l);
    void parseSLine(std::string& sname, size_t& depth);
    void err(const char* s);

private:
    Level top_;
    std::ifstream f0_;
    std::istream* f_;
    std::string line_;
    size_t ln_;
};

inline void Parser::err(const char* s) {
    char buf[256];
    sprintf(buf, "%s on line #%ld", s, ln_);
    throw std::runtime_error(buf);
}

inline std::string trim(const std::string& s) {
    char p[] = " \t\r\n";
    long sp = 0;
    long ep = s.length() - 1;
    for (; sp <= ep; ++sp)
        if (!strchr(p, s[sp]))
            break;
    for (; ep >= 0; --ep)
        if (!strchr(p, s[ep]))
            break;
    return s.substr(sp, ep - sp + 1);
}

inline Parser::Parser(const char* fn) : f0_(fn), f_(&f0_), ln_(0) {
    if (!f0_)
        throw std::runtime_error(std::string("failed to open file: ") + fn);

    parse(top_);
}

inline void Parser::parseSLine(std::string& sname, size_t& depth) {
    depth = 0;
    for (; depth < line_.length(); ++depth)
        if (line_[depth] != '[')
            break;

    sname = line_.substr(depth, line_.length() - 2 * depth);
}

inline void Parser::parse(Level& l) {
    while (std::getline(*f_, line_)) {
        ++ln_;
        if (line_[0] == '#' || line_[0] == ';')
            continue;
        line_ = trim(line_);
        if (line_.empty())
            continue;
        if (line_[0] == '[') {
            size_t depth;
            std::string sname;
            parseSLine(sname, depth);
            Level* lp = NULL;
            Level* parent = &l;
            if (depth > l.depth + 1)
                err("section with wrong depth");
            if (l.depth == depth - 1)
                lp = &l.sections[sname];
            else {
                lp = l.parent;
                size_t n = l.depth - depth;
                for (size_t i = 0; i < n; ++i)
                    lp = lp->parent;
                parent = lp;
                lp = &lp->sections[sname];
            }
            if (lp->depth != 0)
                err("duplicate section name on the same level");
            if (!lp->parent) {
                lp->depth = depth;
                lp->parent = parent;
            }
            parent->ordered_sections.push_back(parent->sections.find(sname));
            parse(*lp);
        } else {
            size_t n = line_.find('=');
            if (n == std::string::npos)
                err("no '=' found");
            std::pair<Level::value_map_t::const_iterator, bool> res = l.values.insert(
                std::make_pair(trim(line_.substr(0, n)), trim(line_.substr(n + 1, line_.length() - n - 1))));
            if (!res.second)
                err("duplicated key found");
            l.ordered_values.push_back(res.first);
        }
    }
}

inline void Parser::dump(std::ostream& s, const Level& l, const std::string& sname) {
    if (!sname.empty())
        s << '\n';
    for (size_t i = 0; i < l.depth; ++i)
        s << '[';
    if (!sname.empty())
        s << sname;
    for (size_t i = 0; i < l.depth; ++i)
        s << ']';
    if (!sname.empty())
        s << std::endl;
    for (Level::values_t::const_iterator it = l.ordered_values.begin(); it != l.ordered_values.end(); ++it)
        s << (*it)->first << '=' << (*it)->second << std::endl;
    for (Level::sections_t::const_iterator it = l.ordered_sections.begin(); it != l.ordered_sections.end(); ++it) {
        assert((*it)->second.depth == l.depth + 1);
        dump(s, (*it)->second, (*it)->first);
    }
}
}

#endif // INI_HPP
<|endoftext|>


<commit_before>// This file is part of the dune-pymor project:
//   https://github.com/pyMor/dune-pymor
// Copyright Holders: Felix Albrecht, Stephan Rave
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_PYMOR_FUNCTIONS_DEFAULT_HH
#define DUNE_PYMOR_FUNCTIONS_DEFAULT_HH

#include <dune/stuff/function/interface.hh>

#include <dune/pymor/common/exceptions.hh>
#include <dune/pymor/parameters/base.hh>
#include <dune/pymor/parameters/functional.hh>
#include "interfaces.hh"

namespace Dune {
namespace Pymor {
namespace Functions {

template< class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDimRows, int rangeDimCols >
class ParametricDefault
  : public ParametricFunctionInterface< DomainFieldImp, domainDim, RangeFieldImp, rangeDimRows, rangeDimCols >
{
  typedef ParametricFunctionInterface< DomainFieldImp, domainDim, RangeFieldImp, rangeDimRows, rangeDimCols > BaseType;
public:
  typedef Dune::Stuff::FunctionInterface< DomainFieldImp, domainDim,
                                          RangeFieldImp, rangeDimRows, rangeDimCols > NonparametricType;
  typedef typename BaseType::DomainType DomainType;
  typedef typename BaseType::RangeType  RangeType;

  ParametricDefault(const NonparametricType* nonparametric)
    : BaseType()
    , nonparametric_(nonparametric)
  {}

  ~ParametricDefault()
  {
    delete nonparametric_;
  }

  int order() const
  {
    return nonparametric_->order();
  }

  virtual evaluate(const DomainType& x, RangeType& ret, const Parameter mu = Parameter()) const
  {
    if (mu.type() != Parametric::parameter_type())
      DUNE_PYMOR_THROW(Exception::wrong_parameter_type,
                       "the type of mu must be trivial (is " << mu.type() << ")!");
    nonparametric_->evaluate(x, ret);
  }

  using BaseType::evaluate;

private:
  const NonparametricType* nonparametric_;
}; // class ParametricDefault

template< class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDimRows, int rangeDimCols >
class AffineParametricDefault
  : public AffineParametricFunctionInterface< DomainFieldImp, domainDim, RangeFieldImp, rangeDimRows, rangeDimCols >
{
  typedef AffineParametricFunctionInterface<  DomainFieldImp, domainDim,
                                              RangeFieldImp, rangeDimRows, rangeDimCols > BaseType;
public:
  typedef ParametricFunctionInterface<  DomainFieldImp, domainDim,
                                        RangeFieldImp, rangeDimRows, rangeDimCols > ParametricFunctionType;
  typedef typename BaseType::DomainType DomainType;
  typedef typename BaseType::RangeType  RangeType;

  AffineParametricDefault(const ParameterType mu = ParameterType())
    : Parametric(mu)
  {}

  virtual ~AffineParametricDefault()
  {
    if (hasAffinePart_)
      delete affinePart_;
    for (auto& element : components_)
      delete element;
    for (auto& element : coefficients_)
      delete element;
  }

  static const std::string static_id()
  {
    return BaseType::static_id() + ".default";
  }

  virtual std::string id() const
  {
    return static_id();
  }

  /**
   * \attention This class takes ownership of aff!
   */
  virtual void register_component(ParametricFunctionType* aff) throw (Exception::this_does_not_make_any_sense,
                                                                      Exception::sizes_do_not_match,
                                                                      Exception::types_are_not_compatible)
  {
    if (hasAffinePart_)
      DUNE_PYMOR_THROW(Exception::this_does_not_make_any_sense,
                       "do not call register_component(affinePart) if hasAffinePart() == true!");
    if (aff->parametric())
      DUNE_PYMOR_THROW(Exception::this_does_not_make_any_sense,
                       "the affinePart must not be parametric!");
    if (size_ == 0) {
      order_ = aff->order();
    } else {
      if (order_ < 0 || aff->order() < 0)
        order_ = -1;
      else
        order_ = std::max(order_, aff->order());
    }
    affinePart_ = aff;
    hasAffinePart_ = true;
  } // ... register_component(...)

  /**
   * \attention This class takes ownership of comp and coeff!
   */
  virtual void register_component(ParametricFunctionType* comp, const ParameterFunctional* coeff)
  {
    if (comp->parametric())
      DUNE_PYMOR_THROW(Exception::this_does_not_make_any_sense,
                       "a component must not be parametric!");
    if (size_ == 0 && !hasAffinePart_) {
      order_ = comp->order();
    } else {
      if (order_ < 0 || comp->order() < 0)
        order_ = -1;
      else
        order_ = std::max(order_, comp->order());
    }
    if (coeff->parameter_type() != Parametric::parameter_type())
      DUNE_PYMOR_THROW(Exception::wrong_parameter_type,
                       "different parameter types for coeff (" << coeff->parameter_type() << ") and this ("
                       << Parametric::parameter_type() << ") is not yet supported!");
    components_.push_back(comp);
    coefficients_.push_back(coeff);
    ++size_;
  } // ... register_component(..., ...)

  virtual unsigned int size() const
  {
    return size_;
  }

  /**
   * \attention The ownership of the component remains with this class!
   */
  virtual const ParametricFunctionType* component(const int ii) const throw (Exception::requirements_not_met,
                                                                             Exception::index_out_of_range)
  {
    if (size() == 0)
      DUNE_PYMOR_THROW(Exception::requirements_not_met,
                       "do not call component(ii) if size() == 0!");
    if (ii < 0 || ii >= size())
      DUNE_PYMOR_THROW(Exception::index_out_of_range,
                       "the condition 0 < ii < size() is not fulfilled for ii = " << ii << "and size() = "
                       << size() << "!");
    return components_[ii];
  }

  /**
   * \attention The ownership of the coefficient remains with this class!
   */
  virtual const ParameterFunctional* coefficient(const int ii) const throw (Exception::requirements_not_met,
                                                                            Exception::index_out_of_range)
  {
    if (size() == 0)
      DUNE_PYMOR_THROW(Exception::requirements_not_met,
                       "do not call coefficient(ii) if size() == 0!");
    if (ii < 0 || ii >= size())
      DUNE_PYMOR_THROW(Exception::index_out_of_range,
                       "the condition 0 < ii < size() is not fulfilled for ii = " << ii << "and size() = "
                       << size() << "!");
    return coefficients_[ii];

  }

  virtual bool hasAffinePart() const
  {
    return hasAffinePart_;
  }

  /**
   * \attention The ownership of affinePart() remains in this class!
   */
  virtual const ParametricFunctionType* affinePart() const throw(Exception::requirements_not_met)
  {
    if (!hasAffinePart())
      DUNE_PYMOR_THROW(Exception::requirements_not_met,
                       "do not call affinePart() if hasAffinePart() == false!");
    return affinePart_;
  }

  virtual evaluate(const DomainType& /*x*/, RangeType& /*ret*/, const Parameter /*mu*/ = Parameter()) const
  {
    DUNE_PYMOR_THROW(Exception::you_have_to_implement_this, "Felix!");
  }

public:
  size_t size_;
  bool hasAffinePart_;
  int order_;
  std::vector< const ParametricFunctionType* > components_;
  std::vector< const ParameterFunctional* > coefficients_;
  ParameterFunctional* affinePart_;
}; // class AffineParametricDefault

} // namespace Functions
} // namespace Pymor
} // namespace Dune

#endif // DUNE_PYMOR_FUNCTIONS_DEFAULT_HH
<commit_msg>[functions.default] renamed ParametricDefault -> NonparametricWrapper<commit_after>// This file is part of the dune-pymor project:
//   https://github.com/pyMor/dune-pymor
// Copyright Holders: Felix Albrecht, Stephan Rave
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_PYMOR_FUNCTIONS_DEFAULT_HH
#define DUNE_PYMOR_FUNCTIONS_DEFAULT_HH

#include <dune/stuff/function/interface.hh>

#include <dune/pymor/common/exceptions.hh>
#include <dune/pymor/parameters/base.hh>
#include <dune/pymor/parameters/functional.hh>
#include "interfaces.hh"

namespace Dune {
namespace Pymor {
namespace Functions {

template< class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDimRows, int rangeDimCols = 1 >
class NonparametricWrapper
  : public ParametricFunctionInterface< DomainFieldImp, domainDim, RangeFieldImp, rangeDimRows, rangeDimCols >
{
  typedef ParametricFunctionInterface< DomainFieldImp, domainDim, RangeFieldImp, rangeDimRows, rangeDimCols > BaseType;
public:
  typedef Dune::Stuff::FunctionInterface< DomainFieldImp, domainDim,
                                          RangeFieldImp, rangeDimRows, rangeDimCols > NonparametricType;
  typedef typename BaseType::DomainType DomainType;
  typedef typename BaseType::RangeType  RangeType;

  NonparametricWrapper(const NonparametricType* nonparametric)
    : BaseType()
    , nonparametric_(nonparametric)
  {}

  ~NonparametricWrapper()
  {
    delete nonparametric_;
  }

  int order() const
  {
    return nonparametric_->order();
  }

  virtual evaluate(const DomainType& x, RangeType& ret, const Parameter mu = Parameter()) const
  {
    if (mu.type() != Parametric::parameter_type())
      DUNE_PYMOR_THROW(Exception::wrong_parameter_type,
                       "the type of mu must be trivial (is " << mu.type() << ")!");
    nonparametric_->evaluate(x, ret);
  }

  using BaseType::evaluate;

private:
  const NonparametricType* nonparametric_;
}; // class NonparametricWrapper

template< class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDimRows, int rangeDimCols >
class AffineParametricDefault
  : public AffineParametricFunctionInterface< DomainFieldImp, domainDim, RangeFieldImp, rangeDimRows, rangeDimCols >
{
  typedef AffineParametricFunctionInterface<  DomainFieldImp, domainDim,
                                              RangeFieldImp, rangeDimRows, rangeDimCols > BaseType;
public:
  typedef ParametricFunctionInterface<  DomainFieldImp, domainDim,
                                        RangeFieldImp, rangeDimRows, rangeDimCols > ParametricFunctionType;
  typedef typename BaseType::DomainType DomainType;
  typedef typename BaseType::RangeType  RangeType;

  AffineParametricDefault(const ParameterType mu = ParameterType())
    : Parametric(mu)
  {}

  virtual ~AffineParametricDefault()
  {
    if (hasAffinePart_)
      delete affinePart_;
    for (auto& element : components_)
      delete element;
    for (auto& element : coefficients_)
      delete element;
  }

  static const std::string static_id()
  {
    return BaseType::static_id() + ".default";
  }

  virtual std::string id() const
  {
    return static_id();
  }

  /**
   * \attention This class takes ownership of aff!
   */
  virtual void register_component(ParametricFunctionType* aff) throw (Exception::this_does_not_make_any_sense,
                                                                      Exception::sizes_do_not_match,
                                                                      Exception::types_are_not_compatible)
  {
    if (hasAffinePart_)
      DUNE_PYMOR_THROW(Exception::this_does_not_make_any_sense,
                       "do not call register_component(affinePart) if hasAffinePart() == true!");
    if (aff->parametric())
      DUNE_PYMOR_THROW(Exception::this_does_not_make_any_sense,
                       "the affinePart must not be parametric!");
    if (size_ == 0) {
      order_ = aff->order();
    } else {
      if (order_ < 0 || aff->order() < 0)
        order_ = -1;
      else
        order_ = std::max(order_, aff->order());
    }
    affinePart_ = aff;
    hasAffinePart_ = true;
  } // ... register_component(...)

  /**
   * \attention This class takes ownership of comp and coeff!
   */
  virtual void register_component(ParametricFunctionType* comp, const ParameterFunctional* coeff)
  {
    if (comp->parametric())
      DUNE_PYMOR_THROW(Exception::this_does_not_make_any_sense,
                       "a component must not be parametric!");
    if (size_ == 0 && !hasAffinePart_) {
      order_ = comp->order();
    } else {
      if (order_ < 0 || comp->order() < 0)
        order_ = -1;
      else
        order_ = std::max(order_, comp->order());
    }
    if (coeff->parameter_type() != Parametric::parameter_type())
      DUNE_PYMOR_THROW(Exception::wrong_parameter_type,
                       "different parameter types for coeff (" << coeff->parameter_type() << ") and this ("
                       << Parametric::parameter_type() << ") is not yet supported!");
    components_.push_back(comp);
    coefficients_.push_back(coeff);
    ++size_;
  } // ... register_component(..., ...)

  virtual unsigned int size() const
  {
    return size_;
  }

  /**
   * \attention The ownership of the component remains with this class!
   */
  virtual const ParametricFunctionType* component(const int ii) const throw (Exception::requirements_not_met,
                                                                             Exception::index_out_of_range)
  {
    if (size() == 0)
      DUNE_PYMOR_THROW(Exception::requirements_not_met,
                       "do not call component(ii) if size() == 0!");
    if (ii < 0 || ii >= size())
      DUNE_PYMOR_THROW(Exception::index_out_of_range,
                       "the condition 0 < ii < size() is not fulfilled for ii = " << ii << "and size() = "
                       << size() << "!");
    return components_[ii];
  }

  /**
   * \attention The ownership of the coefficient remains with this class!
   */
  virtual const ParameterFunctional* coefficient(const int ii) const throw (Exception::requirements_not_met,
                                                                            Exception::index_out_of_range)
  {
    if (size() == 0)
      DUNE_PYMOR_THROW(Exception::requirements_not_met,
                       "do not call coefficient(ii) if size() == 0!");
    if (ii < 0 || ii >= size())
      DUNE_PYMOR_THROW(Exception::index_out_of_range,
                       "the condition 0 < ii < size() is not fulfilled for ii = " << ii << "and size() = "
                       << size() << "!");
    return coefficients_[ii];

  }

  virtual bool hasAffinePart() const
  {
    return hasAffinePart_;
  }

  /**
   * \attention The ownership of affinePart() remains in this class!
   */
  virtual const ParametricFunctionType* affinePart() const throw(Exception::requirements_not_met)
  {
    if (!hasAffinePart())
      DUNE_PYMOR_THROW(Exception::requirements_not_met,
                       "do not call affinePart() if hasAffinePart() == false!");
    return affinePart_;
  }

  virtual evaluate(const DomainType& /*x*/, RangeType& /*ret*/, const Parameter /*mu*/ = Parameter()) const
  {
    DUNE_PYMOR_THROW(Exception::you_have_to_implement_this, "Felix!");
  }

public:
  size_t size_;
  bool hasAffinePart_;
  int order_;
  std::vector< const ParametricFunctionType* > components_;
  std::vector< const ParameterFunctional* > coefficients_;
  ParameterFunctional* affinePart_;
}; // class AffineParametricDefault

} // namespace Functions
} // namespace Pymor
} // namespace Dune

#endif // DUNE_PYMOR_FUNCTIONS_DEFAULT_HH
<|endoftext|>