예제 #1
0
int
ConfigurationParserTest::checkDoublesChoice( const ConfigurationChoice *doublesChoice ){
  int retval = 0;
  
  const ConfigurationValue *doublesValue = 0;
  const VectorConfigurationValue *doublesVectorValue = 0;
  const vector<const ConfigurationValue *> *values = 0;

  CHECK( doublesChoice != 0 );
    
  doublesValue = doublesChoice->getConfigurationValue();
  CHECK( doublesValue != 0 );

  doublesVectorValue = dynamic_cast<const VectorConfigurationValue *>(doublesValue);
  CHECK( doublesVectorValue != 0 );

  values = doublesVectorValue->getVectorValue();
  CHECK( values != 0 );
  CHECK( values->size() == 2 );

  CHECK( closeEnough( (*values)[0]->getDoubleValue(), 2.71 ) );
  CHECK( closeEnough( (*values)[1]->getDoubleValue(), -2.17 ) );

 end:
  return retval;
}
예제 #2
0
bool ConicalViewFrustum::isVerySimilar(const ConicalViewFrustum& other) const {
    const float MIN_POSITION_SLOP_SQUARED = 25.0f; // 5 meters squared
    const float MIN_ANGLE_BETWEEN = 0.174533f; // radian angle between 2 vectors 10 degrees apart
    const float MIN_RELATIVE_ERROR = 0.01f; // 1%

    return glm::distance2(_position, other._position) < MIN_POSITION_SLOP_SQUARED &&
            angleBetween(_direction, other._direction) < MIN_ANGLE_BETWEEN &&
            closeEnough(_angle, other._angle, MIN_RELATIVE_ERROR) &&
            closeEnough(_farClip, other._farClip, MIN_RELATIVE_ERROR) &&
            closeEnough(_radius, other._radius, MIN_RELATIVE_ERROR);
}
void OrientationMath::MatToEuler(float g[3][3], float &phi1, float &Phi, float &phi2)
{
  if(closeEnough(g[2][2], 1.0) || closeEnough(g[2][2], -1.0))
  {
    phi1 = atan(g[0][1]/g[0][0]) / 2.0f;
    Phi = 0.0;
    phi2 = phi1;
  } else {
    Phi = acos(g[2][2]);
    double s = sin(Phi);
    phi1 = atan2(g[2][0] / s, -g[2][1] / s );
    phi2 = atan2(g[0][2] / s, g[1][2] / s );
  }
}
void paralellWall()
{
  int rearSensor = SensorValue[S4] -2;
  bool aligned = false;
  while (!aligned)
  {
    rearSensor = SensorValue[S4] -2;
  nxtDisplayTextLine(3, "s4: %d s3:%d", rearSensor, SensorValue[S3]);
  if (closeEnough(rearSensor, SensorValue[S3]))
  {
    //Already close enough, we're done.
    aligned = true;
  }
  else if (SensorValue[S3] > rearSensor)
  {
    //Front of robot is futher from the wall then back, small turn.
    turnTime(25, "left", 150);
    wait1Msec(100);
  }
  else if (SensorValue[S3] < rearSensor)
  {
    //Back of robot is further, small turn.
    turnTime(25, "right", 150);
    wait1Msec(100);
  }
  else
  {
    //Odd situation, no matches of the case list. Exit.;
    aligned = true;
  }
  //next part, moving walk.
  }

}
예제 #5
0
파일: TDB2.cpp 프로젝트: austinwagner/task
////////////////////////////////////////////////////////////////////////////////
// Locate task by uuid, which may be a partial UUID.
bool TF2::get (const std::string& uuid, Task& task)
{
  if (! _loaded_tasks)
    load_tasks ();

  if (_tasks_map.size () > 0 && uuid.size () == 36)
  {
    // Fast lookup, same result as below. Only used during "task import".
    auto i = _tasks_map.find (uuid);
    if (i != _tasks_map.end ())
    {
      task = i->second;
      return true;
    }
  }
  else
  {
    // Slow lookup, same result as above.
    for (auto& i : _tasks)
    {
      if (closeEnough (i.get ("uuid"), uuid, uuid.length ()))
      {
        task = i;
        return true;
      }
    }
  }

  return false;
}
예제 #6
0
int Origami::getClosestVertexAlongDirection(dvec2 pt, double angle) const
{
	dvec2 o = pt;
	dvec2 dir = dvec2(cos(angle), sin(angle));

	double bestT = 4;
	int ret = -1;
	for (size_t i = 0; i < verts.size(); ++i)
	{
		vertex v = verts[i];

		dvec2 VrelO = v.pt - o;
		double t = dot(VrelO, dir);
		dvec2 closestOnLine = o + dir * t;

		if (t < epsilon)
			continue;

		if (closeEnough(closestOnLine, v.pt))
		{
			if (bestT > t)
			{
				bestT = t;
				ret = i;
			}
		}
	}

	return ret;
}
예제 #7
0
int Origami::getClosestVertexAlongDirection(dvec2 pt, double angle, vector<int>& path) const
{
	dvec2 o = pt;
	dvec2 dir = dvec2(cos(angle), sin(angle));

	double bestT = 4;
	int ret = -1;
	for (size_t i = 0; i < path.size(); ++i)
	{
		vertex v = verts[path[i]];

		dvec2 VrelO = v.pt - o;
		double t = dot(VrelO, dir);
		dvec2 closestOnLine = o + dir * t;

		if (t < epsilon)
			continue;

		if (closeEnough(closestOnLine, v.pt))
		{
			if (bestT > t)
			{
				bestT = t;
				ret = i;
			}
		}
	}

	//ASSERT(false, "getClosestVertexAlongDirection didn't return anything");
	return ret;
}
예제 #8
0
void TestStatistics::testAll()
{
  std::vector<double> data;
  data.push_back(20.48);
  data.push_back(20.32);
  data.push_back(20.57);
  data.push_back(19.73);

  _test( closeEnough(Statistics::sum(data), 81.1, 0.0001));

  _test( closeEnough(Statistics::average(data), 20.275, 0.0001));

  _test( closeEnough(Statistics::sumOfSquares(data,20.275), 0.4281, 0.0001));

  std::cout << Statistics::sumOfSquares(data, 20.275) << std::endl;
  _test( closeEnough(Statistics::variance(data), 0.1427, 0.0001));

}
예제 #9
0
AtomList AtomList::neighborhood(Atomo *a)
{
    AtomList al = AtomList();
    for (int i = 0; i < _size; i++) {
	Atomo *b = &contents[i];
	if (closeEnough(a, b))
	    al.add(*b);
    }
    return al;
}
예제 #10
0
void Camera::updatePosition(const glm::vec3 &direction, float elapsedTimeSec)
{
    // Moves the camera using Newton's second law of motion. Unit mass is
    // assumed here to somewhat simplify the calculations. The direction vector
    // is in the range [-1,1].


	float length2 = glm::dot( m_currentVelocity,m_currentVelocity );
    if ( length2 < 1e-10 )
    {
        // Only move the camera if the velocity vector is not of zero length.
        // Doing this guards against the camera slowly creeping around due to
        // floating point rounding errors.

        glm::vec3 displacement = (m_currentVelocity * elapsedTimeSec) + (0.5f * m_acceleration * elapsedTimeSec * elapsedTimeSec);

        // Floating point rounding errors will slowly accumulate and cause the
        // camera to move along each axis. To prevent any unintended movement
        // the displacement vector is clamped to zero for each direction that
        // the camera isn't moving in. Note that the updateVelocity() method
        // will slowly decelerate the camera's velocity back to a stationary
        // state when the camera is no longer moving along that direction. To
        // account for this the camera's current velocity is also checked.

        if (direction.x == 0.0f && closeEnough(m_currentVelocity.x, 0.0f))
            displacement.x = 0.0f;

        if (direction.y == 0.0f && closeEnough(m_currentVelocity.y, 0.0f))
            displacement.y = 0.0f;

        if (direction.z == 0.0f && closeEnough(m_currentVelocity.z, 0.0f))
            displacement.z = 0.0f;

        move( displacement.x, displacement.y, displacement.z );
    }

    // Continuously update the camera's velocity vector even if the camera
    // hasn't moved during this call. When the camera is no longer being moved
    // the camera is decelerating back to its stationary state.

    updateVelocity(direction, elapsedTimeSec);
}
예제 #11
0
std::array<float,3> eulerAngles(const double4x4& R) {
    //check for gimbal lock
    if (closeEnough(R[2][0], -1.0f) || closeEnough(R[2][0], 1.0f)) {
        float x, y;
        float z = 0;

        if (closeEnough(R[2][0], -1.0f)) {
            float d = atan2(R[0][1], R[0][2]);
            y = M_PI/2;
            x = d;
        } else {
            float d = atan2(-R[0][1], -R[0][2]);
            y = -M_PI/2;
            x = d;
        }

        return { x, y, z };
    } else { //two solutions exist
        float y1 = -asin(R[2][0]);
        float y2 = M_PI - y1;

        float x1 = atan2(R[2][1] / cos(y1), R[2][2] / cos(y1));
        float x2 = atan2(R[2][1] / cos(y2), R[2][2] / cos(y2));

        float z1 = atan2(R[1][0] / cos(y1), R[0][0] / cos(y1));
        float z2 = atan2(R[1][0] / cos(y2), R[0][0] / cos(y2));

        //choose one solution to return
        //for example the "shortest" rotation
        if ((fabs(x1) + fabs(y1) + fabs(z1)) <= (fabs(x2) + fabs(y2) + fabs(z2))) {
            return { x1, y1, z1 };
        } else {
            return { x2, y2, z2 };
        }
    }
}
    std::string TransformMatrix::toString()
    {
        std::stringstream str;

        for (int x=0; x<4; x++) {
            for (int y=0; y<4; y++) {
                if (closeEnough(values[x][y], 0.0f)) {
                    str << "0 ";
                } else {
                    str << values[x][y] << " ";
                }
            }
            str << std::endl;
        }

        return str.str();
    }
 double getDistortionScaleForRadius(double rTarget) {
   double max = rTarget * 2;
   double min = 0;
   double distortionScale;
   while (true) {
     double rSource = ((max - min) / 2.0) + min;
     distortionScale = getUndistortionScaleForRadiusSquared(rSource * rSource);
     double rResult = distortionScale * rSource;
     if (closeEnough(rResult, rTarget)) {
       break;
     }
     if (rResult < rTarget) {
       min = rSource;
     } else {
       max = rSource;
     }
   }
   return 1.0 / distortionScale;
 }
예제 #14
0
void FrogShip::update(double deltaTime, PlayerShip* player, vector<Bullet*>& liveBullets) {
	
	GameObject::updateDebug(deltaTime);
	timeAlive += deltaTime;

	double percent = timeAlive / TIME_TO_CLIMAX;
	percent = 1 - cos(percent*XM_PIDIV2);
	double rt = 1 - percent;
	position = camera.screenToWorld(float(rt*rt)*startPos + 2 * float(rt*percent)*controlPoint
		+ float(percent*percent)*climaxPos);

	if (percent > .25) {
		// start aiming at player
		Vector2 dirToPlayer = player->getCenter() - position;
		dirToPlayer.Normalize();

		float angleToPlayer = atan2(dirToPlayer.y, dirToPlayer.x) + XM_PIDIV2;
		dirToPlayer = Vector2(cos(angleToPlayer), sin(angleToPlayer));
		//dirToPlayer += Vector2(cos(XM_PIDIV2), sin(XM_PIDIV2));
		Vector2 currentRot(cos(rotation), sin(rotation));

		currentRot += (dirToPlayer - currentRot) * float(deltaTime * rotationSpeed);
		setRotation(atan2(currentRot.y, currentRot.x));


		if (timeAlive >= TIME_TO_FIRE && closeEnough(dirToPlayer, currentRot)) {
			for (auto const& weapon : weaponSystems) {
				weapon->timeSinceFired += deltaTime;
				weapon->updatePosition(position);
				if (weapon->ready()) {
					weapon->fired = true;
					Bullet* bullet = weapon->launchBullet(player->getCenter());
					liveBullets.push_back(bullet);
				}
			}
		}
	}

	if (position.y > camera.screenToWorld(Vector2(0, float(camera.viewportHeight + 120))).y) {
		reset();
	}
}
예제 #15
0
int UpdateBoard () {
  if (clients.size() > 0) {
    Client *it = NULL;
    for (int i=0;i<clients.size();i++) {
      if (clients[i]->it) {
	it = clients[i];
	break;
      }
    }
    assert(it);
    for (int i=0;i<clients.size();i++) {
      if (clients[i] != it && closeEnough(clients[i], it)) {
	clients[i]->it = true;
	it->it = false;
	teleport(clients[i]);
	return 0;
      }
    }
  }
  return 0;
}
예제 #16
0
int CmdColor::execute (std::string& output)
{
  int rc = 0;

#ifdef FEATURE_COLOR
  // Get the non-attribute, non-fancy command line arguments.
  bool legend = false;
  std::vector <std::string> words = context.a3.extract_words ();
  std::vector <std::string>::iterator word;
  for (word = words.begin (); word != words.end (); ++word)
    if (closeEnough ("legend", *word))
      legend = true;

  std::stringstream out;
  if (context.color ())
  {
    // If the description contains 'legend', show all the colors currently in
    // use.
    if (legend)
    {
      out << "\n" << STRING_CMD_COLOR_HERE << "\n";

      ViewText view;
      view.width (context.getWidth ());
      view.add (Column::factory ("string", STRING_CMD_COLOR_COLOR));
      view.add (Column::factory ("string", STRING_CMD_COLOR_DEFINITION));

      Config::const_iterator item;
      for (item = context.config.begin (); item != context.config.end (); ++item)
      {
        // Skip items with 'color' in their name, that are not referring to
        // actual colors.
        if (item->first != "_forcecolor" &&
            item->first != "color"       &&
            item->first.find ("color") == 0)
        {
          Color color (context.config.get (item->first));
          int row = view.addRow ();
          view.set (row, 0, item->first, color);
          view.set (row, 1, item->second, color);
        }
      }

      out << view.render ()
          << "\n";
    }

    // If there is something in the description, then assume that is a color,
    // and display it as a sample.
    else if (words.size ())
    {
      Color one    ("black on bright yellow");
      Color two    ("underline cyan on bright blue");
      Color three  ("color214 on color202");
      Color four   ("rgb150 on rgb020");
      Color five   ("underline grey10 on grey3");
      Color six    ("red on color173");

      std::string swatch;
      for (word = words.begin (); word != words.end (); ++word)
      {
        if (word != words.begin ())
          swatch += " ";

        swatch += *word;
      }

      Color sample (swatch);

      out << "\n"
          << STRING_CMD_COLOR_EXPLANATION                                          << "\n"
          << "\n\n"
          << STRING_CMD_COLOR_16                                                   << "\n"
          << "  " << one.colorize ("task color black on bright yellow")            << "\n"
          << "  " << two.colorize ("task color underline cyan on bright blue")     << "\n"
          << "\n"
          << STRING_CMD_COLOR_256                                                  << "\n"
          << "  " << three.colorize ("task color color214 on color202")            << "\n"
          << "  " << four.colorize ("task color rgb150 on rgb020")                 << "\n"
          << "  " << five.colorize ("task color underline grey10 on grey3")        << "\n"
          << "  " << six.colorize ("task color red on color173")                   << "\n"
          << "\n"
          << STRING_CMD_COLOR_YOURS                                                << "\n\n"
          << "  " << sample.colorize ("task color " + swatch)                      << "\n\n";
    }

    // Show all supported colors.  Possibly show some unsupported ones too.
    else
    {
      out << "\n"
          << STRING_CMD_COLOR_BASIC
          << "\n"
          << " " << Color::colorize (" black ",   "black")
          << " " << Color::colorize (" red ",     "red")
          << " " << Color::colorize (" blue ",    "blue")
          << " " << Color::colorize (" green ",   "green")
          << " " << Color::colorize (" magenta ", "magenta")
          << " " << Color::colorize (" cyan ",    "cyan")
          << " " << Color::colorize (" yellow ",  "yellow")
          << " " << Color::colorize (" white ",   "white")
          << "\n"
          << " " << Color::colorize (" black ",   "white on black")
          << " " << Color::colorize (" red ",     "white on red")
          << " " << Color::colorize (" blue ",    "white on blue")
          << " " << Color::colorize (" green ",   "black on green")
          << " " << Color::colorize (" magenta ", "black on magenta")
          << " " << Color::colorize (" cyan ",    "black on cyan")
          << " " << Color::colorize (" yellow ",  "black on yellow")
          << " " << Color::colorize (" white ",   "black on white")
          << "\n\n";

      out << STRING_CMD_COLOR_EFFECTS
          << "\n"
          << " " << Color::colorize (" red ",               "red")
          << " " << Color::colorize (" bold red ",          "bold red")
          << " " << Color::colorize (" underline on blue ", "underline on blue")
          << " " << Color::colorize (" on green ",          "black on green")
          << " " << Color::colorize (" on bright green ",   "black on bright green")
          << " " << Color::colorize (" inverse ",           "inverse")
          << "\n\n";

      // 16 system colors.
      out << "color0 - color15"
          << "\n"
          << "  0 1 2 . . .\n";
      for (int r = 0; r < 2; ++r)
      {
        out << "  ";
        for (int c = 0; c < 8; ++c)
        {
          std::stringstream s;
          s << "on color" << (r*8 + c);
          out << Color::colorize ("  ", s.str ());
        }

        out << "\n";
      }

      out << "          . . . 15\n\n";

      // Color cube.
      out << STRING_CMD_COLOR_CUBE
          << Color::colorize ("0", "bold red")
          << Color::colorize ("0", "bold green")
          << Color::colorize ("0", "bold blue")
          << " - rgb"
          << Color::colorize ("5", "bold red")
          << Color::colorize ("5", "bold green")
          << Color::colorize ("5", "bold blue")
          << " (also color16 - color231)"
          << "\n"
          << "  " << Color::colorize ("0            "
                                      "1            "
                                      "2            "
                                      "3            "
                                      "4            "
                                      "5", "bold red")
          << "\n"
          << "  " << Color::colorize ("0 1 2 3 4 5  "
                                      "0 1 2 3 4 5  "
                                      "0 1 2 3 4 5  "
                                      "0 1 2 3 4 5  "
                                      "0 1 2 3 4 5  "
                                      "0 1 2 3 4 5", "bold blue")
          << "\n";

      char label [12];
      for (int g = 0; g < 6; ++g)
      {
        sprintf (label, " %d", g);
        out << Color::colorize (label, "bold green");
        for (int r = 0; r < 6; ++r)
        {
          for (int b = 0; b < 6; ++b)
          {
            std::stringstream s;
            s << "on rgb" << r << g << b;
            out << Color::colorize ("  ", s.str ());
          }

          out << " ";
        }

        out << "\n";
      }

      out << "\n";

      // Grey ramp.
      out << STRING_CMD_COLOR_RAMP
          << " gray0 - gray23 (also color232 - color255)\n"
          << "  0 1 2 . . .                             . . . 23\n"
          << "  ";
      for (int g = 0; g < 24; ++g)
      {
        std::stringstream s;
        s << "on gray" << g;
        out << Color::colorize ("  ", s.str ());
      }

      out << "\n\n"
          << format (STRING_CMD_COLOR_TRY, "task color white on red")
          << "\n\n";
    }
  }
  else
  {
    out << STRING_CMD_COLOR_OFF << "\n";
    rc = 1;
  }

  output = out.str ();
#else
  output = "Color not supported.\n";
#endif

  return rc;
}
예제 #17
0
int main (int argc, const char** argv)
{
  int status = 0;

  // Create a vector of args.
  std::vector <std::string> args;
  for (int i = 1; i < argc; ++i)
    args.push_back (argv[i]);

  Config config;
  config.set ("verbose", "1");

  // Some options are hard-coded.
  if (args.size ())
  {
    if (args[0] == "-h" || closeEnough ("--help", args[0], 3))
      command_help (args);

    else if (args[0] == "-v" || closeEnough ("--version", args[0], 3))
    {
      Color bold ("bold");
      std::cout << "\n"
                << bold.colorize (PACKAGE_STRING)
#ifdef HAVE_COMMIT
                << " "
                << COMMIT
#endif
                << " built for "

#if defined (DARWIN)
                << "darwin"
#elif defined (SOLARIS)
                << "solaris"
#elif defined (CYGWIN)
                << "cygwin"
#elif defined (HAIKU)
                << "haiku"
#elif defined (OPENBSD)
                << "openbsd"
#elif defined (FREEBSD)
                << "freebsd"
#elif defined (NETBSD)
                << "netbsd"
#elif defined (LINUX)
                << "linux"
#elif defined (KFREEBSD)
                << "GNU/kFreeBSD"
#elif defined (GNUHURD)
                << "GNU/Hurd"
#else
                << "unknown"
#endif

          << "\n"
          << "Copyright (C) 2010 - 2015 Göteborg Bit Factory."
          << "\n"
          << "\n"
          << "Taskd may be copied only under the terms of the MIT license, "
          << "which may be found in the taskd source kit."
          << "\n"
          << "Documentation for taskd can be found using 'man taskd' or at "
          << "http://taskwarrior.org"
          << "\n"
          << "\n";
    }
    else
    {
      try
      {
        // Some defaults come from the environment.
        char* root_env = getenv ("TASKDDATA");
        if (root_env)
          config.set ("root", root_env);

        // Process all the options.
        std::vector <std::string> positionals;
        std::vector <std::string>::iterator arg;
        for (arg = args.begin (); arg != args.end (); ++arg)
        {
          if (closeEnough ("--data", *arg, 3))
          {
            ++arg;
            if (arg == args.end () || (*arg)[0] == '-')
              throw std::string (STRING_TASKD_DATA);

            config.set ("root", *arg);
          }
          else if (closeEnough ("--quiet",  *arg, 3))  config.set ("verbose",      0);
          else if (closeEnough ("--debug",  *arg, 3))  config.set ("debug",        1);
          else if (closeEnough ("--force",  *arg, 3))  config.set ("confirmation", 0);
          else if (closeEnough ("--daemon", *arg, 3))  config.set ("daemon",       1);
          else if (taskd_applyOverride (config, *arg)) ;
          else                                         positionals.push_back (*arg);
        }

        // A database object interfaces to the data.
        Database db (&config);

        // The highest-level commands are hard-coded:
             if (closeEnough ("init",        args[0], 3)) command_init     (db, positionals);
        else if (closeEnough ("config",      args[0], 3)) command_config   (db, positionals);
        else if (closeEnough ("status",      args[0], 3)) command_status   (db, positionals);
        else if (closeEnough ("help",        args[0], 3)) command_help     (    positionals);
        else if (closeEnough ("diagnostics", args[0], 3)) command_diag     (db, positionals);
        else if (closeEnough ("server",      args[0], 3)) command_server   (db, positionals);
        else if (closeEnough ("add",         args[0], 3)) command_add      (db, positionals);
        else if (closeEnough ("remove",      args[0], 3)) command_remove   (db, positionals);
        else if (closeEnough ("suspend",     args[0], 3)) command_suspend  (db, positionals);
        else if (closeEnough ("resume",      args[0], 3)) command_resume   (db, positionals);
        else if (closeEnough ("client",      args[0], 3)) command_client   (db, positionals);
        else if (closeEnough ("validate",    args[0], 3)) command_validate (db, positionals);
        else
          throw format (STRING_TASKD_BAD_COMMAND, args[0]);
      }

      catch (std::string& error)
      {
        if (error == "usage")
        {
          std::vector <std::string> no_args;
          command_help (no_args);
        }
        else
          std::cout << error << "\n";
        status = -1;
      }

      catch (std::bad_alloc& error)
      {
        std::cerr << "Error: Memory allocation failed: " << error.what () << "\n";
        status = -3;
      }

      catch (...)
      {
        std::cerr << STRING_ERROR_UNKNOWN
                  << "\n";
        status = -2;
      }
    }
  }
  else
    command_help (args);

  return status;
}
예제 #18
0
bool
OutputImageParams::PartialXform::matches(PartialXform const& other) const
{
	return closeEnough(m_11, other.m_11) && closeEnough(m_12, other.m_12)
		&& closeEnough(m_21, other.m_21) && closeEnough(m_22, other.m_22);
}
예제 #19
0
void Mesh::mirrorMesh(vector<int> planar_faces){

	map<int, Face*> mirror_faces;
	vector<Vertex*> mirror_vertices;
	map<int, Face*> updated_faces;
	map<int, int> temp_twins;

	int last_face_id;


	std::set<int> planar_set;
	for(vector<int>::iterator it = planar_faces.begin(); it != planar_faces.end(); it++) planar_set.insert(*it);
	 

	Face* pface = faces[(*planar_faces.begin())];
	ofVec3f o = vList[pface->getA()->getId()]->getPoint(); //get a point on this plane
	ofVec3f n = pface->getFaceNormal();
	double w = -(n.x * o.x) - (n.y * o.y) - (n.z * o.z);
	
	for(
		vector<Vertex*>::iterator it = vList.begin(); it != vList.end(); it++){
		ofVec3f p = (*it)->getPoint();
		double distance = n.x*p.x + n.y*p.y + n.z*p.z + w;
		ofVec3f pos = p + 2*distance * -1*n; //starting from the original the distance in the other direction
		int vid = vList.size()+mirror_vertices.size();

		if(!closeEnough(p, pos)){
			mirror_vertices.push_back(new Vertex(vid, pos.x, pos.y, pos.z));
			temp_twins.insert(pair<int, int> ((*it)->getId(), vid));
			insertTwin((*it)->getId(), vid);
		 }else{
		 	temp_twins.insert(pair<int, int> ((*it)->getId(), (*it)->getId())); //link it to itself
		 }
	}
	vList.insert(vList.end(), mirror_vertices.begin(), mirror_vertices.end());

	//find any additional planar triangles 
	for(map<int, Face*>::iterator it = faces.begin(); it != faces.end(); it++){
		last_face_id = (*it).first;
		Face* x = (*it).second;
		if(planar_set.count(x->getId()) > 0) continue;
		int a = x->getA()->getId();
		int b = x->getB()->getId();
		int c = x->getC()->getId();
		if(temp_twins[a] == a && temp_twins[b] == b && temp_twins[c] == c) planar_set.insert(x->getId());
		 
		
	}

	//remove any triangles that lie on the mirror plane
   	for(map<int, Face*>::iterator it = faces.begin(); it != faces.end(); it++){
   		Face* x = (*it).second;
   		if(planar_set.count(x->getId()) == 0) updated_faces.insert(*it);
   	}

   	faces.clear();
   	faces.insert(updated_faces.begin(), updated_faces.end());

	//now replicate remaining faces with new vertex values
	for(map<int, Face*>::iterator it = faces.begin(); it != faces.end(); it++){
		Face* x = (*it).second;
		int a = x->getA()->getId();
		int b = x->getB()->getId();
		int c = x->getC()->getId();

		x->resetFaceVertexNexts(); //this will make it so that it will look for connections

		int fid = last_face_id + mirror_faces.size() + 1; //okay to have mirror faces size because it will be sequential 
		Face* n_face = new Face(fid, temp_twins[b], temp_twins[a], temp_twins[c]); //flip to make ccw
		mirror_faces.insert(pair<int, Face*> (fid, n_face));
	}

	assert(mirror_faces.size() == faces.size());
	faces.insert(mirror_faces.begin(), mirror_faces.end());
	assert(faces.size() == 2*mirror_faces.size()); //make sure we didn't duplicate any indices
	constructTopology();
}