<commit_before>/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "osparser.h"
#include "projectexplorerconstants.h"
#include "task.h"

#include <utils/hostosinfo.h>

using namespace ProjectExplorer;

OsParser::OsParser() :
    m_hasFatalError(false)
{
    setObjectName(QLatin1String("OsParser"));
}

void OsParser::stdError(const QString &line)
{
    IOutputParser::stdError(line);
}

void OsParser::stdOutput(const QString &line)
{
    if (Utils::HostOsInfo::isWindowsHost()) {
        const QString trimmed = line.trimmed();
        if (trimmed == QLatin1String("The process cannot access the file because it is being used by another process.")) {
            addTask(Task(Task::Error, tr("The process can not access the file because it is being used by another process.\n"
                                         "Please close all running instances of your application before starting a build."),
                         Utils::FileName(), -1, Constants::TASK_CATEGORY_COMPILE));
            m_hasFatalError = true;
        }
    }
    IOutputParser::stdOutput(line);
}

bool OsParser::hasFatalErrors() const
{
    return m_hasFatalError || IOutputParser::hasFatalErrors();
}
<commit_msg>Linux: Warn on build applications failing due to missing libraries<commit_after>/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "osparser.h"
#include "projectexplorerconstants.h"
#include "task.h"

#include <utils/hostosinfo.h>

using namespace ProjectExplorer;

OsParser::OsParser() :
    m_hasFatalError(false)
{
    setObjectName(QLatin1String("OsParser"));
}

void OsParser::stdError(const QString &line)
{
    if (Utils::HostOsInfo::isLinuxHost()) {
        const QString trimmed = line.trimmed();
        if (trimmed.contains(QLatin1String(": error while loading shared libraries:"))) {
            addTask(Task(Task::Error, trimmed, Utils::FileName(), -1, Constants::TASK_CATEGORY_COMPILE));
        }
    }
    IOutputParser::stdError(line);
}

void OsParser::stdOutput(const QString &line)
{
    if (Utils::HostOsInfo::isWindowsHost()) {
        const QString trimmed = line.trimmed();
        if (trimmed == QLatin1String("The process cannot access the file because it is being used by another process.")) {
            addTask(Task(Task::Error, tr("The process can not access the file because it is being used by another process.\n"
                                         "Please close all running instances of your application before starting a build."),
                         Utils::FileName(), -1, Constants::TASK_CATEGORY_COMPILE));
            m_hasFatalError = true;
        }
    }
    IOutputParser::stdOutput(line);
}

bool OsParser::hasFatalErrors() const
{
    return m_hasFatalError || IOutputParser::hasFatalErrors();
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <sstream>
#include <iostream>
#include "lcontrol/control.h"
#include <thread>

using namespace std::literals;
using namespace lcomm;

#define NUM_ITER 20
#define SLEEP_DELAY 20ms

// Define to 1 if you want the frames sent to the drone to be printed on stdout.
#define PRINT_FRAMES 0

namespace lcontrol {

    namespace {
        void printFrame(std::string const& f) {
#if PRINT_FRAMES
            std::cout << f << '\n';
#endif
        }
    }

    std::atomic<std::uint32_t> Control::m_seqNum;
    std::unique_ptr<lcomm::ClientSocket> Control::m_sock;

    std::string Control::float_to_string(float i) {
        return std::to_string(*reinterpret_cast<std::uint32_t const*>(&i));
    }

    void Control::init() {
        m_seqNum = 0;
        m_sock = std::make_unique<ClientSocket>("127.0.0.1", 5556, false);
    }

    void Control::enableStabilization() {
        for(int i = 0; i < NUM_ITER; ++i) {
            Control::horizontalPlan(m_seqNum.fetch_add(1), *m_sock);
            std::this_thread::sleep_for(SLEEP_DELAY);
        }
    }

    void Control::takeoff() {
        for(int i = 0; i < NUM_ITER; ++i) {
            Control::takeoff(m_seqNum.fetch_add(1), *m_sock);
            std::this_thread::sleep_for(SLEEP_DELAY);
        }
    }

    void Control::land() {
        for(int i = 0; i < NUM_ITER; ++i) {
            Control::land(m_seqNum.fetch_add(1), *m_sock);
            std::this_thread::sleep_for(SLEEP_DELAY);
        }
    }

    // Ask the drone to send the navdata :
    // AT*CONFIG="seqNum",\"general:navdata_demo\",\"TRUE\"\r
    void Control::sendNavData(std::uint32_t seqNum, ClientSocket& s) {
        std::string data("AT*CONFIG=");
        std::string seqStr = std::to_string(seqNum);
        data += seqStr + ",\"general:navdata_demo\",\"TRUE\"\r";
        printFrame(data);
        s.write(data);
    }

    // Reset the communication watchdog :
    // AT*COMWDG="seqNum"\r
    void Control::watchdog(std::uint32_t seqNum, ClientSocket& s) {
        std::string data("AT*COMWD=");
        std::string seqStr = std::to_string(seqNum);
        data += seqStr + "\r";
        printFrame(data);
        s.write(data);
    }

    // Emergency mode on the drone :
    // AT*REF="seqNum",290717952\r
    void Control::emergencyMode(std::uint32_t seqNum, ClientSocket& s) {
        std::string data("AT*REF=");
        std::string seqStr = std::to_string(seqNum);
        data += seqStr + ",290717952\r";
        printFrame(data);
        s.write(data);
    }

    // Calibrate the horizontal plan :
    // AT*FTRIM="seqNum"\r
    void Control::horizontalPlan(std::uint32_t seqNum, ClientSocket& s) {
        std::string data("AT*FTRIM=");
        std::string seqStr = std::to_string(seqNum);
        data += seqStr + "\r";
        printFrame(data);
        s.write(data);
    }

    // Calibrate the magnetometer :
    // AT*CALIB="seqNum",0\r
    void Control::magnetometer(std::uint32_t seqNum, ClientSocket& s) {
        std::string data("AT*CALIB=");
        std::string seqStr = std::to_string(seqNum);
        data += seqStr + ",0\r";
        printFrame(data);
        s.write(data);
    }

    // Take off :
    // AT*REF="seqNum",290718208\r
    void Control::takeoff(std::uint32_t seqNum, ClientSocket& s) {
        std::string data("AT*REF=");
        std::string seqStr = std::to_string(seqNum);
        data += seqStr + ",290718208\r";
        printFrame(data);
        s.write(data);
    }

    // Land :
    // AT*REF="seqNum",290717696\r
    void Control::land(std::uint32_t seqNum, ClientSocket& s) {
        std::string data("AT*REF=");
        std::string seqStr = std::to_string(seqNum);
        data += seqStr + ",290717696\r";
        printFrame(data);
        s.write(data);
    }

    // Send a movement to the drone :
    // AT*PCMD="seqNum","flag","leftRightTilt","frontBackTilt","verticalSpeed","angularSpeed",\r
    void Control::movement(std::uint32_t seqNum, int flag, float frontBackTilt, float leftRightTilt, float verticalSpeed, float angularSpeed, ClientSocket& s) {
        std::string data("AT*PCMD=");
        std::string seqStr = std::to_string(seqNum);
        data += seqStr + "," + std::to_string(flag) + "," + Control::float_to_string(leftRightTilt) + "," +
                Control::float_to_string(frontBackTilt) + "," + Control::float_to_string(verticalSpeed) + "," +
                Control::float_to_string(angularSpeed) + ",\r";
        printFrame(data);
        s.write(data);
    }
}
<commit_msg>libcontrol has now a blocking connection initialization<commit_after>#include <iostream>
#include <string>
#include <sstream>
#include <iostream>
#include "lcontrol/control.h"
#include <thread>

using namespace std::literals;
using namespace lcomm;

#define NUM_ITER 20
#define SLEEP_DELAY 20ms

// Define to 1 if you want the frames sent to the drone to be printed on stdout.
#define PRINT_FRAMES 0

namespace lcontrol {

    namespace {
        void printFrame(std::string const& f) {
#if PRINT_FRAMES
            std::cout << f << '\n';
#endif
        }
    }

    std::atomic<std::uint32_t> Control::m_seqNum;
    std::unique_ptr<lcomm::ClientSocket> Control::m_sock;

    std::string Control::float_to_string(float i) {
        return std::to_string(*reinterpret_cast<std::uint32_t const*>(&i));
    }

    void Control::init() {
        m_seqNum = 0;
        m_sock = std::make_unique<ClientSocket>("127.0.0.1", 5556, false);
        int numAttempt = 0;
        while(!m_sock->opened()) {
            std::cout << "Waiting for lcontrol's connection " << numAttempt++ << "..." << std::endl;
            std::this_thread::sleep_for(100ms);
        }
        std::cout << "lcontrol connected!" << std::endl;
    }

    void Control::enableStabilization() {
        for(int i = 0; i < NUM_ITER; ++i) {
            Control::horizontalPlan(m_seqNum.fetch_add(1), *m_sock);
            std::this_thread::sleep_for(SLEEP_DELAY);
        }
    }

    void Control::takeoff() {
        for(int i = 0; i < NUM_ITER; ++i) {
            Control::takeoff(m_seqNum.fetch_add(1), *m_sock);
            std::this_thread::sleep_for(SLEEP_DELAY);
        }
    }

    void Control::land() {
        for(int i = 0; i < NUM_ITER; ++i) {
            Control::land(m_seqNum.fetch_add(1), *m_sock);
            std::this_thread::sleep_for(SLEEP_DELAY);
        }
    }

    // Ask the drone to send the navdata :
    // AT*CONFIG="seqNum",\"general:navdata_demo\",\"TRUE\"\r
    void Control::sendNavData(std::uint32_t seqNum, ClientSocket& s) {
        std::string data("AT*CONFIG=");
        std::string seqStr = std::to_string(seqNum);
        data += seqStr + ",\"general:navdata_demo\",\"TRUE\"\r";
        printFrame(data);
        s.write(data);
    }

    // Reset the communication watchdog :
    // AT*COMWDG="seqNum"\r
    void Control::watchdog(std::uint32_t seqNum, ClientSocket& s) {
        std::string data("AT*COMWD=");
        std::string seqStr = std::to_string(seqNum);
        data += seqStr + "\r";
        printFrame(data);
        s.write(data);
    }

    // Emergency mode on the drone :
    // AT*REF="seqNum",290717952\r
    void Control::emergencyMode(std::uint32_t seqNum, ClientSocket& s) {
        std::string data("AT*REF=");
        std::string seqStr = std::to_string(seqNum);
        data += seqStr + ",290717952\r";
        printFrame(data);
        s.write(data);
    }

    // Calibrate the horizontal plan :
    // AT*FTRIM="seqNum"\r
    void Control::horizontalPlan(std::uint32_t seqNum, ClientSocket& s) {
        std::string data("AT*FTRIM=");
        std::string seqStr = std::to_string(seqNum);
        data += seqStr + "\r";
        printFrame(data);
        s.write(data);
    }

    // Calibrate the magnetometer :
    // AT*CALIB="seqNum",0\r
    void Control::magnetometer(std::uint32_t seqNum, ClientSocket& s) {
        std::string data("AT*CALIB=");
        std::string seqStr = std::to_string(seqNum);
        data += seqStr + ",0\r";
        printFrame(data);
        s.write(data);
    }

    // Take off :
    // AT*REF="seqNum",290718208\r
    void Control::takeoff(std::uint32_t seqNum, ClientSocket& s) {
        std::string data("AT*REF=");
        std::string seqStr = std::to_string(seqNum);
        data += seqStr + ",290718208\r";
        printFrame(data);
        s.write(data);
    }

    // Land :
    // AT*REF="seqNum",290717696\r
    void Control::land(std::uint32_t seqNum, ClientSocket& s) {
        std::string data("AT*REF=");
        std::string seqStr = std::to_string(seqNum);
        data += seqStr + ",290717696\r";
        printFrame(data);
        s.write(data);
    }

    // Send a movement to the drone :
    // AT*PCMD="seqNum","flag","leftRightTilt","frontBackTilt","verticalSpeed","angularSpeed",\r
    void Control::movement(std::uint32_t seqNum, int flag, float frontBackTilt, float leftRightTilt, float verticalSpeed, float angularSpeed, ClientSocket& s) {
        std::string data("AT*PCMD=");
        std::string seqStr = std::to_string(seqNum);
        data += seqStr + "," + std::to_string(flag) + "," + Control::float_to_string(leftRightTilt) + "," +
                Control::float_to_string(frontBackTilt) + "," + Control::float_to_string(verticalSpeed) + "," +
                Control::float_to_string(angularSpeed) + ",\r";
        printFrame(data);
        s.write(data);
    }
}
<|endoftext|>


<commit_before>/*
    Copyright (C) 2000 by Norman Kramer

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "csengine/crysball.h"
#include "csgeom/frustum.h"

int csCrystalBall::csTriNode::Add (const csCrystalBallVec *normal,
	int tri1, int tri2, int tri3, csVector *vP, csVector *vTP)
{
  int nPos = 0;
  if (IsLeaf ())
  {
    // we reached the last level
    // if this leaf is empty just add the polyidx
    // if the new normal to be added equals the one in this leaf we are done
    // otherwise we have to split this leaf
    if (len == 0)
    {
      nPos = vP->Insert (from, (void*)normal);
    }
    else
    {
      csCrystalBallVec *n = (csCrystalBallVec*)vP->Get (from);

      if (*n == *normal)
      {
	// just append this index
	nPos = vP->Insert (from, (void*)normal);
      }
      else
      {
	// split
	// as the splitpoint we just take the middle of old-new (this will
	// ensure, that the old and new point are separated in distinct
	// triangles)
	csVector3 *mc = new csVector3 (*n + (*normal - *n)/2.0f);
	mc->Normalize (); // now the point lies on the unit sphere
	divider = vTP->Push ((void*)mc);

	bool bNew=false, bOld=false;

	// now decide which triangle the old and the new point(s) will go into
	if ((bOld=(Classify (*n, tri1, tri2, divider, vTP) == INSIDE)))
	  // contains the original points
	  AddChild (new csTriNode (this, from, len));
	else
	if ((bNew=(Classify (*normal, tri1, tri2, divider, vTP) == INSIDE)))
	{
	  csTriNode *tnode = new csTriNode (this, from+len, 0);
	  AddChild (tnode); // contains the new point
	  nPos = tnode->Add (normal, tri1, tri2, divider, vP, vTP);
	}
	else
	  AddChild (new csTriNode (this, from+len+1, 0)); // remains empty

	if (!bOld && (bOld=(Classify (*n, tri2, tri3, divider, vTP) == INSIDE)))
	  // contains the original points
	  AddChild (new csTriNode (this, from, len));
	else
	if (!bNew && (bNew=(Classify (*normal, tri2, tri3, divider, vTP)
		== INSIDE)))
	{
	  csTriNode *tnode = new csTriNode (this, from+len, 0);
	  // contains the new point
	  AddChild (new csTriNode (this, from+len, 1));
	  nPos = tnode->Add (normal, tri2, tri3, divider, vP, vTP);
	}
	else
	  AddChild (new csTriNode (this, from+len+1, 0)); // remains empty

	if (!bOld && (bOld=(Classify (*n, tri3, tri1, divider, vTP) == INSIDE)))
	  // contains the original points
	  AddChild (new csTriNode (this, from, len));
	else
	if (!bNew && (bNew=(Classify (*normal, tri3, tri1, divider, vTP)
		== INSIDE)))
	{
	  csTriNode *tnode = new csTriNode (this, from+len, 0);
	  // contains the new point
	  AddChild (new csTriNode (this, from+len, 1));
	  nPos = tnode->Add (normal, tri3, tri1, divider, vP, vTP);
	}
	else
	  AddChild (new csTriNode (this, from+len+1, 0)); // remains empty

      }
    }
  } // IsLeaf ()
  else
  {
    // ok, this is not a leaf, lets check which subtriangle we have to dive into
    if (Classify (*normal, tri1, tri2, divider, vTP) == INSIDE)
      nPos = ((csTriNode*)children.Get (0))->
      	Add (normal, tri1, tri2, divider, vP, vTP);
    else
    if (Classify (*normal, tri2, tri3, divider, vTP) == INSIDE)
      nPos = ((csTriNode*)children.Get (1))->
      	Add (normal, tri2, tri3, divider, vP, vTP);
    else
      nPos = ((csTriNode*)children.Get (2))->
      	Add (normal, tri3, tri1, divider, vP, vTP);
  }
  return nPos;
}

void csCrystalBall::csTriNode::Adjust (int nPos)
{
  bool bDive = true;
  if (from > nPos)
    from++;
  else
  if ((from <= nPos && from+len > nPos) || (from == nPos && len == 0))
    len++;
  else
    bDive = false;

  if (bDive && !IsLeaf())
  {
    ((csTriNode*)children.Get (0))->Adjust (nPos);
    ((csTriNode*)children.Get (1))->Adjust (nPos);
    ((csTriNode*)children.Get (2))->Adjust (nPos);
  }
}

int csCrystalBall::csTriNode::Classify (const csVector3 &n, int i1, int i2,
				      int i3, const csVector *vTP) const
{
  csVector3 origo (0,0,0);

  csFrustum frust (origo);
  frust.AddVertex (*(csVector3*)vTP->Get (i1));
  frust.AddVertex (*(csVector3*)vTP->Get (i2));
  frust.AddVertex (*(csVector3*)vTP->Get (i3));

  return (frust.Contains (n)
  	? csCrystalBall::csTriNode::INSIDE
	: csCrystalBall::csTriNode::OUTSIDE);
}

void csCrystalBall::csTriNode::Transform (
	const csMatrix3 &m, csVector &indexVector,
	int useSign, long cookie,
	const csVector *vP, const csVector *vTP,
	const csVector3 &v1, const csVector3 &v2,
	const csVector3 &v3)
{
  // If the node has no children, we can decide based on the normal
  // assigned to this triangle.
  if (IsLeaf ())
  {
    if (len>0)
    {
      // check the normal directly
      csCrystalBallVec *n = (csCrystalBallVec*)vP->Get (from);
      csVector3 tn = m* (*n);
      if (SignMatches (&tn, useSign))
      {
	// add all polygon indices
	int to = from+len;
	int i;
	for (i=from; i < to; i++)
	  indexVector.Push ((csSome)((csCrystalBallVec*)vP->Get (i))->
	  	GetIndex ());
      }
    }
  }
  else
  {
    const csVector3 *p[4] = {&v1, &v2, &v3, &v1};
    csVector3 td = m* (*(csCrystalBallVec*)vTP->Get (divider));
	int i;
    for (i=0; i < 3; i++)
    {
      const csVector3 &n1 = *p[i];
      const csVector3 &n2 = *p[i+1];
      int match = SignMatches (&n1, &n2, &td, useSign);

      if (match == 0)
      {
	// all in same half of sphere, sp add them all
	csTriNode *tri = (csTriNode*)children.Get (i);
	int to = tri->from+tri->len;
	int j;
	for (j=tri->from; j < to; j++)
	  indexVector.Push ((csSome)((csCrystalBallVec*)vP->Get (j))->
	  	GetIndex ());
      }
      else
      if (match == 1)
      {
	// triangle is on both sides of sphere, so dive into subtriangles
	Transform (m, indexVector, useSign, cookie, vP, vTP, n1, n2, td);
      }
    }
  }
}

bool csCrystalBall::csTriNode::SignMatches (const csVector3 *tn, int useSign)
{
  bool match = false;
  if (useSign < 0)
  {
    if (tn->z <= 0.0)
      match = true;
    else
    if (tn->z >= 0.0)
      match = false;
  }
  else
  {
    if (tn->z >= 0.0)
      match = true;
    else
    if (tn->z <= 0.0)
      match = false;
  }
  return match;
}

int csCrystalBall::csTriNode::SignMatches (
	const csVector3 *n1, const csVector3 *n2,
	const csVector3 *td, int useSign)
{
  int match;
  if (useSign < 0)
  {
    if (n1->z <= 0.0 && n2->z <= 0.0 && td->z <= 0.0)
      match = 0;
    else
    if (n1->z >= 0.0 && n2->z >= 0.0 && td->z >= 0.0)
      match = 2;
    else
      match = 1;
  }
  else
  {
    if (n1->z >= 0.0 && n2->z >= 0.0 && td->z >= 0.0)
      match = 0;
    else
    if (n1->z <= 0.0 && n2->z <= 0.0 && td->z <= 0.0)
      match = 2;
    else
      match = 1;
  }
  return match;
}

csCrystalBall::csCrystalBall ()
{
  // standard axis points from which we'll create the initial 8 triangles
  vTrianglePoints.Push (new csVector3 (1,0,0));
  vTrianglePoints.Push (new csVector3 (0,1,0));
  vTrianglePoints.Push (new csVector3 (0,0,1));
  vTrianglePoints.Push (new csVector3 (-1,0,0));
  vTrianglePoints.Push (new csVector3 (0,-1,0));
  vTrianglePoints.Push (new csVector3 (0,0,-1));
}

csCrystalBall::~csCrystalBall ()
{
  int i;
  for (i=0; i < vTrianglePoints.Length (); i++)
    delete (csVector3*)vTrianglePoints.Get (i);
  for (i=0; i < vPoints.Length (); i++)
    delete (csCrystalBallVec*)vPoints.Get (i);
}

void csCrystalBall::InsertPolygon (iPolygonMesh *polyset, int idx)
{
  csMeshedPolygon &mp = polyset->GetPolygons ()[idx];
  // calc the normal first
  csCrystalBallVec *n = new csCrystalBallVec (idx);
  csMath3::CalcNormal (*n, polyset->GetVertices ()[mp.vertices[0]],
		       polyset->GetVertices ()[mp.vertices[1]],
		       polyset->GetVertices ()[mp.vertices[2]]
		       );
  // which of the 8 starting triangles we add this to ?
  int i1 = 0, i2 = 0, i3 = 0, i = 0;
  if (n->y < 0)
    i += 4;
  if (n->z < 0)
    i += 2;
  if (n->x >= 0)
    i += 1;

  switch (i)
  {
    case 0: i1=3; i2=1; i2=2; break;
    case 1: i1=0; i2=1; i2=2; break;
    case 2: i1=3; i2=1; i2=5; break;
    case 3: i1=0; i2=1; i2=5; break;
    case 4: i1=3; i2=4; i2=2; break;
    case 5: i1=0; i2=4; i2=2; break;
    case 6: i1=3; i2=4; i2=5; break;
    case 7: i1=0; i2=4; i2=5; break;
  }

  int nPos = tri[i].Add (n, i1, i2, i3, &vPoints, &vTrianglePoints);
  for (i=0; i < 7; i++)
    tri[i].Adjust (nPos);
}

void csCrystalBall::Build (iPolygonMesh *polyset)
{
  // just cycle through all polygons and add them
  int i;
  for (i=0; i<polyset->GetPolygonCount (); i++)
    InsertPolygon (polyset, i);
}

void csCrystalBall::Transform (const csTransform &o2c, csVector &indexVector,
			       int useSign, long cookie)
{
  // fill indexVector with the indices to those polygons that have a
  // normal vector with sign(z-coordinate) == <useSign>

  // first check the base triangles
  // for this we simply check the base vectors - luckily the form a unit matrix
  // so we can simply check o2c.

  const csMatrix3 &m = o2c.GetO2T ();
  csVector3 e1 = m.Col1 ();
  csVector3 e2 = m.Col2 ();
  csVector3 e3 = m.Col3 ();
  csVector3 ne1 = -1 * e1;
  csVector3 ne2 = -1 * e2;
  csVector3 ne3 = -1 * e3;

  tri[0].Transform (m, indexVector, useSign, cookie, &vPoints,
  	&vTrianglePoints, ne1,  e2,  e3);
  tri[1].Transform (m, indexVector, useSign, cookie, &vPoints,
  	&vTrianglePoints, e1,  e2,  e3);
  tri[2].Transform (m, indexVector, useSign, cookie, &vPoints,
  	&vTrianglePoints, ne1,  e2, ne3);
  tri[3].Transform (m, indexVector, useSign, cookie, &vPoints,
  	&vTrianglePoints, e1,  e2, ne3);
  tri[4].Transform (m, indexVector, useSign, cookie, &vPoints,
  	&vTrianglePoints, ne1, ne2,  e3);
  tri[5].Transform (m, indexVector, useSign, cookie, &vPoints,
  	&vTrianglePoints, e1, ne2,  e3);
  tri[6].Transform (m, indexVector, useSign, cookie, &vPoints,
  	&vTrianglePoints, ne1, ne2, ne3);
  tri[7].Transform (m, indexVector, useSign, cookie, &vPoints,
  	&vTrianglePoints, e1, ne2, ne3);
}
<commit_msg>Elimated the assignments within conditional expression wanings under MSVC and also cleaned up the code.<commit_after>/*
    Copyright (C) 2000 by Norman Kramer

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "csengine/crysball.h"
#include "csgeom/frustum.h"

int csCrystalBall::csTriNode::Add (const csCrystalBallVec *normal,
	int tri1, int tri2, int tri3, csVector *vP, csVector *vTP)
{
  int nPos = 0;
  if (IsLeaf ())
  {
    // we reached the last level
    // if this leaf is empty just add the polyidx
    // if the new normal to be added equals the one in this leaf we are done
    // otherwise we have to split this leaf
    if (len == 0)
    {
      nPos = vP->Insert (from, (void*)normal);
    }
    else
    {
      csCrystalBallVec *n = (csCrystalBallVec*)vP->Get (from);

      if (*n == *normal)
      {
	// just append this index
	nPos = vP->Insert (from, (void*)normal);
      }
      else
      {
	// split
	// as the splitpoint we just take the middle of old-new (this will
	// ensure, that the old and new point are separated in distinct
	// triangles)
	csVector3 *mc = new csVector3 (*n + (*normal - *n)/2.0f);
	mc->Normalize (); // now the point lies on the unit sphere
	divider = vTP->Push ((void*)mc);

	bool bNew = false, bOld = false;

	// now decide which triangle the old and the new point(s) will go into
  bOld = Classify (*n, tri1, tri2, divider, vTP);
	if (bOld == INSIDE)
  {
	  // contains the original points
	  AddChild (new csTriNode (this, from, len));
  }
	else
  {
    bNew = Classify (*normal, tri1, tri2, divider, vTP);
    if (bNew == INSIDE)
    {
      csTriNode *tnode = new csTriNode (this, from+len, 0);
      AddChild (tnode); // contains the new point
      nPos = tnode->Add (normal, tri1, tri2, divider, vP, vTP);
    }
    else
      AddChild (new csTriNode (this, from+len+1, 0)); // remains empty
  }

  bOld = Classify (*n, tri2, tri3, divider, vTP);
	if (!bOld && bOld == INSIDE)
  {
	  // contains the original points
	  AddChild (new csTriNode (this, from, len));
  }
	else
  {
    bNew = Classify (*normal, tri2, tri3, divider, vTP);
    if (!bNew && bNew == INSIDE)
    {
      csTriNode *tnode = new csTriNode (this, from+len, 0);
      // contains the new point
      AddChild (new csTriNode (this, from+len, 1));
      nPos = tnode->Add (normal, tri2, tri3, divider, vP, vTP);
    }
    else
      AddChild (new csTriNode (this, from+len+1, 0)); // remains empty
  }

  bOld = Classify (*n, tri3, tri1, divider, vTP);
	if (!bOld && bOld == INSIDE)
  {
	  // contains the original points
	  AddChild (new csTriNode (this, from, len));
  }
	else
  {
    bNew = Classify (*normal, tri3, tri1, divider, vTP);
    if (!bNew && bNew== INSIDE)
    {
      csTriNode *tnode = new csTriNode (this, from+len, 0);
      // contains the new point
      AddChild (new csTriNode (this, from+len, 1));
      nPos = tnode->Add (normal, tri3, tri1, divider, vP, vTP);
    }
    else
      AddChild (new csTriNode (this, from+len+1, 0)); // remains empty
  }

      }
    }
  } // IsLeaf ()
  else
  {
    // ok, this is not a leaf, lets check which subtriangle we have to dive into
    if (Classify (*normal, tri1, tri2, divider, vTP) == INSIDE)
      nPos = ((csTriNode*)children.Get (0))->
      	Add (normal, tri1, tri2, divider, vP, vTP);
    else
    if (Classify (*normal, tri2, tri3, divider, vTP) == INSIDE)
      nPos = ((csTriNode*)children.Get (1))->
      	Add (normal, tri2, tri3, divider, vP, vTP);
    else
      nPos = ((csTriNode*)children.Get (2))->
      	Add (normal, tri3, tri1, divider, vP, vTP);
  }
  return nPos;
}

void csCrystalBall::csTriNode::Adjust (int nPos)
{
  bool bDive = true;
  if (from > nPos)
    from++;
  else
  if ((from <= nPos && from+len > nPos) || (from == nPos && len == 0))
    len++;
  else
    bDive = false;

  if (bDive && !IsLeaf())
  {
    ((csTriNode*)children.Get (0))->Adjust (nPos);
    ((csTriNode*)children.Get (1))->Adjust (nPos);
    ((csTriNode*)children.Get (2))->Adjust (nPos);
  }
}

int csCrystalBall::csTriNode::Classify (const csVector3 &n, int i1, int i2,
				      int i3, const csVector *vTP) const
{
  csVector3 origo (0,0,0);

  csFrustum frust (origo);
  frust.AddVertex (*(csVector3*)vTP->Get (i1));
  frust.AddVertex (*(csVector3*)vTP->Get (i2));
  frust.AddVertex (*(csVector3*)vTP->Get (i3));

  return (frust.Contains (n)
  	? csCrystalBall::csTriNode::INSIDE
	: csCrystalBall::csTriNode::OUTSIDE);
}

void csCrystalBall::csTriNode::Transform (
	const csMatrix3 &m, csVector &indexVector,
	int useSign, long cookie,
	const csVector *vP, const csVector *vTP,
	const csVector3 &v1, const csVector3 &v2,
	const csVector3 &v3)
{
  // If the node has no children, we can decide based on the normal
  // assigned to this triangle.
  if (IsLeaf ())
  {
    if (len>0)
    {
      // check the normal directly
      csCrystalBallVec *n = (csCrystalBallVec*)vP->Get (from);
      csVector3 tn = m* (*n);
      if (SignMatches (&tn, useSign))
      {
	// add all polygon indices
	int to = from+len;
	int i;
	for (i=from; i < to; i++)
	  indexVector.Push ((csSome)((csCrystalBallVec*)vP->Get (i))->
	  	GetIndex ());
      }
    }
  }
  else
  {
    const csVector3 *p[4] = {&v1, &v2, &v3, &v1};
    csVector3 td = m* (*(csCrystalBallVec*)vTP->Get (divider));
	int i;
    for (i=0; i < 3; i++)
    {
      const csVector3 &n1 = *p[i];
      const csVector3 &n2 = *p[i+1];
      int match = SignMatches (&n1, &n2, &td, useSign);

      if (match == 0)
      {
	// all in same half of sphere, sp add them all
	csTriNode *tri = (csTriNode*)children.Get (i);
	int to = tri->from+tri->len;
	int j;
	for (j=tri->from; j < to; j++)
	  indexVector.Push ((csSome)((csCrystalBallVec*)vP->Get (j))->
	  	GetIndex ());
      }
      else
      if (match == 1)
      {
	// triangle is on both sides of sphere, so dive into subtriangles
	Transform (m, indexVector, useSign, cookie, vP, vTP, n1, n2, td);
      }
    }
  }
}

bool csCrystalBall::csTriNode::SignMatches (const csVector3 *tn, int useSign)
{
  bool match = false;
  if (useSign < 0)
  {
    if (tn->z <= 0.0)
      match = true;
    else
    if (tn->z >= 0.0)
      match = false;
  }
  else
  {
    if (tn->z >= 0.0)
      match = true;
    else
    if (tn->z <= 0.0)
      match = false;
  }
  return match;
}

int csCrystalBall::csTriNode::SignMatches (
	const csVector3 *n1, const csVector3 *n2,
	const csVector3 *td, int useSign)
{
  int match;
  if (useSign < 0)
  {
    if (n1->z <= 0.0 && n2->z <= 0.0 && td->z <= 0.0)
      match = 0;
    else
    if (n1->z >= 0.0 && n2->z >= 0.0 && td->z >= 0.0)
      match = 2;
    else
      match = 1;
  }
  else
  {
    if (n1->z >= 0.0 && n2->z >= 0.0 && td->z >= 0.0)
      match = 0;
    else
    if (n1->z <= 0.0 && n2->z <= 0.0 && td->z <= 0.0)
      match = 2;
    else
      match = 1;
  }
  return match;
}

csCrystalBall::csCrystalBall ()
{
  // standard axis points from which we'll create the initial 8 triangles
  vTrianglePoints.Push (new csVector3 (1,0,0));
  vTrianglePoints.Push (new csVector3 (0,1,0));
  vTrianglePoints.Push (new csVector3 (0,0,1));
  vTrianglePoints.Push (new csVector3 (-1,0,0));
  vTrianglePoints.Push (new csVector3 (0,-1,0));
  vTrianglePoints.Push (new csVector3 (0,0,-1));
}

csCrystalBall::~csCrystalBall ()
{
  int i;
  for (i=0; i < vTrianglePoints.Length (); i++)
    delete (csVector3*)vTrianglePoints.Get (i);
  for (i=0; i < vPoints.Length (); i++)
    delete (csCrystalBallVec*)vPoints.Get (i);
}

void csCrystalBall::InsertPolygon (iPolygonMesh *polyset, int idx)
{
  csMeshedPolygon &mp = polyset->GetPolygons ()[idx];
  // calc the normal first
  csCrystalBallVec *n = new csCrystalBallVec (idx);
  csMath3::CalcNormal (*n, polyset->GetVertices ()[mp.vertices[0]],
		       polyset->GetVertices ()[mp.vertices[1]],
		       polyset->GetVertices ()[mp.vertices[2]]
		       );
  // which of the 8 starting triangles we add this to ?
  int i1 = 0, i2 = 0, i3 = 0, i = 0;
  if (n->y < 0)
    i += 4;
  if (n->z < 0)
    i += 2;
  if (n->x >= 0)
    i += 1;

  switch (i)
  {
    case 0: i1=3; i2=1; i2=2; break;
    case 1: i1=0; i2=1; i2=2; break;
    case 2: i1=3; i2=1; i2=5; break;
    case 3: i1=0; i2=1; i2=5; break;
    case 4: i1=3; i2=4; i2=2; break;
    case 5: i1=0; i2=4; i2=2; break;
    case 6: i1=3; i2=4; i2=5; break;
    case 7: i1=0; i2=4; i2=5; break;
  }

  int nPos = tri[i].Add (n, i1, i2, i3, &vPoints, &vTrianglePoints);
  for (i=0; i < 7; i++)
    tri[i].Adjust (nPos);
}

void csCrystalBall::Build (iPolygonMesh *polyset)
{
  // just cycle through all polygons and add them
  int i;
  for (i=0; i<polyset->GetPolygonCount (); i++)
    InsertPolygon (polyset, i);
}

void csCrystalBall::Transform (const csTransform &o2c, csVector &indexVector,
			       int useSign, long cookie)
{
  // fill indexVector with the indices to those polygons that have a
  // normal vector with sign(z-coordinate) == <useSign>

  // first check the base triangles
  // for this we simply check the base vectors - luckily the form a unit matrix
  // so we can simply check o2c.

  const csMatrix3 &m = o2c.GetO2T ();
  csVector3 e1 = m.Col1 ();
  csVector3 e2 = m.Col2 ();
  csVector3 e3 = m.Col3 ();
  csVector3 ne1 = -1 * e1;
  csVector3 ne2 = -1 * e2;
  csVector3 ne3 = -1 * e3;

  tri[0].Transform (m, indexVector, useSign, cookie, &vPoints,
  	&vTrianglePoints, ne1,  e2,  e3);
  tri[1].Transform (m, indexVector, useSign, cookie, &vPoints,
  	&vTrianglePoints, e1,  e2,  e3);
  tri[2].Transform (m, indexVector, useSign, cookie, &vPoints,
  	&vTrianglePoints, ne1,  e2, ne3);
  tri[3].Transform (m, indexVector, useSign, cookie, &vPoints,
  	&vTrianglePoints, e1,  e2, ne3);
  tri[4].Transform (m, indexVector, useSign, cookie, &vPoints,
  	&vTrianglePoints, ne1, ne2,  e3);
  tri[5].Transform (m, indexVector, useSign, cookie, &vPoints,
  	&vTrianglePoints, e1, ne2,  e3);
  tri[6].Transform (m, indexVector, useSign, cookie, &vPoints,
  	&vTrianglePoints, ne1, ne2, ne3);
  tri[7].Transform (m, indexVector, useSign, cookie, &vPoints,
  	&vTrianglePoints, e1, ne2, ne3);
}
<|endoftext|>


<commit_before>#include "stdafx.h"

void*	NULLC::defaultAlloc(int size)
{
	return ::new(std::nothrow) char[size];
}
void	NULLC::defaultDealloc(void* ptr)
{
	::delete[] (char*)ptr;
}

void*	(*NULLC::alloc)(int) = NULLC::defaultAlloc;
void	(*NULLC::dealloc)(void*) = NULLC::defaultDealloc;

void* NULLC::alignedAlloc(int size)
{
	void *unaligned = alloc((size + 16 - 1) + sizeof(void*));
	if(!unaligned)
		return NULL;
	void *ptr = (void*)(((intptr_t)unaligned + sizeof(void*) + 16 - 1) & ~(16 - 1));
	memcpy((void**)ptr - 1, &unaligned, sizeof(unaligned));
	return ptr;
}

void* NULLC::alignedAlloc(int size, int extraSize)
{
	void *unaligned = alloc((size + 16 - 1) + sizeof(void*) + extraSize);
	if(!unaligned)
		return NULL;
	void *ptr = (void*)((((intptr_t)unaligned + sizeof(void*) + extraSize + 16 - 1) & ~(16 - 1)) - extraSize);
	memcpy((void**)ptr - 1, &unaligned, sizeof(unaligned));
	return ptr;
}

void NULLC::alignedDealloc(void* ptr)
{
	void* unaligned = NULL;
	memcpy(&unaligned, (void**)ptr - 1, sizeof(unaligned));
	dealloc(unaligned);
}

const char* NULLC::defaultFileLoad(const char* name, unsigned* size)
{
	assert(name);
	assert(size);

	FILE *file = fopen(name, "rb");
	if(file)
	{
		fseek(file, 0, SEEK_END);
		*size = ftell(file);
		fseek(file, 0, SEEK_SET);
		char *fileContent = (char*)NULLC::alloc(*size + 1);
		unsigned read = (unsigned)fread(fileContent, 1, *size, file);

		if(read != *size)
		{
			NULLC::dealloc(fileContent);
			*size = 0;
			return NULL;
		}

		fileContent[*size] = 0;
		fclose(file);
		return fileContent;
	}
	*size = 0;
	return NULL;
}

void NULLC::defaultFileFree(const char* data)
{
	if(data)
		NULLC::dealloc((char*)data);
}

const char* (*NULLC::fileLoad)(const char*, unsigned*) = NULLC::defaultFileLoad;
void (*NULLC::fileFree)(const char*) = NULLC::defaultFileFree;
<commit_msg>Fixed file handle leak after file read failure<commit_after>#include "stdafx.h"

void*	NULLC::defaultAlloc(int size)
{
	return ::new(std::nothrow) char[size];
}
void	NULLC::defaultDealloc(void* ptr)
{
	::delete[] (char*)ptr;
}

void*	(*NULLC::alloc)(int) = NULLC::defaultAlloc;
void	(*NULLC::dealloc)(void*) = NULLC::defaultDealloc;

void* NULLC::alignedAlloc(int size)
{
	void *unaligned = alloc((size + 16 - 1) + sizeof(void*));
	if(!unaligned)
		return NULL;
	void *ptr = (void*)(((intptr_t)unaligned + sizeof(void*) + 16 - 1) & ~(16 - 1));
	memcpy((void**)ptr - 1, &unaligned, sizeof(unaligned));
	return ptr;
}

void* NULLC::alignedAlloc(int size, int extraSize)
{
	void *unaligned = alloc((size + 16 - 1) + sizeof(void*) + extraSize);
	if(!unaligned)
		return NULL;
	void *ptr = (void*)((((intptr_t)unaligned + sizeof(void*) + extraSize + 16 - 1) & ~(16 - 1)) - extraSize);
	memcpy((void**)ptr - 1, &unaligned, sizeof(unaligned));
	return ptr;
}

void NULLC::alignedDealloc(void* ptr)
{
	void* unaligned = NULL;
	memcpy(&unaligned, (void**)ptr - 1, sizeof(unaligned));
	dealloc(unaligned);
}

const char* NULLC::defaultFileLoad(const char* name, unsigned* size)
{
	assert(name);
	assert(size);

	FILE *file = fopen(name, "rb");
	if(file)
	{
		fseek(file, 0, SEEK_END);
		*size = ftell(file);
		fseek(file, 0, SEEK_SET);
		char *fileContent = (char*)NULLC::alloc(*size + 1);
		unsigned read = (unsigned)fread(fileContent, 1, *size, file);

		if(read != *size)
		{
			NULLC::dealloc(fileContent);
			*size = 0;

			fclose(file);
			return NULL;
		}

		fileContent[*size] = 0;
		fclose(file);
		return fileContent;
	}
	*size = 0;
	return NULL;
}

void NULLC::defaultFileFree(const char* data)
{
	if(data)
		NULLC::dealloc((char*)data);
}

const char* (*NULLC::fileLoad)(const char*, unsigned*) = NULLC::defaultFileLoad;
void (*NULLC::fileFree)(const char*) = NULLC::defaultFileFree;
<|endoftext|>


<commit_before>/*
 *  PointerAgent.cpp
 *  openc2e
 *
 *  Created by Alyssa Milburn on Tue Aug 30 2005.
 *  Copyright (c) 2005 Alyssa Milburn. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 */

#include "PointerAgent.h"
#include "openc2e.h"
#include "World.h"
#include "Engine.h"
#include "caosVM.h"
#include "Room.h"

// TODO: change imagecount?
PointerAgent::PointerAgent(std::string spritefile) : SimpleAgent(2, 1, 1, INT_MAX, spritefile, 0, 0) {
	name = "hand";
	handle_events = true;
	holdingWire = 0;
	wireOriginID = 0;
	// TODO: verify attributes on the pointer in c2e
	attr.setInt(256); // camera shy
}

void PointerAgent::finishInit() {
	Agent::finishInit();

	// float relative to main camera
	attr.setInt(attr.getInt() & 32);
	floatSetup();
}

// TODO: this should have a queueScript equiv too
void PointerAgent::firePointerScript(unsigned short event, Agent *src) {
	assert(src); // TODO: I /think/ this should only be called by the engine..
	shared_ptr<script> s = src->findScript(event);
	if (!s && engine.version < 3) { // TODO: are we sure this doesn't apply to c2e?
		s = findScript(event); // TODO: we should make sure this actually belongs to the pointer agent and isn't a fallback, maybe
	}
	if (!s) return;
	if (!vm) vm = world.getVM(this);
	if (vm->fireScript(s, false, src)) { // TODO: should FROM be src?
		vm->setTarg(this);
		zotstack();
	}
}

void PointerAgent::physicsTick() {
	// TODO: this is a hack, which does nothing, because we set a velocity in main() but also move the cursor manually
}

void PointerAgent::kill() {
	// pointer agent isn't killable
}

void PointerAgent::handleEvent(SomeEvent &event) {
	if (event.type == eventmousemove) {
		moveTo(event.x + world.camera.getX(), event.y + world.camera.getY());
		velx.setInt(event.xrel * 4);
		vely.setInt(event.yrel * 4);

		// middle mouse button scrolling
		if (event.button & buttonmiddle)
			world.camera.moveTo(world.camera.getX() - event.xrel, world.camera.getY() - event.yrel, jump);
	} else if (!handle_events) {
		/* mouse move events are (apparently - see eg C3 agent help) still handled with handle_events disabled, but nothing else */
		return;
	} else if (event.type == eventmousebuttondown) {
		// do our custom handling
		if (event.button == buttonleft) {
			CompoundPart *a = world.partAt(x, y);
			if (a /* && a->canActivate() */) { // TODO
				Agent* parent = a->getParent();

				int eve = -1;

				bool foundport = false;
				if (engine.version > 2) {
					for (std::map<unsigned int, boost::shared_ptr<OutputPort> >::iterator i = parent->outports.begin();
							 i != parent->outports.end(); i++) {
						// TODO: 4 is a magic number i pulled out of nooooowhere
						if (abs(i->second->x + parent->x - x) < 4 && abs(i->second->y + parent->y - y) < 4) {
							foundport = true;
							if (holdingWire == 2) {
								parent->join(i->first, wireOriginAgent, wireOriginID);
								holdingWire = 0;
								eve = 111;
							} else if (holdingWire == 0) {
								eve = 110;
								holdingWire = 1;
								wireOriginAgent = parent;
								wireOriginID = i->first;
							}
							break;
						}
					}
					if (!foundport) {
						for (std::map<unsigned int, boost::shared_ptr<InputPort> >::iterator i = parent->inports.begin();
								 i != parent->inports.end(); i++) {
							// TODO: 4 is a magic number i pulled out of nooooowhere
							if (abs(i->second->x + parent->x - x) < 4 && abs(i->second->y + parent->y - y) < 4) {
								foundport = true;
								if (holdingWire == 1) {
									wireOriginAgent->join(wireOriginID, parent, i->first);
									holdingWire = 0;
									eve = 111;
								} else if (holdingWire == 0) {
									eve = 110;
									holdingWire = 2;
									wireOriginAgent = parent;
									wireOriginID = i->first;
								}
								break;
							}
						}
					}
				}

				if (!foundport) {
					if (holdingWire) {
						holdingWire = 0;
						eve = 113;
					} else {
						// if the agent isn't paused, tell it to handle a click
						int scriptid = a->handleClick(x - a->x - parent->x, y - a->y - parent->y);
						if (scriptid != -1) {
							// fire the script
							// _p1_ is id of part for button clicks, according to Edynn code
							// TODO: should _p1_ always be set? :)
							if (!parent->paused) parent->queueScript(scriptid, world.hand(), (int)a->id);

							// annoyingly queueScript doesn't reliably tell us if it did anything useful.
							// TODO: work out the mess which is queueScript's return values etc
							if (!parent->findScript(scriptid)) return;

							// fire the associated pointer script too, if necessary
							// TODO: fuzzie has no idea if this code is remotely correct
							if (engine.version < 3) {
								eve = 50;
							} else {
								eve = 101; // Pointer Activate 1
							}
							switch (scriptid) {
								case 0: eve += 2; break; // deactivate
								case 1: break; // activate 1
								case 2: eve += 1; break; // activate 2
								default: return;
							}
						}
					}
				}

				if (eve != -1) firePointerScript(eve, a->getParent());
			} else if (engine.version > 2) {
				if (holdingWire) {
					holdingWire = 0;
					queueScript(113, 0);
				} else {
					queueScript(116, 0); // Pointer Clicked Background
				}
			}
		} else if (event.button == buttonright) {
			if (world.paused) return; // TODO: wrong?

			// picking up and dropping are implictly handled by the scripts (well,
			// messages) 4 and 5	TODO: check if this is correct behaviour, one issue
			// is that this isn't instant, another is the messages might only be
			// fired in c2e when you use MESG WRIT, in which case we'll need to
			// manually set carrying to NULL and a here, respectively - fuzzie
			if (carrying) {
				// TODO: c1 support - these attributes are invalid for c1
				if (!carrying->suffercollisions() || (carrying->validInRoomSystem() || engine.version == 1)) {
					carrying->queueScript(5, this); // drop

					int eve; if (engine.version < 3) eve = 54; else eve = 105;
					firePointerScript(eve, carrying); // Pointer Drop

					// TODO: is this the correct check?
					if (carrying->sufferphysics() && carrying->suffercollisions()) {
						// TODO: do this in the pointer agent?
						carrying->velx.setFloat(velx.getFloat());
						carrying->vely.setFloat(vely.getFloat());
					}
				} else {
					// TODO: some kind of "fail to drop" animation/sound?
				}
			} else {
				Agent *a = world.agentAt(x, y, false, true);
				if (a) {
					a->queueScript(4, this); // pickup

					int eve; if (engine.version < 3) eve = 53; else eve = 104;
					firePointerScript(eve, a); // Pointer Pickup
				}
			}
		} else if (event.button == buttonmiddle) {
			std::vector<shared_ptr<Room> > rooms = world.map.roomsAt(event.x + world.camera.getX(), event.y + world.camera.getY());
			if (rooms.size() > 0) std::cout << "Room at cursor is " << rooms[0]->id << std::endl;
			Agent *a = world.agentAt(event.x + world.camera.getX(), event.y + world.camera.getY(), true);
			if (a)
				std::cout << "Agent under mouse is " << a->identify();
			else
				std::cout << "No agent under cursor";
			std::cout << std::endl;
		}
	}
}

/* vim: set noet: */
<commit_msg>Ports are disconnectable now (click inputport-side connection to remove)<commit_after>/*
 *  PointerAgent.cpp
 *  openc2e
 *
 *  Created by Alyssa Milburn on Tue Aug 30 2005.
 *  Copyright (c) 2005 Alyssa Milburn. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 */

#include "PointerAgent.h"
#include "openc2e.h"
#include "World.h"
#include "Engine.h"
#include "caosVM.h"
#include "Room.h"

// TODO: change imagecount?
PointerAgent::PointerAgent(std::string spritefile) : SimpleAgent(2, 1, 1, INT_MAX, spritefile, 0, 0) {
	name = "hand";
	handle_events = true;
	holdingWire = 0;
	wireOriginID = 0;
	// TODO: verify attributes on the pointer in c2e
	attr.setInt(256); // camera shy
}

void PointerAgent::finishInit() {
	Agent::finishInit();

	// float relative to main camera
	attr.setInt(attr.getInt() & 32);
	floatSetup();
}

// TODO: this should have a queueScript equiv too
void PointerAgent::firePointerScript(unsigned short event, Agent *src) {
	assert(src); // TODO: I /think/ this should only be called by the engine..
	shared_ptr<script> s = src->findScript(event);
	if (!s && engine.version < 3) { // TODO: are we sure this doesn't apply to c2e?
		s = findScript(event); // TODO: we should make sure this actually belongs to the pointer agent and isn't a fallback, maybe
	}
	if (!s) return;
	if (!vm) vm = world.getVM(this);
	if (vm->fireScript(s, false, src)) { // TODO: should FROM be src?
		vm->setTarg(this);
		zotstack();
	}
}

void PointerAgent::physicsTick() {
	// TODO: this is a hack, which does nothing, because we set a velocity in main() but also move the cursor manually
}

void PointerAgent::kill() {
	// pointer agent isn't killable
}

void PointerAgent::handleEvent(SomeEvent &event) {
	if (event.type == eventmousemove) {
		moveTo(event.x + world.camera.getX(), event.y + world.camera.getY());
		velx.setInt(event.xrel * 4);
		vely.setInt(event.yrel * 4);

		// middle mouse button scrolling
		if (event.button & buttonmiddle)
			world.camera.moveTo(world.camera.getX() - event.xrel, world.camera.getY() - event.yrel, jump);
	} else if (!handle_events) {
		/* mouse move events are (apparently - see eg C3 agent help) still handled with handle_events disabled, but nothing else */
		return;
	} else if (event.type == eventmousebuttondown) {
		// do our custom handling
		if (event.button == buttonleft) {
			CompoundPart *a = world.partAt(x, y);
			if (a /* && a->canActivate() */) { // TODO
				Agent* parent = a->getParent();

				int eve = -1;

				bool foundport = false;
				if (engine.version > 2) {
					for (std::map<unsigned int, boost::shared_ptr<OutputPort> >::iterator i = parent->outports.begin();
							 i != parent->outports.end(); i++) {
						// TODO: 4 is a magic number i pulled out of nooooowhere
						if (abs(i->second->x + parent->x - x) < 4 && abs(i->second->y + parent->y - y) < 4) {
							foundport = true;
							if (holdingWire == 2) {
								parent->join(i->first, wireOriginAgent, wireOriginID);
								holdingWire = 0;
								eve = 111;
							} else if (holdingWire == 0) {
								eve = 110;
								holdingWire = 1;
								wireOriginAgent = parent;
								wireOriginID = i->first;
							}
							break;
						}
					}
					if (!foundport) {
						for (std::map<unsigned int, boost::shared_ptr<InputPort> >::iterator i = parent->inports.begin();
								 i != parent->inports.end(); i++) {
							// TODO: 4 is a magic number i pulled out of nooooowhere
							if (abs(i->second->x + parent->x - x) < 4 && abs(i->second->y + parent->y - y) < 4) {
								foundport = true;
								if (holdingWire == 1) {
									wireOriginAgent->join(wireOriginID, parent, i->first);
									holdingWire = 0;
									eve = 111;
								} else if (holdingWire == 0) {
									if (i->second->source) {
										eve = 112;
										holdingWire = 1;
										wireOriginAgent = i->second->source;
										wireOriginID = i->second->sourceid;
										i->second->source->outports[i->second->sourceid]->dests.remove(std::pair<AgentRef, unsigned int>(parent, i->first));
									} else {
										eve = 110;
										holdingWire = 2;
										wireOriginAgent = parent;
										wireOriginID = i->first;
									}
								}
								break;
							}
						}
					}
				}

				if (!foundport) {
					if (holdingWire) {
						holdingWire = 0;
						eve = 113;
					} else {
						// if the agent isn't paused, tell it to handle a click
						int scriptid = a->handleClick(x - a->x - parent->x, y - a->y - parent->y);
						if (scriptid != -1) {
							// fire the script
							// _p1_ is id of part for button clicks, according to Edynn code
							// TODO: should _p1_ always be set? :)
							if (!parent->paused) parent->queueScript(scriptid, world.hand(), (int)a->id);

							// annoyingly queueScript doesn't reliably tell us if it did anything useful.
							// TODO: work out the mess which is queueScript's return values etc
							if (!parent->findScript(scriptid)) return;

							// fire the associated pointer script too, if necessary
							// TODO: fuzzie has no idea if this code is remotely correct
							if (engine.version < 3) {
								eve = 50;
							} else {
								eve = 101; // Pointer Activate 1
							}
							switch (scriptid) {
								case 0: eve += 2; break; // deactivate
								case 1: break; // activate 1
								case 2: eve += 1; break; // activate 2
								default: return;
							}
						}
					}
				}

				if (eve != -1) firePointerScript(eve, a->getParent());
			} else if (engine.version > 2) {
				if (holdingWire) {
					holdingWire = 0;
					queueScript(113, 0);
				} else {
					queueScript(116, 0); // Pointer Clicked Background
				}
			}
		} else if (event.button == buttonright) {
			if (world.paused) return; // TODO: wrong?

			// picking up and dropping are implictly handled by the scripts (well,
			// messages) 4 and 5	TODO: check if this is correct behaviour, one issue
			// is that this isn't instant, another is the messages might only be
			// fired in c2e when you use MESG WRIT, in which case we'll need to
			// manually set carrying to NULL and a here, respectively - fuzzie
			if (carrying) {
				// TODO: c1 support - these attributes are invalid for c1
				if (!carrying->suffercollisions() || (carrying->validInRoomSystem() || engine.version == 1)) {
					carrying->queueScript(5, this); // drop

					int eve; if (engine.version < 3) eve = 54; else eve = 105;
					firePointerScript(eve, carrying); // Pointer Drop

					// TODO: is this the correct check?
					if (carrying->sufferphysics() && carrying->suffercollisions()) {
						// TODO: do this in the pointer agent?
						carrying->velx.setFloat(velx.getFloat());
						carrying->vely.setFloat(vely.getFloat());
					}
				} else {
					// TODO: some kind of "fail to drop" animation/sound?
				}
			} else {
				Agent *a = world.agentAt(x, y, false, true);
				if (a) {
					a->queueScript(4, this); // pickup

					int eve; if (engine.version < 3) eve = 53; else eve = 104;
					firePointerScript(eve, a); // Pointer Pickup
				}
			}
		} else if (event.button == buttonmiddle) {
			std::vector<shared_ptr<Room> > rooms = world.map.roomsAt(event.x + world.camera.getX(), event.y + world.camera.getY());
			if (rooms.size() > 0) std::cout << "Room at cursor is " << rooms[0]->id << std::endl;
			Agent *a = world.agentAt(event.x + world.camera.getX(), event.y + world.camera.getY(), true);
			if (a)
				std::cout << "Agent under mouse is " << a->identify();
			else
				std::cout << "No agent under cursor";
			std::cout << std::endl;
		}
	}
}

/* vim: set noet: */
<|endoftext|>


<commit_before>#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>

typedef struct
{
	int codigo;
	char raca[30], nome[100];
} registro;

typedef struct
{
	int codigo, offset;
} indice1;

typedef struct
{
	char vacina[30];
	int offset;
} indice2;

int Menu();
void AbreArquivos(FILE **AP1, FILE **AP2, FILE **IndPrim, FILE **IndSec1, FILE **IndSec2);
void CadastraVacina(FILE **AP1, FILE **AP2);
void CadastraCachorro(FILE **AP2);
void AtualizaInfoIndice(char status, FILE **arq);
int ExisteCachorro(int codigo, FILE **AP2);

int main()
{
    int opcao;
	FILE *AP1, *AP2, *IndPrim, *IndSec1, *IndSec2;

	AbreArquivos(&AP1, &AP2, &IndPrim, &IndSec1, &IndSec2);
	opcao = Menu();
	while (opcao != 0)
	{
	    switch(opcao)
	    {
	        case 1: CadastraCachorro(&AP2);
        }
        opcao = Menu();
    }

	fclose(AP1);
	fclose(AP2);
	fclose(IndPrim);
	fclose(IndSec1);
	fclose(IndSec2);
	return 0;
}

int Menu()
{
	int opcao = -1;

	while ((opcao != 1) && (opcao != 0))
	{
		system("CLS");
        printf("\n1 - Cadastra Cachorro");
		printf("\n0 - Sair");
		printf("\n\nEscolha a opcao: ");
        scanf("%d", &opcao);
    }
	return opcao;
}

/*
DESCRIO: Verifica se os arquivos j foram criados.
           Se no, cria-os.
PARMETROS: AP1 - Arquivo Principal 1
            AP2 - Arquivo Principal 2
	        IndPrim - Arquivo de ndice (busca por chave primria)
			IndSec1 - Arquivo de ndice 1 (busca por chave secundria)
			IndSec2 - Arquivo de ndice 2 (busca por chave secundria)
*/
void AbreArquivos(FILE **AP1, FILE **AP2, FILE **IndPrim, FILE **IndSec1, FILE **IndSec2)
{
    if ((*AP1 = fopen("AP1.bin", "r+b")) == NULL)
    {
    	*AP1 = fopen("AP1.bin", "w+b");
    	fprintf(*AP1, "%d", -1);
    	*IndPrim = fopen("IndPrim.bin", "w+b");
    	AtualizaInfoIndice('!', IndPrim);
    	*IndSec1 = fopen("IndSec1.bin", "w+b");
    	AtualizaInfoIndice('!', IndSec1);
    	*IndSec2 = fopen("IndSec2.bin", "w+b");
    	AtualizaInfoIndice('!', IndSec2);
	}
	/*else if (ExigeRecriaIndice(IndPrim))
	{
		RecriaIndicePrim(AP1);
		QuickSortInd1(INDEX1, 0, tam1);
	}
	else
	{
		IndPrim = fopen("IndPrim.bin", "r+b");
		CarregaIndice(IndPrim, 1);
    	IndSec1 = fopen("IndSec1.bin", "r+b");
    	CarregaIndice(IndSec1, 2);
    	IndSec2 = fopen("IndSec2.bin", "r+b");
    	CarregaIndice(IndSec2, 1);
	}*/

    if ((*AP2 = fopen("AP2.bin", "r+b")) == NULL)
        *AP2 = fopen("AP2.bin", "w+b");

}

/*
DESCRIO: Cadastra informaes de um cachorro no Arquivo Principal 2
PARMETROS: AP2 - Arquivo Principal 2
*/
void CadastraCachorro(FILE **AP2)
{
	registro reg;

	system("CLS");
	printf("\nCodigo: ");
	scanf("%d", &reg.codigo);
	while (ExisteCachorro(reg.codigo, AP2))
	{
		system("CLS");
		printf("\nCodigo ja cadastrado. Digite novamente!");
		getch();
		system("CLS");
		printf("\nCodigo: ");
		scanf("%d", &reg.codigo);
	}
	fflush(stdin);
	printf("Raca: ");
	gets(reg.raca);
	printf("Nome do Cachorro: ");
	gets(reg.nome);

	fseek(*AP2, 0, SEEK_END); //seta a posio para o fim do arquivo.
	fwrite(&reg, sizeof(reg), 1, *AP2); //escreve no fim do arquivo.
}

/*
DESCRIO: Atualiza o header do ndice com o status de atualizao
PARMETROS: status - '*' - ndice atualizado
                     '!' - ndice desatualizado
            arq - ndice a ser atualizado
*/
void AtualizaInfoIndice(char status, FILE **arq)
{
	fseek(*arq, 0, SEEK_SET);
	fputc(status, *arq);
}

/*
DESCRIO: Verifica se o cdigo j existe no arquivo.
PARMETROS: codigo - Cdigo a ser verificado
            AP2 - Arquivo Principal 2
RETORNOS: 0 - No existe um cachorro com o cdigo passado por parmetro
          1 - Existe um cachorro com o cdigo passado por parmetro
*/
int ExisteCachorro(int codigo, FILE **AP2)
{
	int i = 0;
	registro reg;

	rewind(*AP2);
	while (fread(&reg, sizeof(registro)*i, 1, *AP2) >= 1)
	{
		if (reg.codigo == codigo)
		{
			return 1;
			break;
		}
		i++;
	}
    return 0;
}

void CadastraVacina(FILE **AP1, FILE **AP2)
{
    int cod_controle, cod_cachorro, tam_reg;
    char verificador = '*', vacina[30], data[6], respo[100], registro[255];

    system("CLS");
    printf("\n\nDigite o cdigo do cachorro <-1 para cadastrar um cachorro>: ");
    scanf("%d", &cod_cachorro);
    if (cod_cachorro == -1)
      CadastraCachorro(AP2);
    else
    {
        while (!ExisteCachorro(cod_cachorro, AP2))
        {
            printf("\n\nCachorro inexistente. Digite novamente!");
            system("CLS");
            printf("\n\nDigite o cdigo do cachorro <-1 para cadastrar um cachorro>: ");
            scanf("%d", &cod_cachorro);
            if (cod_cachorro == -1)
              CadastraCachorro(AP2);
        }
        system("CLS");
        //cod_controle = pegar do INDEX1 ordenado;
        printf("Codigo do cachorro: %d", cod_cachorro);
        printf("\nNome da vacina: ");
        gets(vacina);
        printf("\nData de vacinacao <MM/AA>: ");
        gets(data);
        printf("\nResponsavel pela aplicacao: ");
        gets(respo);
        sprintf(registro, "%d|%d|%s|%s|%s|", cod_controle, cod_cachorro, vacina, data, respo);
        tam_reg = strlen(registro);
        //verificar espaos em branco no arquivo para insero;
        fwrite(&tam_reg, sizeof(int), 1, *AP1);
        fwrite(&verificador, sizeof(char), 1, *AP1);
        fwrite(registro, sizeof(char), tam_reg, *AP1);
    }
}

<commit_msg>Novas Funções<commit_after>#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>

typedef struct
{
	int codigo;
	char raca[30], nome[100];
} registro;

typedef struct
{
	int codigo, offset;
} indice1;

typedef struct
{
	char vacina[30];
	int offset;
} indice2;

int Menu();
void AbreArquivos(FILE **AP1, FILE **AP2, FILE **IndPrim, FILE **IndSec1, FILE **IndSec2);
void CadastraVacina(FILE **AP1, FILE **AP2);
void CadastraCachorro(FILE **AP2);
void AtualizaInfoIndice(char status, FILE **arq);
int ExisteCachorro(int codigo, FILE **AP2);
int ProcuraEspacoVazio(FILE **AP1, int tam_reg);

int main()
{
    int opcao;
	FILE *AP1, *AP2, *IndPrim, *IndSec1, *IndSec2;

	AbreArquivos(&AP1, &AP2, &IndPrim, &IndSec1, &IndSec2);
	opcao = Menu();
	while (opcao != 0)
	{
	    switch(opcao)
	    {
	        case 1: CadastraVacina(&AP1, &AP2);
        }
        opcao = Menu();
    }

	fclose(AP1);
	fclose(AP2);
	fclose(IndPrim);
	fclose(IndSec1);
	fclose(IndSec2);
	return 0;
}

int Menu()
{
	int opcao = -1;

	while ((opcao != 1) && (opcao != 0))
	{
		system("CLS");
        printf("\n1 - Cadastra Vacina");
		printf("\n0 - Sair");
		printf("\n\nEscolha a opcao: ");
        scanf("%d", &opcao);
    }
	return opcao;
}

/*
DESCRIO: Verifica se os arquivos j foram criados.
           Se no, cria-os.
PARMETROS: AP1 - Arquivo Principal 1
            AP2 - Arquivo Principal 2
	        IndPrim - Arquivo de ndice (busca por chave primria)
			IndSec1 - Arquivo de ndice 1 (busca por chave secundria)
			IndSec2 - Arquivo de ndice 2 (busca por chave secundria)
*/
void AbreArquivos(FILE **AP1, FILE **AP2, FILE **IndPrim, FILE **IndSec1, FILE **IndSec2)
{
    if ((*AP1 = fopen("AP1.bin", "r+b")) == NULL)
    {
    	*AP1 = fopen("AP1.bin", "w+b");
    	fprintf(*AP1, "%d", -1);
    	*IndPrim = fopen("IndPrim.bin", "w+b");
    	AtualizaInfoIndice('!', IndPrim);
    	*IndSec1 = fopen("IndSec1.bin", "w+b");
    	AtualizaInfoIndice('!', IndSec1);
    	*IndSec2 = fopen("IndSec2.bin", "w+b");
    	AtualizaInfoIndice('!', IndSec2);
	}
	/*else if (ExigeRecriaIndice(IndPrim))
	{
		RecriaIndicePrim(AP1);
		QuickSortInd1(INDEX1, 0, tam1);
	}
	else
	{
		IndPrim = fopen("IndPrim.bin", "r+b");
		CarregaIndice(IndPrim, 1);
    	IndSec1 = fopen("IndSec1.bin", "r+b");
    	CarregaIndice(IndSec1, 2);
    	IndSec2 = fopen("IndSec2.bin", "r+b");
    	CarregaIndice(IndSec2, 1);
	}*/

    if ((*AP2 = fopen("AP2.bin", "r+b")) == NULL)
        *AP2 = fopen("AP2.bin", "w+b");

}

/*
DESCRIO: Cadastra informaes de um cachorro no Arquivo Principal 2
PARMETROS: AP2 - Arquivo Principal 2
*/
void CadastraCachorro(FILE **AP2)
{
	registro reg;

	system("CLS");
	printf("\nCodigo: ");
	scanf("%d", &reg.codigo);
	while (ExisteCachorro(reg.codigo, AP2))
	{
		system("CLS");
		printf("\nCodigo ja cadastrado. Digite novamente!");
		getch();
		system("CLS");
		printf("\nCodigo: ");
		scanf("%d", &reg.codigo);
	}
	fflush(stdin);
	printf("Raca: ");
	gets(reg.raca);
	printf("Nome do Cachorro: ");
	gets(reg.nome);

	fseek(*AP2, 0, SEEK_END); //seta a posio para o fim do arquivo.
	fwrite(&reg, sizeof(reg), 1, *AP2); //escreve no fim do arquivo.
}

/*
DESCRIO: Atualiza o header do ndice com o status de atualizao
PARMETROS: status - '*' - ndice atualizado
                     '!' - ndice desatualizado
            arq - ndice a ser atualizado
*/
void AtualizaInfoIndice(char status, FILE **arq)
{
	fseek(*arq, 0, SEEK_SET);
	fputc(status, *arq);
}

/*
DESCRIO: Verifica se o cdigo j existe no arquivo.
PARMETROS: codigo - Cdigo a ser verificado
            AP2 - Arquivo Principal 2
RETORNOS: 0 - No existe um cachorro com o cdigo passado por parmetro
          1 - Existe um cachorro com o cdigo passado por parmetro
*/
int ExisteCachorro(int codigo, FILE **AP2)
{
	int i = 1;
	registro reg;

	rewind(*AP2);
	while (fread(&reg, sizeof(registro)*i, 1, *AP2) >= 1)
	{
		if (reg.codigo == codigo)
		{
			return 1;
			break;
		}
		i++;
	}
    return 0;
}

/*
DESCRIO: Realiza o cadastro de vacinas
PARMETROS: AP1 - Arquivo principal 1
            AP2 - Arquivo principal 2
*/
void CadastraVacina(FILE **AP1, FILE **AP2)
{
    int cod_controle, cod_cachorro, tam_reg, posicao;
    char verificador = '*', vacina[30], data[6], respo[100], registro[255];

    system("CLS");
    printf("\n\nDigite o cdigo do cachorro <-1 para cadastrar um cachorro>: ");
    scanf("%d", &cod_cachorro);
    if (cod_cachorro == -1)
      CadastraCachorro(AP2);
    else
    {
        while (!ExisteCachorro(cod_cachorro, AP2))
        {
            printf("\n\nCachorro inexistente. Digite novamente!");
            system("CLS");
            printf("\n\nDigite o cdigo do cachorro <-1 para cadastrar um cachorro>: ");
            scanf("%d", &cod_cachorro);
            if (cod_cachorro == -1)
              CadastraCachorro(AP2);
        }
        system("CLS");
        cod_controle = 1;//cod_controle = pegar do INDEX1 ordenado;
        printf("Codigo do cachorro: %d", cod_cachorro);
        fflush(stdin);
        printf("\nNome da vacina: ");
        gets(vacina);
        printf("\nData de vacinacao <MM/AA>: ");
        gets(data);
        printf("\nResponsavel pela aplicacao: ");
        gets(respo);
        sprintf(registro, "%d|%d|%s|%s|%s|", cod_controle, cod_cachorro, vacina, data, respo);
        tam_reg = strlen(registro);
        posicao = ProcuraEspacoVazio(AP1, tam_reg);
        if (posicao != -1)
          fseek(*AP1, posicao, SEEK_SET);
        else
          fseek(*AP1, 0, SEEK_END);
        fwrite(&tam_reg, sizeof(int), 1, *AP1);
        fwrite(&verificador, sizeof(char), 1, *AP1);
        fwrite(registro, sizeof(char), tam_reg, *AP1);
    }
}

/*
DESCRIO: Retorna o espao vazio encontrado no arquivo
PARMETROS: AP1 - Arquivo principal 1
            tam_reg - tamanho do registro a ser inserido
RETORNO: posio livre para ser escrita
*/
int ProcuraEspacoVazio(FILE **AP1, int tam_reg)
{
    int offset, tam, pos;
    char ch;

    rewind(*AP1);
    fread(&offset, sizeof(int), 1, *AP1);
    if (offset == -1)
        return -1;
    else
    {
        fseek(*AP1, offset, SEEK_SET);
        pos = ftell(*AP1);
        while (fread(&tam, sizeof(int), 1, *AP1))
        {
            if (tam == -1)
            {
                return -1;
                break;
            }
            else
            {
                ch = fgetc(*AP1);
                if ((tam > tam_reg) && (ch == '!'))
                {
                   return pos;
                   break;
                }
                else
                {
                    fread(&offset, sizeof(int), 1, *AP1);
                    fseek(*AP1, offset, SEEK_SET);
                }
            }
        }
    }
}

<|endoftext|>


<commit_before>#include "fileHelpers/DICOMLoaderVTK.h"
#include "ContourFromMask.h"
#include "ActiveContour.h"
#include "ContourToMask.h"
#include "Helpers/Validator.h"
#include "Helpers/Converter.h"

#include <vtkExtractVOI.h>

#include <opencv2/highgui.hpp>
#include <vtkRenderer.h>

int main( int argc, char** argv )
{
    if( argc < 4 )
    {
        std::cerr << "usage: " << argv[0] << " [pathToDatasetImage] [pathToMaskImage] [pathToGroundTruth]" << std::endl;
        return -1;
    }

    int nPoints = 500;
    double simplficationEps = 1;
    double elasticity = 10;
    double stiffness = 500;
    double speed = 0.2;
    double smoothingSigma = 2;
    double iterations = 130;

    std::cerr << "load data" << std::endl;
    vtkSmartPointer<vtkImageData> image =
            DICOMLoaderVTK::loadDICOMSeries( std::string( argv[1] ) );

    vtkSmartPointer<vtkImageData> mask =
            DICOMLoaderVTK::loadDICOMSeries( std::string( argv[2] ) );

    vtkSmartPointer<vtkImageData> groundTruth =
            DICOMLoaderVTK::loadDICOMSeries( std::string( argv[3] ) );

    int* dim = mask->GetDimensions();

    std::cerr << "find initial contours" << std::endl;
    std::vector< std::vector<Contour> > contoursPerSclice;
    for( int i = 0; i < mask->GetDimensions()[2]; ++i )
    {
        vtkSmartPointer<vtkExtractVOI> voiExtractor =
                vtkSmartPointer<vtkExtractVOI>::New();
        voiExtractor->SetInputData( mask );
        voiExtractor->SetVOI( 0, dim[0]-1, 0, dim[1]-1, i, i );
        voiExtractor->Update();
        voiExtractor->GetOutput()->SetExtent( 0, dim[0]-1, 0, dim[1]-1, 0, 0 );

        std::vector<Contour> contoursInSlice = ContourFromMask::computeWithEdgeFilter( voiExtractor->GetOutput(), 0 );
        std::cout << "found contours " << contoursInSlice.size() << " in slice " << mask->GetDimensions()[2]-i << std::endl;
        for( size_t j = 0; j < contoursInSlice.size(); ++j )
        {
            // if number of points is small enough, don't simplify
            if( contoursInSlice[j].size() < nPoints )
                continue;

            contoursInSlice[j] = ContourFromMask::simplify( contoursInSlice[j], simplficationEps );
            contoursInSlice[j] = ContourFromMask::resample( contoursInSlice[j], nPoints );
        }
        if( contoursInSlice.size() > 3 )
            std::cerr << "contours found in slice bigger than 3: " << contoursInSlice.size() << " in slice " << i << std::endl;
        contoursPerSclice.push_back( contoursInSlice );
    }

    std::cerr << "initalizing contour algorithm" << std::endl;
    std::cerr << "mask dimension: " << dim[0] << " " << dim[1] << " " << dim[2] << std::endl;
    // initialize all algorithms
    std::vector<std::vector<ActiveContour> > activeContourAlgorithms( contoursPerSclice.size() );
    for( size_t i = 0; i < contoursPerSclice.size(); ++i )
    {
        vtkSmartPointer<vtkExtractVOI> voiExtractor =
                vtkSmartPointer<vtkExtractVOI>::New();
        voiExtractor->SetInputData( image );
        voiExtractor->SetVOI( 0, dim[0]-1, 0, dim[1]-1, i, i );
        voiExtractor->Update();
        voiExtractor->GetOutput()->SetExtent( 0, dim[0]-1, 0, dim[1]-1, 0, 0 );

        activeContourAlgorithms[i].resize( contoursPerSclice[i].size() );
        for( size_t j = 0; j < contoursPerSclice[i].size(); ++j )
        {
            ActiveContour& activeContour = activeContourAlgorithms[i][j];
            activeContour.setMaxIterations( iterations );
            activeContour.setElasticity( elasticity );
            activeContour.setStiffness( stiffness );
            activeContour.setIterationSpeed( speed );
            activeContour.setEdgeSoothingSigma( smoothingSigma );
            activeContour.setStartPoints( contoursPerSclice[i][j] );

            activeContour.setImage( voiExtractor->GetOutput() );
        }
    }

    std::cerr << "optimizing contours" << std::endl;
    // fit curves:
    std::vector< std::vector<Contour> > finalContoursPerSclice( contoursPerSclice.size() );
    for( size_t i = 0; i < activeContourAlgorithms.size(); ++i )
    {
        finalContoursPerSclice[i].resize( activeContourAlgorithms[i].size() );
        for( size_t j = 0; j < activeContourAlgorithms[i].size(); ++j )
        {
             finalContoursPerSclice[i][j] = activeContourAlgorithms[i][j].compute();
        }
    }

    std::cerr << "converting contours to masks and saving" << std::endl;
    std::vector<cv::Mat3b> masksSlicewise;
    // covert curves to masks
    for( size_t i = 0; i < finalContoursPerSclice.size(); ++i )
    {
        cv::Mat3b sliceMask( dim[1], dim[0], cv::Vec3b( 0, 0, 0 ) );
        for( size_t j = 0; j < finalContoursPerSclice[i].size(); ++j )
        {
            cv::Mat3b mask = ContourToMask::compute( finalContoursPerSclice[i][j], dim );
            cv::add( sliceMask, mask, sliceMask );
        }
        std::stringstream ss;
        ss << "mask" << std::setfill('0') << std::setw(2) << finalContoursPerSclice.size()- i << ".jpg";
        cv::imwrite( ss.str(), sliceMask );
        masksSlicewise.push_back( sliceMask );
    }

    std::cerr << "computing validation" << std::endl;
    double diceCoeffOptimized =
            Validator::diceCoeff3DVolume( ContourToMask::computeITK( finalContoursPerSclice, mask->GetDimensions() ),
                                          Converter::ConvertVTKToITK<MaskType>( groundTruth ) );
    double diceCoeffBefore =
            Validator::diceCoeff3DVolume( Converter::ConvertVTKToITK<MaskType>( mask ),
                                          Converter::ConvertVTKToITK<MaskType>( groundTruth ) );

    std::cerr << "diceCoeff before optimization: " << diceCoeffBefore << std::endl;
    std::cerr << "diceCoeff after optimization: " << diceCoeffOptimized << std::endl;

}
<commit_msg>added filters to fit3D executable<commit_after>#include "fileHelpers/DICOMLoaderVTK.h"
#include "ContourFromMask.h"
#include "ActiveContour.h"
#include "ContourToMask.h"
#include "Helpers/Validator.h"
#include "Helpers/Converter.h"
#include "BiasCorrection.h"
#include "Denoising.h"

#include <vtkExtractVOI.h>

#include <opencv2/highgui.hpp>
#include <vtkRenderer.h>

int main( int argc, char** argv )
{
    if( argc < 4 )
    {
        std::cerr << "usage: " << argv[0] << " [pathToDatasetImage] [pathToMaskImage] [pathToGroundTruth]" << std::endl;
        return -1;
    }

    int nPoints = 500;
    double simplficationEps = 1;
    double elasticity = 10;
    double stiffness = 500;
    double speed = 0.2;
    double smoothingSigma = 2;
    double iterations = 130;

    std::cerr << "load data" << argv[1] << std::endl;
    vtkSmartPointer<vtkImageData> image =
            DICOMLoaderVTK::loadDICOMSeries( std::string( argv[1] ) );

    vtkSmartPointer<vtkImageData> mask =
            DICOMLoaderVTK::loadDICOMSeries( std::string( argv[2] ) );

    vtkSmartPointer<vtkImageData> groundTruth =
            DICOMLoaderVTK::loadDICOMSeries( std::string( argv[3] ) );

    int* dim = mask->GetDimensions();

    //image = BiasCorrection::shadingFilter( image, mask, 2, true, 500, 500 );
    ImageType::Pointer itkImg = Converter::ConvertVTKToITK<ImageType>( image );
    itkImg =Denoising::bilateralFilterTemplate<ImageType>( itkImg, 2, 100 );
    image = Converter::ConvertITKToVTK<ImageType>( itkImg );

    std::cerr << "find initial contours" << std::endl;
    std::vector< std::vector<Contour> > contoursPerSclice;
    for( int i = 0; i < mask->GetDimensions()[2]; ++i )
    {
        vtkSmartPointer<vtkExtractVOI> voiExtractor =
                vtkSmartPointer<vtkExtractVOI>::New();
        voiExtractor->SetInputData( mask );
        voiExtractor->SetVOI( 0, dim[0]-1, 0, dim[1]-1, i, i );
        voiExtractor->Update();
        voiExtractor->GetOutput()->SetExtent( 0, dim[0]-1, 0, dim[1]-1, 0, 0 );

        std::vector<Contour> contoursInSlice = ContourFromMask::computeWithEdgeFilter( voiExtractor->GetOutput(), 0 );
        std::cout << "found contours " << contoursInSlice.size() << " in slice " << mask->GetDimensions()[2]-i << std::endl;
        for( size_t j = 0; j < contoursInSlice.size(); ++j )
        {
            // if number of points is small enough, don't simplify
            if( contoursInSlice[j].size() < nPoints )
                continue;

            contoursInSlice[j] = ContourFromMask::simplify( contoursInSlice[j], simplficationEps );
            contoursInSlice[j] = ContourFromMask::resample( contoursInSlice[j], nPoints );
        }
        if( contoursInSlice.size() > 3 )
            std::cerr << "contours found in slice bigger than 3: " << contoursInSlice.size() << " in slice " << i << std::endl;
        contoursPerSclice.push_back( contoursInSlice );
    }

    std::cerr << "initalizing contour algorithm" << std::endl;
    std::cerr << "mask dimension: " << dim[0] << " " << dim[1] << " " << dim[2] << std::endl;
    // initialize all algorithms
    std::vector<std::vector<ActiveContour> > activeContourAlgorithms( contoursPerSclice.size() );
    for( size_t i = 0; i < contoursPerSclice.size(); ++i )
    {
        vtkSmartPointer<vtkExtractVOI> voiExtractor =
                vtkSmartPointer<vtkExtractVOI>::New();
        voiExtractor->SetInputData( image );
        voiExtractor->SetVOI( 0, dim[0]-1, 0, dim[1]-1, i, i );
        voiExtractor->Update();
        voiExtractor->GetOutput()->SetExtent( 0, dim[0]-1, 0, dim[1]-1, 0, 0 );

        activeContourAlgorithms[i].resize( contoursPerSclice[i].size() );
        for( size_t j = 0; j < contoursPerSclice[i].size(); ++j )
        {
            ActiveContour& activeContour = activeContourAlgorithms[i][j];
            activeContour.setMaxIterations( iterations );
            activeContour.setElasticity( elasticity );
            activeContour.setStiffness( stiffness );
            activeContour.setIterationSpeed( speed );
            activeContour.setEdgeSoothingSigma( smoothingSigma );
            activeContour.setStartPoints( contoursPerSclice[i][j] );

            activeContour.setImage( voiExtractor->GetOutput() );
        }
    }

    std::cerr << "optimizing contours" << std::endl;
    // fit curves:
    std::vector< std::vector<Contour> > finalContoursPerSclice( contoursPerSclice.size() );
    for( size_t i = 0; i < activeContourAlgorithms.size(); ++i )
    {
        finalContoursPerSclice[i].resize( activeContourAlgorithms[i].size() );
        for( size_t j = 0; j < activeContourAlgorithms[i].size(); ++j )
        {
             finalContoursPerSclice[i][j] = activeContourAlgorithms[i][j].compute();
        }
    }

    std::cerr << "converting contours to masks and saving" << std::endl;
    std::vector<cv::Mat3b> masksSlicewise;
    // covert curves to masks
    for( size_t i = 0; i < finalContoursPerSclice.size(); ++i )
    {
        cv::Mat3b sliceMask( dim[1], dim[0], cv::Vec3b( 0, 0, 0 ) );
        for( size_t j = 0; j < finalContoursPerSclice[i].size(); ++j )
        {
            cv::Mat3b mask = ContourToMask::compute( finalContoursPerSclice[i][j], dim );
            cv::add( sliceMask, mask, sliceMask );
        }
        std::stringstream ss;
        ss << "mask" << std::setfill('0') << std::setw(2) << finalContoursPerSclice.size()- i << ".jpg";
        cv::imwrite( ss.str(), sliceMask );
        masksSlicewise.push_back( sliceMask );
    }

    std::cerr << "computing validation" << std::endl;
    double diceCoeffOptimized =
            Validator::diceCoeff3DVolume( ContourToMask::computeITK( finalContoursPerSclice, mask->GetDimensions() ),
                                          Converter::ConvertVTKToITK<MaskType>( groundTruth ) );
    double diceCoeffBefore =
            Validator::diceCoeff3DVolume( Converter::ConvertVTKToITK<MaskType>( mask ),
                                          Converter::ConvertVTKToITK<MaskType>( groundTruth ) );

    std::cerr << "diceCoeff before optimization: " << diceCoeffBefore << std::endl;
    std::cerr << "diceCoeff after optimization: " << diceCoeffOptimized << std::endl;

}
<|endoftext|>