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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include <vector>
#include <iostream>
#include <fstream>
#include <algorithm>

#include <itkImageFileWriter.h>
#include <itkMetaDataObject.h>
#include <itkVectorImage.h>

#include <mitkBaseData.h>
#include <mitkFiberBundle.h>
#include "mitkCommandLineParser.h"
#include <mitkLexicalCast.h>
#include <mitkCoreObjectFactory.h>
#include <mitkIOUtil.h>
#include <itkFiberCurvatureFilter.h>

mitk::FiberBundle::Pointer LoadFib(std::string filename)
{
  std::vector<mitk::BaseData::Pointer> fibInfile = mitk::IOUtil::Load(filename);
  if( fibInfile.empty() )
    std::cout << "File " << filename << " could not be read!";
  mitk::BaseData::Pointer baseData = fibInfile.at(0);
  return dynamic_cast<mitk::FiberBundle*>(baseData.GetPointer());
}

/*!
\brief Modify input tractogram: fiber resampling, compression, pruning and transformation.
*/
int main(int argc, char* argv[])
{
  mitkCommandLineParser parser;

  parser.setTitle("Fiber Processing");
  parser.setCategory("Fiber Tracking and Processing Methods");
  parser.setDescription("Modify input tractogram: fiber resampling, compression, pruning and transformation.");
  parser.setContributor("MIC");

  parser.setArgumentPrefix("--", "-");

  parser.beginGroup("1. Mandatory arguments:");
  parser.addArgument("", "i", mitkCommandLineParser::String, "Input:", "Input fiber bundle (.fib, .trk, .tck)", us::Any(), false, false, false, mitkCommandLineParser::Input);
  parser.addArgument("", "o", mitkCommandLineParser::String, "Output:", "Output fiber bundle (.fib, .trk)", us::Any(), false, false, false, mitkCommandLineParser::Output);
  parser.endGroup();

  parser.beginGroup("2. Resampling:");
  parser.addArgument("spline_resampling", "", mitkCommandLineParser::Float, "Spline resampling:", "Resample fiber using splines with the given point distance (in mm)");
  parser.addArgument("linear_resampling", "", mitkCommandLineParser::Float, "Linear resampling:", "Resample fiber linearly with the given point distance (in mm)");
  parser.addArgument("num_resampling", "", mitkCommandLineParser::Int, "Num. fiber points resampling:", "Resample all fibers to the given number of points");
  parser.addArgument("compress", "", mitkCommandLineParser::Float, "Compress:", "Compress fiber using the given error threshold (in mm)");
  parser.endGroup();

  parser.beginGroup("3. Filtering:");
  parser.addArgument("min_length", "", mitkCommandLineParser::Float, "Minimum length:", "Minimum fiber length (in mm)");
  parser.addArgument("max_length", "", mitkCommandLineParser::Float, "Maximum length:", "Maximum fiber length (in mm)");
  parser.addArgument("max_angle", "", mitkCommandLineParser::Float, "Maximum angle:", "Maximum angular STDEV (in degree) over given distance");
  parser.addArgument("max_angle_dist", "", mitkCommandLineParser::Float, "Distance:", "Distance in mm", 10);
  parser.addArgument("remove", "", mitkCommandLineParser::Bool, "Remove fibers exceeding curvature threshold:", "If false, only the high curvature parts are removed");
  parser.addArgument("subsample", "", mitkCommandLineParser::Float, "Randomly select fraction of streamlines:", "Randomly select the specified fraction of streamlines from the input tractogram");
  parser.addArgument("random_subsample", "", mitkCommandLineParser::Bool, "Randomly seed subsampling:", "Randomly seed subsampling. Else, use seed 0.");
  parser.endGroup();

  parser.beginGroup("4. Transformation:");
  parser.addArgument("mirror", "", mitkCommandLineParser::Int, "Invert coordinates:", "Invert fiber coordinates XYZ (e.g. 010 to invert y-coordinate of each fiber point)");

  parser.addArgument("rotate_x", "", mitkCommandLineParser::Float, "Rotate x-axis:", "Rotate around x-axis (in deg)");
  parser.addArgument("rotate_y", "", mitkCommandLineParser::Float, "Rotate y-axis:", "Rotate around y-axis (in deg)");
  parser.addArgument("rotate_z", "", mitkCommandLineParser::Float, "Rotate z-axis:", "Rotate around z-axis (in deg)");

  parser.addArgument("scale_x", "", mitkCommandLineParser::Float, "Scale x-axis:", "Scale in direction of x-axis");
  parser.addArgument("scale_y", "", mitkCommandLineParser::Float, "Scale y-axis:", "Scale in direction of y-axis");
  parser.addArgument("scale_z", "", mitkCommandLineParser::Float, "Scale z-axis", "Scale in direction of z-axis");

  parser.addArgument("translate_x", "", mitkCommandLineParser::Float, "Translate x-axis:", "Translate in direction of x-axis (in mm)");
  parser.addArgument("translate_y", "", mitkCommandLineParser::Float, "Translate y-axis:", "Translate in direction of y-axis (in mm)");
  parser.addArgument("translate_z", "", mitkCommandLineParser::Float, "Translate z-axis:", "Translate in direction of z-axis (in mm)");
  parser.endGroup();

  std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
  if (parsedArgs.size()==0)
    return EXIT_FAILURE;

  bool remove = false;
  if (parsedArgs.count("remove"))
    remove = us::any_cast<bool>(parsedArgs["remove"]);

  bool random_subsample = false;
  if (parsedArgs.count("random_subsample"))
    random_subsample = us::any_cast<bool>(parsedArgs["random_subsample"]);

  float spline_resampling = -1;
  if (parsedArgs.count("spline_resampling"))
    spline_resampling = us::any_cast<float>(parsedArgs["spline_resampling"]);

  float linear_resampling = -1;
  if (parsedArgs.count("linear_resampling"))
    linear_resampling = us::any_cast<float>(parsedArgs["linear_resampling"]);

  int num_resampling = -1;
  if (parsedArgs.count("num_resampling"))
    num_resampling = us::any_cast<int>(parsedArgs["num_resampling"]);

  float subsample = -1;
  if (parsedArgs.count("subsample"))
    subsample = us::any_cast<float>(parsedArgs["subsample"]);

  float compress = -1;
  if (parsedArgs.count("compress"))
    compress = us::any_cast<float>(parsedArgs["compress"]);

  float minFiberLength = -1;
  if (parsedArgs.count("min_length"))
    minFiberLength = us::any_cast<float>(parsedArgs["min_length"]);

  float maxFiberLength = -1;
  if (parsedArgs.count("max_length"))
    maxFiberLength = us::any_cast<float>(parsedArgs["max_length"]);

  float max_angle_dist = 10;
  if (parsedArgs.count("max_angle_dist"))
    max_angle_dist = us::any_cast<float>(parsedArgs["max_angle_dist"]);

  float maxAngularDev = -1;
  if (parsedArgs.count("max_angle"))
    maxAngularDev = us::any_cast<float>(parsedArgs["max_angle"]);

  int axis = 0;
  if (parsedArgs.count("mirror"))
    axis = us::any_cast<int>(parsedArgs["mirror"]);

  float rotateX = 0;
  if (parsedArgs.count("rotate_x"))
    rotateX = us::any_cast<float>(parsedArgs["rotate_x"]);

  float rotateY = 0;
  if (parsedArgs.count("rotate_y"))
    rotateY = us::any_cast<float>(parsedArgs["rotate_y"]);

  float rotateZ = 0;
  if (parsedArgs.count("rotate_z"))
    rotateZ = us::any_cast<float>(parsedArgs["rotate_z"]);

  float scaleX = 0;
  if (parsedArgs.count("scale_x"))
    scaleX = us::any_cast<float>(parsedArgs["scale_x"]);

  float scaleY = 0;
  if (parsedArgs.count("scale_y"))
    scaleY = us::any_cast<float>(parsedArgs["scale_y"]);

  float scaleZ = 0;
  if (parsedArgs.count("scale_z"))
    scaleZ = us::any_cast<float>(parsedArgs["scale_z"]);

  float translateX = 0;
  if (parsedArgs.count("translate_x"))
    translateX = us::any_cast<float>(parsedArgs["translate_x"]);

  float translateY = 0;
  if (parsedArgs.count("translate_y"))
    translateY = us::any_cast<float>(parsedArgs["translate_y"]);

  float translateZ = 0;
  if (parsedArgs.count("translate_z"))
    translateZ = us::any_cast<float>(parsedArgs["translate_z"]);

  std::string inFileName = us::any_cast<std::string>(parsedArgs["i"]);
  std::string outFileName = us::any_cast<std::string>(parsedArgs["o"]);

  try
  {
    mitk::FiberBundle::Pointer fib = LoadFib(inFileName);

    if (subsample>0)
      fib = fib->SubsampleFibers(subsample, random_subsample);

    if (maxAngularDev>0)
    {
      auto filter = itk::FiberCurvatureFilter::New();
      filter->SetInputFiberBundle(fib);
      filter->SetAngularDeviation(maxAngularDev);
      filter->SetDistance(max_angle_dist);
      filter->SetRemoveFibers(remove);
      filter->Update();
      fib = filter->GetOutputFiberBundle();
    }

    if (minFiberLength>0)
      fib->RemoveShortFibers(minFiberLength);

    if (maxFiberLength>0)
      fib->RemoveLongFibers(maxFiberLength);

    if (spline_resampling>0)
      fib->ResampleSpline(spline_resampling);

    if (linear_resampling>0)
      fib->ResampleLinear(linear_resampling);

    if (num_resampling>0)
      fib->ResampleToNumPoints(num_resampling);

    if (compress>0)
      fib->Compress(compress);

    if (axis/100==1)
      fib->MirrorFibers(0);

    if ((axis%100)/10==1)
      fib->MirrorFibers(1);

    if (axis%10==1)
      fib->MirrorFibers(2);

    if (rotateX > 0 || rotateY > 0 || rotateZ > 0){
      std::cout << "Rotate " << rotateX << " " << rotateY << " " << rotateZ;
      fib->RotateAroundAxis(rotateX, rotateY, rotateZ);
    }
    if (translateX > 0 || translateY > 0 || translateZ > 0){
      fib->TranslateFibers(translateX, translateY, translateZ);
    }
    if (scaleX > 0 || scaleY > 0 || scaleZ > 0)
      fib->ScaleFibers(scaleX, scaleY, scaleZ);

    mitk::IOUtil::Save(fib.GetPointer(), outFileName );

  }
  catch (itk::ExceptionObject e)
  {
    std::cout << e;
    return EXIT_FAILURE;
  }
  catch (std::exception e)
  {
    std::cout << e.what();
    return EXIT_FAILURE;
  }
  catch (...)
  {
    std::cout << "ERROR!?!";
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;
}
<commit_msg>Fiber cutting<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include <vector>
#include <iostream>
#include <fstream>
#include <algorithm>

#include <itkImageFileWriter.h>
#include <itkMetaDataObject.h>
#include <itkVectorImage.h>

#include <mitkBaseData.h>
#include <mitkFiberBundle.h>
#include "mitkCommandLineParser.h"
#include <mitkLexicalCast.h>
#include <mitkCoreObjectFactory.h>
#include <mitkIOUtil.h>
#include <itkFiberCurvatureFilter.h>
#include <mitkDiffusionDataIOHelper.h>
#include <itkImage.h>

mitk::FiberBundle::Pointer LoadFib(std::string filename)
{
  std::vector<mitk::BaseData::Pointer> fibInfile = mitk::IOUtil::Load(filename);
  if( fibInfile.empty() )
    std::cout << "File " << filename << " could not be read!";
  mitk::BaseData::Pointer baseData = fibInfile.at(0);
  return dynamic_cast<mitk::FiberBundle*>(baseData.GetPointer());
}

/*!
\brief Modify input tractogram: fiber resampling, compression, pruning and transformation.
*/
int main(int argc, char* argv[])
{
  mitkCommandLineParser parser;

  parser.setTitle("Fiber Processing");
  parser.setCategory("Fiber Tracking and Processing Methods");
  parser.setDescription("Modify input tractogram: fiber resampling, compression, pruning and transformation.");
  parser.setContributor("MIC");

  parser.setArgumentPrefix("--", "-");

  parser.beginGroup("1. Mandatory arguments:");
  parser.addArgument("", "i", mitkCommandLineParser::String, "Input:", "Input fiber bundle (.fib, .trk, .tck)", us::Any(), false, false, false, mitkCommandLineParser::Input);
  parser.addArgument("", "o", mitkCommandLineParser::String, "Output:", "Output fiber bundle (.fib, .trk)", us::Any(), false, false, false, mitkCommandLineParser::Output);
  parser.endGroup();

  parser.beginGroup("2. Resampling:");
  parser.addArgument("spline_resampling", "", mitkCommandLineParser::Float, "Spline resampling:", "Resample fiber using splines with the given point distance (in mm)");
  parser.addArgument("linear_resampling", "", mitkCommandLineParser::Float, "Linear resampling:", "Resample fiber linearly with the given point distance (in mm)");
  parser.addArgument("num_resampling", "", mitkCommandLineParser::Int, "Num. fiber points resampling:", "Resample all fibers to the given number of points");
  parser.addArgument("compress", "", mitkCommandLineParser::Float, "Compress:", "Compress fiber using the given error threshold (in mm)");
  parser.endGroup();

  parser.beginGroup("3. Filtering:");
  parser.addArgument("min_length", "", mitkCommandLineParser::Float, "Minimum length:", "Minimum fiber length (in mm)");
  parser.addArgument("max_length", "", mitkCommandLineParser::Float, "Maximum length:", "Maximum fiber length (in mm)");
  parser.addArgument("max_angle", "", mitkCommandLineParser::Float, "Maximum angle:", "Maximum angular STDEV (in degree) over given distance");
  parser.addArgument("max_angle_dist", "", mitkCommandLineParser::Float, "Distance:", "Distance in mm", 10);
  parser.addArgument("remove", "", mitkCommandLineParser::Bool, "Remove fibers exceeding curvature threshold:", "If false, only the high curvature parts are removed");
  parser.addArgument("subsample", "", mitkCommandLineParser::Float, "Randomly select fraction of streamlines:", "Randomly select the specified fraction of streamlines from the input tractogram");
  parser.addArgument("random_subsample", "", mitkCommandLineParser::Bool, "Randomly seed subsampling:", "Randomly seed subsampling. Else, use seed 0.");
  parser.endGroup();

  parser.beginGroup("4. Transformation:");
  parser.addArgument("mirror", "", mitkCommandLineParser::Int, "Invert coordinates:", "Invert fiber coordinates XYZ (e.g. 010 to invert y-coordinate of each fiber point)");

  parser.addArgument("rotate_x", "", mitkCommandLineParser::Float, "Rotate x-axis:", "Rotate around x-axis (in deg)");
  parser.addArgument("rotate_y", "", mitkCommandLineParser::Float, "Rotate y-axis:", "Rotate around y-axis (in deg)");
  parser.addArgument("rotate_z", "", mitkCommandLineParser::Float, "Rotate z-axis:", "Rotate around z-axis (in deg)");

  parser.addArgument("scale_x", "", mitkCommandLineParser::Float, "Scale x-axis:", "Scale in direction of x-axis");
  parser.addArgument("scale_y", "", mitkCommandLineParser::Float, "Scale y-axis:", "Scale in direction of y-axis");
  parser.addArgument("scale_z", "", mitkCommandLineParser::Float, "Scale z-axis", "Scale in direction of z-axis");

  parser.addArgument("translate_x", "", mitkCommandLineParser::Float, "Translate x-axis:", "Translate in direction of x-axis (in mm)");
  parser.addArgument("translate_y", "", mitkCommandLineParser::Float, "Translate y-axis:", "Translate in direction of y-axis (in mm)");
  parser.addArgument("translate_z", "", mitkCommandLineParser::Float, "Translate z-axis:", "Translate in direction of z-axis (in mm)");

  parser.endGroup();

  parser.beginGroup("5. Remove fiber parts:");
  parser.addArgument("remove_inside", "", mitkCommandLineParser::Bool, "Remove fibers inside mask:", "remove fibers inside mask");
  parser.addArgument("remove_outside", "", mitkCommandLineParser::Bool, "Remove fibers outside mask:", "remove fibers outside mask");
  parser.addArgument("mask", "", mitkCommandLineParser::String, "Mask image:", "mask image", us::Any(), true, false, false, mitkCommandLineParser::Input);
  parser.endGroup();

  std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
  if (parsedArgs.size()==0)
    return EXIT_FAILURE;

  bool remove_outside = false;
  if (parsedArgs.count("remove_outside"))
    remove_outside = us::any_cast<bool>(parsedArgs["remove_outside"]);

  bool remove_inside = false;
  if (!remove_outside && parsedArgs.count("remove_inside"))
    remove_inside = us::any_cast<bool>(parsedArgs["remove_inside"]);

  typedef itk::Image< unsigned char, 3 > UcharImageType;
  UcharImageType::Pointer mask = nullptr;
  if (remove_inside || remove_outside)
  {
    if (parsedArgs.count("mask"))
      mask = mitk::DiffusionDataIOHelper::load_itk_image< UcharImageType >(us::any_cast<std::string>(parsedArgs["mask"]));
    else {
      MITK_INFO << "Mask needed to remove fibers inside or outside mask!";
      return EXIT_FAILURE;
    }
  }

  bool remove = false;
  if (parsedArgs.count("remove"))
    remove = us::any_cast<bool>(parsedArgs["remove"]);

  bool random_subsample = false;
  if (parsedArgs.count("random_subsample"))
    random_subsample = us::any_cast<bool>(parsedArgs["random_subsample"]);

  float spline_resampling = -1;
  if (parsedArgs.count("spline_resampling"))
    spline_resampling = us::any_cast<float>(parsedArgs["spline_resampling"]);

  float linear_resampling = -1;
  if (parsedArgs.count("linear_resampling"))
    linear_resampling = us::any_cast<float>(parsedArgs["linear_resampling"]);

  int num_resampling = -1;
  if (parsedArgs.count("num_resampling"))
    num_resampling = us::any_cast<int>(parsedArgs["num_resampling"]);

  float subsample = -1;
  if (parsedArgs.count("subsample"))
    subsample = us::any_cast<float>(parsedArgs["subsample"]);

  float compress = -1;
  if (parsedArgs.count("compress"))
    compress = us::any_cast<float>(parsedArgs["compress"]);

  float minFiberLength = -1;
  if (parsedArgs.count("min_length"))
    minFiberLength = us::any_cast<float>(parsedArgs["min_length"]);

  float maxFiberLength = -1;
  if (parsedArgs.count("max_length"))
    maxFiberLength = us::any_cast<float>(parsedArgs["max_length"]);

  float max_angle_dist = 10;
  if (parsedArgs.count("max_angle_dist"))
    max_angle_dist = us::any_cast<float>(parsedArgs["max_angle_dist"]);

  float maxAngularDev = -1;
  if (parsedArgs.count("max_angle"))
    maxAngularDev = us::any_cast<float>(parsedArgs["max_angle"]);

  int axis = 0;
  if (parsedArgs.count("mirror"))
    axis = us::any_cast<int>(parsedArgs["mirror"]);

  float rotateX = 0;
  if (parsedArgs.count("rotate_x"))
    rotateX = us::any_cast<float>(parsedArgs["rotate_x"]);

  float rotateY = 0;
  if (parsedArgs.count("rotate_y"))
    rotateY = us::any_cast<float>(parsedArgs["rotate_y"]);

  float rotateZ = 0;
  if (parsedArgs.count("rotate_z"))
    rotateZ = us::any_cast<float>(parsedArgs["rotate_z"]);

  float scaleX = 0;
  if (parsedArgs.count("scale_x"))
    scaleX = us::any_cast<float>(parsedArgs["scale_x"]);

  float scaleY = 0;
  if (parsedArgs.count("scale_y"))
    scaleY = us::any_cast<float>(parsedArgs["scale_y"]);

  float scaleZ = 0;
  if (parsedArgs.count("scale_z"))
    scaleZ = us::any_cast<float>(parsedArgs["scale_z"]);

  float translateX = 0;
  if (parsedArgs.count("translate_x"))
    translateX = us::any_cast<float>(parsedArgs["translate_x"]);

  float translateY = 0;
  if (parsedArgs.count("translate_y"))
    translateY = us::any_cast<float>(parsedArgs["translate_y"]);

  float translateZ = 0;
  if (parsedArgs.count("translate_z"))
    translateZ = us::any_cast<float>(parsedArgs["translate_z"]);

  std::string inFileName = us::any_cast<std::string>(parsedArgs["i"]);
  std::string outFileName = us::any_cast<std::string>(parsedArgs["o"]);

  try
  {
    mitk::FiberBundle::Pointer fib = LoadFib(inFileName);

    if (subsample>0)
      fib = fib->SubsampleFibers(subsample, random_subsample);

    if (maxAngularDev>0)
    {
      auto filter = itk::FiberCurvatureFilter::New();
      filter->SetInputFiberBundle(fib);
      filter->SetAngularDeviation(maxAngularDev);
      filter->SetDistance(max_angle_dist);
      filter->SetRemoveFibers(remove);
      filter->Update();
      fib = filter->GetOutputFiberBundle();
    }

    if (minFiberLength>0)
      fib->RemoveShortFibers(minFiberLength);

    if (maxFiberLength>0)
      fib->RemoveLongFibers(maxFiberLength);

    if (spline_resampling>0)
      fib->ResampleSpline(spline_resampling);

    if (linear_resampling>0)
      fib->ResampleLinear(linear_resampling);

    if (num_resampling>0)
      fib->ResampleToNumPoints(num_resampling);

    if (compress>0)
      fib->Compress(compress);

    if ( mask.IsNotNull() )
    {
      if (remove_outside)
        fib = fib->RemoveFibersOutside(mask, false);
      else if (remove_inside)
        fib = fib->RemoveFibersOutside(mask, true);
    }

    if (axis/100==1)
      fib->MirrorFibers(0);

    if ((axis%100)/10==1)
      fib->MirrorFibers(1);

    if (axis%10==1)
      fib->MirrorFibers(2);

    if (rotateX > 0 || rotateY > 0 || rotateZ > 0){
      std::cout << "Rotate " << rotateX << " " << rotateY << " " << rotateZ;
      fib->RotateAroundAxis(rotateX, rotateY, rotateZ);
    }
    if (translateX > 0 || translateY > 0 || translateZ > 0){
      fib->TranslateFibers(translateX, translateY, translateZ);
    }
    if (scaleX > 0 || scaleY > 0 || scaleZ > 0)
      fib->ScaleFibers(scaleX, scaleY, scaleZ);

    mitk::IOUtil::Save(fib.GetPointer(), outFileName );

  }
  catch (itk::ExceptionObject e)
  {
    std::cout << e;
    return EXIT_FAILURE;
  }
  catch (std::exception e)
  {
    std::cout << e.what();
    return EXIT_FAILURE;
  }
  catch (...)
  {
    std::cout << "ERROR!?!";
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>AliAnalysisTaskSEpPbCorrelationsJetV2Kine_dev *AddTaskSEpPbCorrelationsJetV2Kine(TString sMode = "TPCTPCFMDA")
{
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    ::Error("AddTaskKineAmpt.C::AddTaskKineAmpt", "No analysis manager to connect to");
    return nullptr;
  }
//=============================================================================

  AliAnalysisTaskSEpPbCorrelationsJetV2Kine_dev *task = new AliAnalysisTaskSEpPbCorrelationsJetV2Kine_dev("AliAnalysisTaskSEpPbCorrelationsJetV2Kine_dev");

  Double_t trigPtLimits[] = {0.5, 1.0, 1.5, 2.0, 3.0, 5.0, 8.0};
  const Int_t nBinTrigPt = sizeof(trigPtLimits) / sizeof(Double_t) - 1;
  task->SetTrigPtBinning(nBinTrigPt, trigPtLimits);

  Double_t assocPtLimits[] = {0.5, 1., 1.5, 50.};
  const Int_t nBinAssocPt = sizeof(assocPtLimits) / sizeof(Double_t) - 1;
  task->SetAssocPtBinning(nBinAssocPt, assocPtLimits);

  task->SetAnaMode(sMode);
  task->SetAssoCut(1.0);

  task->SetPtMin(0.5);
  task->SetPtMax(50.);

  task->SetCen1(0);
  task->SetCen2(10);

  // Input File
  TGrid::Connect("alien://");
  TFile *file = TFile::Open("alien:///alice/cern.ch/user/s/sitang/AMPT_Centrality_Calibration/Centrality.root");

  //TFile *file = TFile::Open("./Centrality/Centrality.root");
  TH1D *h_Charge  = (TH1D*)file->Get("hChargeV0A"); h_Charge->SetDirectory(0);
  file->Close();

  // create input container
  AliAnalysisDataContainer *cinput1 = mgr->CreateContainer("h_centrality",
                                    TH1D::Class(),
                                    AliAnalysisManager::kInputContainer);
  cinput1->SetData(h_Charge);

  mgr->AddTask(task);
  mgr->ConnectInput (task, 0, mgr->GetCommonInputContainer());
  mgr->ConnectInput(task, 1, cinput1);
  mgr->ConnectOutput(task, 1, mgr->CreateContainer(Form("listKineAmpt_%s",sMode.Data()),
                                                   TList::Class(),
                                                   AliAnalysisManager::kOutputContainer,
                                                   AliAnalysisManager::GetCommonFileName()));
//=============================================================================

  return task;
}
<commit_msg>Update Jet particle v2 MC<commit_after>AliAnalysisTaskSEpPbCorrelationsJetV2Kine *AddTaskSEpPbCorrelationsJetV2Kine(TString sMode = "TPCTPCFMDA")
{
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    ::Error("AddTaskKineAmpt.C::AddTaskKineAmpt", "No analysis manager to connect to");
    return nullptr;
  }
//=============================================================================

  AliAnalysisTaskSEpPbCorrelationsJetV2Kine *task = new AliAnalysisTaskSEpPbCorrelationsJetV2Kine("AliAnalysisTaskSEpPbCorrelationsJetV2Kine");

  Double_t trigPtLimits[] = {0.5, 1.0, 1.5, 2.0, 3.0, 5.0, 8.0};
  const Int_t nBinTrigPt = sizeof(trigPtLimits) / sizeof(Double_t) - 1;
  task->SetTrigPtBinning(nBinTrigPt, trigPtLimits);

  Double_t assocPtLimits[] = {0.5, 1., 1.5, 50.};
  const Int_t nBinAssocPt = sizeof(assocPtLimits) / sizeof(Double_t) - 1;
  task->SetAssocPtBinning(nBinAssocPt, assocPtLimits);

  task->SetAnaMode(sMode);
  task->SetAssoCut(1.0);

  task->SetPtMin(0.5);
  task->SetPtMax(50.);

  task->SetCen1(0);
  task->SetCen2(10);

  // Input File
  TGrid::Connect("alien://");
  TFile *file = TFile::Open("alien:///alice/cern.ch/user/s/sitang/AMPT_Centrality_Calibration/Centrality.root");

  //TFile *file = TFile::Open("./Centrality/Centrality.root");
  TH1D *h_Charge  = (TH1D*)file->Get("hChargeV0A"); h_Charge->SetDirectory(0);
  file->Close();

  // create input container
  AliAnalysisDataContainer *cinput1 = mgr->CreateContainer("h_centrality",
                                    TH1D::Class(),
                                    AliAnalysisManager::kInputContainer);
  cinput1->SetData(h_Charge);

  mgr->AddTask(task);
  mgr->ConnectInput (task, 0, mgr->GetCommonInputContainer());
  mgr->ConnectInput(task, 1, cinput1);
  mgr->ConnectOutput(task, 1, mgr->CreateContainer(Form("listKineAmpt_%s",sMode.Data()),
                                                   TList::Class(),
                                                   AliAnalysisManager::kOutputContainer,
                                                   AliAnalysisManager::GetCommonFileName()));
//=============================================================================

  return task;
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------------------------
// File: LineFollower.cpp
// Project: LG Exec Ed Program
// Versions:
// 1.0 April 2017 - initial version
// Main line follower Program. This is the main program follows a line.
// To invoke LineFollower <hostname> <port>. This program will send the processed camera image
// via UDP to the RecvImage_UDP program that will display the image
//
// Use the following keys
// r key - run mode (starts the robot following the line
// s key - disables run mode and stops the robot
// j key - moves the camera pan servo left
// l key - moves the camera pan servo right
// i key - moves the camera tilt servo up
// m key - moves the camera tilt servo down
// k key - moves the camera pan and tilt servos to center
// q key - descreases the speed of the robot (manual control only both wheels move at the same speed)
// w key - stops the robot (manual control only)
// e key - increases the speed of the robot (manual control only both wheels move at the same speed)
//----------------------------------------------------------------------------------------------
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <math.h>
#include <stdio.h>
#include <signal.h>
#include <iostream>

#include "ImageProcessing.h"
#include "PI3OpencvCompat.h"
#include "PID.h"
#include "Servos.h"
#include "NetworkUDP.h"
#include "UdpSendJpeg.h"
#include "UdpSendMap.h"
#include "KeyboardSetup.h"

#ifndef UBUNTU		// For building in ubuntu. Below code sould be built in raspberry pi.
#include <wiringPi.h>
#endif //UBUNTU

#include "sensor_manager.h"
#include "servos_manager.h"

#define INIT 0
#define STOP 1
#define FOWARD 2
#define LEFT 3
#define RIGHT 4

using namespace cv;
using namespace std;

#define WIDTH 640
#define HEIGHT 480

static int            AWidth;
static int            AHeight;
static int            Pan;
static int            Tilt;
static CvCapture *    capture=NULL;
static UdpSendJpeg    VideoSender;
static UdpSendMap	  MapSender;
static TPID           PID;
static int           Run=INIT;

float	   offset;		   // computed robot deviation from the line

static void  Setup_Control_C_Signal_Handler_And_Keyboard_No_Enter(void);
static void  CleanUp(void);
static void  Control_C_Handler(int s);
static void  HandleInputChar(void);

//----------------------------------------------------------------
// main - This is the main program for the line follower and
// contains the control loop
//-----------------------------------------------------------------
int main(int argc, const char** argv)
{
  IplImage * iplCameraImage; // camera image in IplImage format
  Mat        image;          // camera image in Mat format

   if (argc !=3) {
       fprintf(stderr,"usage %s hostname port\n", argv[0]);
       exit(0);
    }

  Setup_Control_C_Signal_Handler_And_Keyboard_No_Enter(); // Set Control-c handler to properly exit cleanly

  if (VideoSender.OpenUdp(argv[1],argv[2]) == 0) // Setup remote network destination to send images
  {
	  printf("VideoSender.OpenUdp Failed\n");
	  CleanUp();
	  return(-1);
  }

  if (MapSender.OpenUdp(argv[1], "30002") == 0) // Setup remote network destination to send images
  {
	  printf("MapSender.OpenUdp Failed\n");
	  CleanUp();
	  return(-1);
  }

  printf("cvCreateCameraCapture()\n");

  capture =cvCreateCameraCapture(0);   // Open default Camera
    if(!capture)
      {
        printf("Camera Not Initialized\n");
        CleanUp();
        return 0;
      }

  if (cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH,WIDTH)==0) // Set camera width
    {
      printf("cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH,WIDTH) Failed)\n");
    }

 if (cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT,HEIGHT)==0) // Set camera height
    {
      printf("cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT,HEIGHT) Failed)\n");
    }

  AWidth=cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  AHeight=cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  printf("Width = %d\n",AWidth );
  printf("Height = %d\n", AHeight);

  if (!IsPi3) namedWindow( "camera", CV_WINDOW_AUTOSIZE ); // If not running on PI3 open local Window

 //if (!IsPi3) namedWindow( "processed", CV_WINDOW_AUTOSIZE );  // If not running on PI3 open local Window
  do
   {
	sensor_manager_main();
	servos_manager_main();

    iplCameraImage = cvQueryFrame(capture); // Get Camera image
    image= cv::cvarrToMat(iplCameraImage);  // Convert Camera image to Mat format
    if (IsPi3) flip(image, image,-1);       // if running on PI3 flip(-1)=180 degrees

    offset=FindLineInImageAndComputeOffset(image); // Process camera image / locat line and compute offset from line

	VideoSender.UdpSendImageAsJpeg(image);

    if (!IsPi3) imshow("camera", image );             // Show image locally if not running on PI 3
    HandleInputChar();                                // Handle Keyboard Input
    if (!IsPi3) cv::waitKey(1);                       // must be call show image locally work with imshow

  } while (1);

  return 0;
}
//-----------------------------------------------------------------
// END main
//-----------------------------------------------------------------
//----------------------------------------------------------------
// Setup_Control_C_Signal_Handler_And_Keyboard_No_Enter - This
// sets uo the Control-c Handler and put the keyboard in a mode
// where it will not
// 1. echo input
// 2. need enter hit to get a character
// 3. block waiting for input
//-----------------------------------------------------------------
static void Setup_Control_C_Signal_Handler_And_Keyboard_No_Enter(void)
{
 struct sigaction sigIntHandler;
 sigIntHandler.sa_handler = Control_C_Handler; // Setup control-c callback
 sigemptyset(&sigIntHandler.sa_mask);
 sigIntHandler.sa_flags = 0;
 sigaction(SIGINT, &sigIntHandler, NULL);
 ConfigKeyboardNoEnterBlockEcho();             // set keyboard configuration
}
//-----------------------------------------------------------------
// END Setup_Control_C_Signal_Handler_And_Keyboard_No_Enter
//-----------------------------------------------------------------
//----------------------------------------------------------------
// CleanUp - Performs cleanup processing before exiting the
// the program
//-----------------------------------------------------------------
static void CleanUp(void)
{
 RestoreKeyboard();                // restore Keyboard

  if (capture!=NULL)
      {
       cvReleaseCapture(&capture); // Close camera
       capture=NULL;
      }

 VideoSender.CloseUdp();
 MapSender.CloseUdp();
 ResetServos();                    // Reset servos to center or stopped
 CloseServos();                    // Close servo device driver
 printf("restored\n");
}
//-----------------------------------------------------------------
// END CleanUp
//-----------------------------------------------------------------
//----------------------------------------------------------------
// Control_C_Handler - called when control-c pressed
//-----------------------------------------------------------------
static void Control_C_Handler(int s)
{
 CleanUp();
 printf("Caught signal %d\n",s);
 printf("exiting\n");
 exit(1);
}
//-----------------------------------------------------------------
// END Control_C_Handler
//-----------------------------------------------------------------
//----------------------------------------------------------------
// HandleInputChar - check if keys are press and proccess keys of
// interest.
//-----------------------------------------------------------------
static void HandleInputChar(void)
{
 int ch;
 static int speed=0;
  if ((ch=getchar())==EOF)              // no key pressed return
     {
       return;
     }

	if  (ch=='w')
	{
		robot_mode_setting(ROBOT_FOWARD_MOVING,offset);
    }
	else if  (ch=='x')
    {
		robot_mode_setting(ROBOT_BACKWARD_MOVING,offset);
    }
	else if  (ch=='d')
    {
		robot_mode_setting(ROBOT_RIGHT_ROTATING,offset);
    }
	else if  (ch=='a')
    {
		robot_mode_setting(ROBOT_LEFT_ROTATING,offset);
    }
	else
	{
		robot_mode_setting(ROBOT_STOP,offset);
	}

}

//-----------------------------------------------------------------
// END HandleInputChar
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// END of File
//-----------------------------------------------------------------

<commit_msg>add map_port to command line!<commit_after>//------------------------------------------------------------------------------------------------
// File: LineFollower.cpp
// Project: LG Exec Ed Program
// Versions:
// 1.0 April 2017 - initial version
// Main line follower Program. This is the main program follows a line.
// To invoke LineFollower <hostname> <port>. This program will send the processed camera image
// via UDP to the RecvImage_UDP program that will display the image
//
// Use the following keys
// r key - run mode (starts the robot following the line
// s key - disables run mode and stops the robot
// j key - moves the camera pan servo left
// l key - moves the camera pan servo right
// i key - moves the camera tilt servo up
// m key - moves the camera tilt servo down
// k key - moves the camera pan and tilt servos to center
// q key - descreases the speed of the robot (manual control only both wheels move at the same speed)
// w key - stops the robot (manual control only)
// e key - increases the speed of the robot (manual control only both wheels move at the same speed)
//----------------------------------------------------------------------------------------------
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <math.h>
#include <stdio.h>
#include <signal.h>
#include <iostream>

#include "ImageProcessing.h"
#include "PI3OpencvCompat.h"
#include "PID.h"
#include "Servos.h"
#include "NetworkUDP.h"
#include "UdpSendJpeg.h"
#include "UdpSendMap.h"
#include "KeyboardSetup.h"

#ifndef UBUNTU		// For building in ubuntu. Below code sould be built in raspberry pi.
#include <wiringPi.h>
#endif //UBUNTU

#include "sensor_manager.h"
#include "servos_manager.h"

#define INIT 0
#define STOP 1
#define FOWARD 2
#define LEFT 3
#define RIGHT 4

using namespace cv;
using namespace std;

#define WIDTH 640
#define HEIGHT 480

static int            AWidth;
static int            AHeight;
static int            Pan;
static int            Tilt;
static CvCapture *    capture=NULL;
static UdpSendJpeg    VideoSender;
static UdpSendMap	  MapSender;
static TPID           PID;
static int           Run=INIT;

float	   offset;		   // computed robot deviation from the line

static void  Setup_Control_C_Signal_Handler_And_Keyboard_No_Enter(void);
static void  CleanUp(void);
static void  Control_C_Handler(int s);
static void  HandleInputChar(void);

//----------------------------------------------------------------
// main - This is the main program for the line follower and
// contains the control loop
//-----------------------------------------------------------------
int main(int argc, const char** argv)
{
  IplImage * iplCameraImage; // camera image in IplImage format
  Mat        image;          // camera image in Mat format

   if (argc !=4) {
       fprintf(stderr,"usage %s hostname video_port map_port\n", argv[0]);
       exit(0);
    }

  Setup_Control_C_Signal_Handler_And_Keyboard_No_Enter(); // Set Control-c handler to properly exit cleanly

  if (VideoSender.OpenUdp(argv[1],argv[2]) == 0) // Setup remote network destination to send images
  {
	  printf("VideoSender.OpenUdp Failed\n");
	  CleanUp();
	  return(-1);
  }

  if (MapSender.OpenUdp(argv[1], argv[3]) == 0) // Setup remote network destination to send images
  {
	  printf("MapSender.OpenUdp Failed\n");
	  CleanUp();
	  return(-1);
  }

  printf("cvCreateCameraCapture()\n");

  capture =cvCreateCameraCapture(0);   // Open default Camera
    if(!capture)
      {
        printf("Camera Not Initialized\n");
        CleanUp();
        return 0;
      }

  if (cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH,WIDTH)==0) // Set camera width
    {
      printf("cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH,WIDTH) Failed)\n");
    }

 if (cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT,HEIGHT)==0) // Set camera height
    {
      printf("cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT,HEIGHT) Failed)\n");
    }

  AWidth=cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  AHeight=cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  printf("Width = %d\n",AWidth );
  printf("Height = %d\n", AHeight);

  if (!IsPi3) namedWindow( "camera", CV_WINDOW_AUTOSIZE ); // If not running on PI3 open local Window

 //if (!IsPi3) namedWindow( "processed", CV_WINDOW_AUTOSIZE );  // If not running on PI3 open local Window
  do
   {
	sensor_manager_main();
	servos_manager_main();

    iplCameraImage = cvQueryFrame(capture); // Get Camera image
    image= cv::cvarrToMat(iplCameraImage);  // Convert Camera image to Mat format
    if (IsPi3) flip(image, image,-1);       // if running on PI3 flip(-1)=180 degrees

    offset=FindLineInImageAndComputeOffset(image); // Process camera image / locat line and compute offset from line

	VideoSender.UdpSendImageAsJpeg(image);

    if (!IsPi3) imshow("camera", image );             // Show image locally if not running on PI 3
    HandleInputChar();                                // Handle Keyboard Input
    if (!IsPi3) cv::waitKey(1);                       // must be call show image locally work with imshow

  } while (1);

  return 0;
}
//-----------------------------------------------------------------
// END main
//-----------------------------------------------------------------
//----------------------------------------------------------------
// Setup_Control_C_Signal_Handler_And_Keyboard_No_Enter - This
// sets uo the Control-c Handler and put the keyboard in a mode
// where it will not
// 1. echo input
// 2. need enter hit to get a character
// 3. block waiting for input
//-----------------------------------------------------------------
static void Setup_Control_C_Signal_Handler_And_Keyboard_No_Enter(void)
{
 struct sigaction sigIntHandler;
 sigIntHandler.sa_handler = Control_C_Handler; // Setup control-c callback
 sigemptyset(&sigIntHandler.sa_mask);
 sigIntHandler.sa_flags = 0;
 sigaction(SIGINT, &sigIntHandler, NULL);
 ConfigKeyboardNoEnterBlockEcho();             // set keyboard configuration
}
//-----------------------------------------------------------------
// END Setup_Control_C_Signal_Handler_And_Keyboard_No_Enter
//-----------------------------------------------------------------
//----------------------------------------------------------------
// CleanUp - Performs cleanup processing before exiting the
// the program
//-----------------------------------------------------------------
static void CleanUp(void)
{
 RestoreKeyboard();                // restore Keyboard

  if (capture!=NULL)
      {
       cvReleaseCapture(&capture); // Close camera
       capture=NULL;
      }

 VideoSender.CloseUdp();
 MapSender.CloseUdp();
 ResetServos();                    // Reset servos to center or stopped
 CloseServos();                    // Close servo device driver
 printf("restored\n");
}
//-----------------------------------------------------------------
// END CleanUp
//-----------------------------------------------------------------
//----------------------------------------------------------------
// Control_C_Handler - called when control-c pressed
//-----------------------------------------------------------------
static void Control_C_Handler(int s)
{
 CleanUp();
 printf("Caught signal %d\n",s);
 printf("exiting\n");
 exit(1);
}
//-----------------------------------------------------------------
// END Control_C_Handler
//-----------------------------------------------------------------
//----------------------------------------------------------------
// HandleInputChar - check if keys are press and proccess keys of
// interest.
//-----------------------------------------------------------------
static void HandleInputChar(void)
{
 int ch;
 static int speed=0;
  if ((ch=getchar())==EOF)              // no key pressed return
     {
       return;
     }

	if  (ch=='w')
	{
		robot_mode_setting(ROBOT_FOWARD_MOVING,offset);
    }
	else if  (ch=='x')
    {
		robot_mode_setting(ROBOT_BACKWARD_MOVING,offset);
    }
	else if  (ch=='d')
    {
		robot_mode_setting(ROBOT_RIGHT_ROTATING,offset);
    }
	else if  (ch=='a')
    {
		robot_mode_setting(ROBOT_LEFT_ROTATING,offset);
    }
	else
	{
		robot_mode_setting(ROBOT_STOP,offset);
	}

}

//-----------------------------------------------------------------
// END HandleInputChar
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// END of File
//-----------------------------------------------------------------

<|endoftext|>


<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2016 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// 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.1 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.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes

// Local includes
#include "libmesh/side.h"
#include "libmesh/cell_pyramid5.h"
#include "libmesh/edge_edge2.h"
#include "libmesh/face_tri3.h"
#include "libmesh/face_quad4.h"

namespace libMesh
{

// ------------------------------------------------------------
// Pyramid5 class static member initializations
const unsigned int Pyramid5::side_nodes_map[5][4] =
  {
    {0, 1, 4, 99}, // Side 0
    {1, 2, 4, 99}, // Side 1
    {2, 3, 4, 99}, // Side 2
    {3, 0, 4, 99}, // Side 3
    {0, 3, 2,  1}  // Side 4
  };

const unsigned int Pyramid5::edge_nodes_map[8][2] =
  {
    {0, 1}, // Side 0
    {1, 2}, // Side 1
    {2, 3}, // Side 2
    {0, 3}, // Side 3
    {0, 4}, // Side 4
    {1, 4}, // Side 5
    {2, 4}, // Side 6
    {3, 4}  // Side 7
  };

// ------------------------------------------------------------
// Pyramid5 class member functions

bool Pyramid5::is_vertex(const unsigned int) const
{
  return true;
}

bool Pyramid5::is_edge(const unsigned int) const
{
  return false;
}

bool Pyramid5::is_face(const unsigned int) const
{
  return false;
}

bool Pyramid5::is_node_on_side(const unsigned int n,
                               const unsigned int s) const
{
  libmesh_assert_less (s, n_sides());
  for (unsigned int i = 0; i != 4; ++i)
    if (side_nodes_map[s][i] == n)
      return true;
  return false;
}

bool Pyramid5::is_node_on_edge(const unsigned int n,
                               const unsigned int e) const
{
  libmesh_assert_less (e, n_edges());
  for (unsigned int i = 0; i != 2; ++i)
    if (edge_nodes_map[e][i] == n)
      return true;
  return false;
}

bool Pyramid5::has_affine_map() const
{
  //  Point v = this->point(3) - this->point(0);
  //  return (v.relative_fuzzy_equals(this->point(2) - this->point(1)));
  return false;
}

UniquePtr<Elem> Pyramid5::build_side (const unsigned int i,
                                      bool proxy) const
{
  libmesh_assert_less (i, this->n_sides());

  if (proxy)
    {
      switch (i)
        {
        case 0:
        case 1:
        case 2:
        case 3:
          return UniquePtr<Elem>(new Side<Tri3,Pyramid5>(this,i));

        case 4:
          return UniquePtr<Elem>(new Side<Quad4,Pyramid5>(this,i));

        default:
          libmesh_error_msg("Invalid side i = " << i);
        }
    }

  else
    {
      // Create NULL pointer to be initialized, returned later.
      Elem * face = libmesh_nullptr;

      switch (i)
        {
        case 0: // triangular face 1
        case 1: // triangular face 2
        case 2: // triangular face 3
        case 3: // triangular face 4
          {
            face = new Tri3;
            break;
          }
        case 4: // the quad face at z=0
          {
            face = new Quad4;
            break;
          }
        default:
          libmesh_error_msg("Invalid side i = " << i);
        }

      face->subdomain_id() = this->subdomain_id();

      // Set the nodes
      for (unsigned n=0; n<face->n_nodes(); ++n)
        face->set_node(n) = this->get_node(Pyramid5::side_nodes_map[i][n]);

      return UniquePtr<Elem>(face);
    }

  libmesh_error_msg("We'll never get here!");
  return UniquePtr<Elem>();
}

UniquePtr<Elem> Pyramid5::build_edge (const unsigned int i) const
{
  libmesh_assert_less (i, this->n_edges());

  return UniquePtr<Elem>(new SideEdge<Edge2,Pyramid5>(this,i));
}

void Pyramid5::connectivity(const unsigned int libmesh_dbg_var(sc),
                            const IOPackage iop,
                            std::vector<dof_id_type> & conn) const
{
  libmesh_assert(_nodes);
  libmesh_assert_less (sc, this->n_sub_elem());
  libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);

  switch (iop)
    {
    case TECPLOT:
      {
        conn.resize(8);
        conn[0] = this->node(0)+1;
        conn[1] = this->node(1)+1;
        conn[2] = this->node(2)+1;
        conn[3] = this->node(3)+1;
        conn[4] = this->node(4)+1;
        conn[5] = this->node(4)+1;
        conn[6] = this->node(4)+1;
        conn[7] = this->node(4)+1;
        return;
      }

    case VTK:
      {
        conn.resize(5);
        conn[0] = this->node(3);
        conn[1] = this->node(2);
        conn[2] = this->node(1);
        conn[3] = this->node(0);
        conn[4] = this->node(4);
        return;
      }

    default:
      libmesh_error_msg("Unsupported IO package " << iop);
    }
}

Real Pyramid5::volume () const
{
  // Make copies of our points.  It makes the subsequent calculations a bit
  // shorter and avoids dereferencing the same pointer multiple times.
  Point
    x0 = point(0), x1 = point(1), x2 = point(2), x3 = point(3), x4 = point(4);

  // The number of components in the dx_dxi, dx_deta, and dx_dzeta arrays.
  const int n_components = 4;

  Point dx_dxi[n_components] =
    {
      -x0/4 + x1/4 + x2/4 - x3/4, // const
      x0/4 - x1/4 - x2/4 + x3/4,  // zeta
      x0/4 - x1/4 + x2/4 - x3/4   // eta
    };

  Point dx_deta[n_components] =
    {
      -x0/4 - x1/4 + x2/4 + x3/4, // const
      x0/4 + x1/4 - x2/4 - x3/4,  // zeta
      x0/4 - x1/4 + x2/4 - x3/4,  // xi
    };

  Point dx_dzeta[n_components] =
    {
      -x0/4 - x1/4 - x2/4 - x3/4 + x4,  // const
      x0/2 + x1/2 + x2/2 + x3/2 - 2*x4, // zeta
      -x0/4 - x1/4 - x2/4 - x3/4 + x4,  // zeta**2
      x0/4 - x1/4 + x2/4 - x3/4         // xi*eta
    };

  // Number of points in the 2D quadrature rule
  const int N = 8;

  // Parameters of the quadrature rule
  static const Real
    a1 = -5.0661630334978742377431469429037e-01L,
    a2 = -2.6318405556971359557121701304557e-01L,
    b1 = 1.2251482265544137786674043037115e-01L,
    b2 = 5.4415184401122528879992623629551e-01L,
    w1 = 2.3254745125350790274997694884235e-01L,
    w2 = 1.0078588207982543058335638449098e-01L;

  // The points and weights of the 2x2x2 quadrature rule
  static const Real xi[8]   = {a1,  a2,  a1,  a2, -a1, -a2, -a1, -a2};
  static const Real eta[8]  = {a1,  a2, -a1, -a2,  a1,  a2, -a1, -a2};
  static const Real zeta[8] = {b1,  b2,  b1,  b2,  b1,  b2,  b1,  b2};
  static const Real w[8] = {w1, w2, w1, w2, w1, w2, w1, w2};

  Real vol = 0.;
  for (int q=0; q<N; ++q)
    {
      // Note: we need to scale dx/dxi and dx/deta by (1-z), and dx/dzeta by (1-z)**2
      Point
        dx_dxi_q   = (dx_dxi[0] + zeta[q]*dx_dxi[1] + eta[q]*dx_dxi[2]) / (1. - zeta[q]),
        dx_deta_q  = (dx_deta[0] + zeta[q]*dx_deta[1] + xi[q]*dx_deta[2]) / (1. - zeta[q]),
        dx_dzeta_q = (dx_dzeta[0] + zeta[q]*dx_dzeta[1] + zeta[q]*zeta[q]*dx_dzeta[2] + xi[q]*eta[q]*dx_dzeta[3]) / (1. - zeta[q]) / (1. - zeta[q]);

      // Compute scalar triple product, multiply by weight, and accumulate volume.
      vol += w[q] * dx_dxi_q * dx_deta_q.cross(dx_dzeta_q);
    }

  return vol;
}

} // namespace libMesh
<commit_msg>Revert "Add quadrature-based volume() implementation for Pyramid5."<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2016 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// 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.1 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.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes

// Local includes
#include "libmesh/side.h"
#include "libmesh/cell_pyramid5.h"
#include "libmesh/edge_edge2.h"
#include "libmesh/face_tri3.h"
#include "libmesh/face_quad4.h"

namespace libMesh
{

// ------------------------------------------------------------
// Pyramid5 class static member initializations
const unsigned int Pyramid5::side_nodes_map[5][4] =
  {
    {0, 1, 4, 99}, // Side 0
    {1, 2, 4, 99}, // Side 1
    {2, 3, 4, 99}, // Side 2
    {3, 0, 4, 99}, // Side 3
    {0, 3, 2,  1}  // Side 4
  };

const unsigned int Pyramid5::edge_nodes_map[8][2] =
  {
    {0, 1}, // Side 0
    {1, 2}, // Side 1
    {2, 3}, // Side 2
    {0, 3}, // Side 3
    {0, 4}, // Side 4
    {1, 4}, // Side 5
    {2, 4}, // Side 6
    {3, 4}  // Side 7
  };

// ------------------------------------------------------------
// Pyramid5 class member functions

bool Pyramid5::is_vertex(const unsigned int) const
{
  return true;
}

bool Pyramid5::is_edge(const unsigned int) const
{
  return false;
}

bool Pyramid5::is_face(const unsigned int) const
{
  return false;
}

bool Pyramid5::is_node_on_side(const unsigned int n,
                               const unsigned int s) const
{
  libmesh_assert_less (s, n_sides());
  for (unsigned int i = 0; i != 4; ++i)
    if (side_nodes_map[s][i] == n)
      return true;
  return false;
}

bool Pyramid5::is_node_on_edge(const unsigned int n,
                               const unsigned int e) const
{
  libmesh_assert_less (e, n_edges());
  for (unsigned int i = 0; i != 2; ++i)
    if (edge_nodes_map[e][i] == n)
      return true;
  return false;
}

bool Pyramid5::has_affine_map() const
{
  //  Point v = this->point(3) - this->point(0);
  //  return (v.relative_fuzzy_equals(this->point(2) - this->point(1)));
  return false;
}

UniquePtr<Elem> Pyramid5::build_side (const unsigned int i,
                                      bool proxy) const
{
  libmesh_assert_less (i, this->n_sides());

  if (proxy)
    {
      switch (i)
        {
        case 0:
        case 1:
        case 2:
        case 3:
          return UniquePtr<Elem>(new Side<Tri3,Pyramid5>(this,i));

        case 4:
          return UniquePtr<Elem>(new Side<Quad4,Pyramid5>(this,i));

        default:
          libmesh_error_msg("Invalid side i = " << i);
        }
    }

  else
    {
      // Create NULL pointer to be initialized, returned later.
      Elem * face = libmesh_nullptr;

      switch (i)
        {
        case 0: // triangular face 1
        case 1: // triangular face 2
        case 2: // triangular face 3
        case 3: // triangular face 4
          {
            face = new Tri3;
            break;
          }
        case 4: // the quad face at z=0
          {
            face = new Quad4;
            break;
          }
        default:
          libmesh_error_msg("Invalid side i = " << i);
        }

      face->subdomain_id() = this->subdomain_id();

      // Set the nodes
      for (unsigned n=0; n<face->n_nodes(); ++n)
        face->set_node(n) = this->get_node(Pyramid5::side_nodes_map[i][n]);

      return UniquePtr<Elem>(face);
    }

  libmesh_error_msg("We'll never get here!");
  return UniquePtr<Elem>();
}

UniquePtr<Elem> Pyramid5::build_edge (const unsigned int i) const
{
  libmesh_assert_less (i, this->n_edges());

  return UniquePtr<Elem>(new SideEdge<Edge2,Pyramid5>(this,i));
}

void Pyramid5::connectivity(const unsigned int libmesh_dbg_var(sc),
                            const IOPackage iop,
                            std::vector<dof_id_type> & conn) const
{
  libmesh_assert(_nodes);
  libmesh_assert_less (sc, this->n_sub_elem());
  libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);

  switch (iop)
    {
    case TECPLOT:
      {
        conn.resize(8);
        conn[0] = this->node(0)+1;
        conn[1] = this->node(1)+1;
        conn[2] = this->node(2)+1;
        conn[3] = this->node(3)+1;
        conn[4] = this->node(4)+1;
        conn[5] = this->node(4)+1;
        conn[6] = this->node(4)+1;
        conn[7] = this->node(4)+1;
        return;
      }

    case VTK:
      {
        conn.resize(5);
        conn[0] = this->node(3);
        conn[1] = this->node(2);
        conn[2] = this->node(1);
        conn[3] = this->node(0);
        conn[4] = this->node(4);
        return;
      }

    default:
      libmesh_error_msg("Unsupported IO package " << iop);
    }
}

Real Pyramid5::volume () const
{
  // The pyramid with a bilinear base has volume given by the
  // formula in: "Calculation of the Volume of a General Hexahedron
  // for Flow Predictions", AIAA Journal v.23, no.6, 1984, p.954-
  Node * node0 = this->get_node(0);
  Node * node1 = this->get_node(1);
  Node * node2 = this->get_node(2);
  Node * node3 = this->get_node(3);
  Node * node4 = this->get_node(4);

  // Construct Various edge and diagonal vectors
  Point v40 ( *node0 - *node4 );
  Point v13 ( *node3 - *node1 );
  Point v02 ( *node2 - *node0 );
  Point v03 ( *node3 - *node0 );
  Point v01 ( *node1 - *node0 );

  // Finally, ready to return the volume!
  return (1./6.)*(v40*(v13.cross(v02))) + (1./12.)*(v02*(v01.cross(v03)));
}

} // namespace libMesh
<|endoftext|>


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

/**
 * \file ir_validate.cpp
 *
 * Attempts to verify that various invariants of the IR tree are true.
 *
 * In particular, at the moment it makes sure that no single
 * ir_instruction node except for ir_variable appears multiple times
 * in the ir tree.  ir_variable does appear multiple times: Once as a
 * declaration in an exec_list, and multiple times as the endpoint of
 * a dereference chain.
 */

#include <inttypes.h>
#include "ir.h"
#include "ir_hierarchical_visitor.h"
#include "hash_table.h"

class ir_validate : public ir_hierarchical_visitor {
public:
   ir_validate()
   {
      this->ht = hash_table_ctor(0, hash_table_pointer_hash,
				 hash_table_pointer_compare);

      this->current_function = NULL;

      this->callback = ir_validate::validate_ir;
      this->data = ht;
   }

   ~ir_validate()
   {
      hash_table_dtor(this->ht);
   }

   virtual ir_visitor_status visit(ir_variable *v);
   virtual ir_visitor_status visit(ir_dereference_variable *ir);

   virtual ir_visitor_status visit_enter(ir_function *ir);
   virtual ir_visitor_status visit_leave(ir_function *ir);
   virtual ir_visitor_status visit_enter(ir_function_signature *ir);

   static void validate_ir(ir_instruction *ir, void *data);

   ir_function *current_function;

   struct hash_table *ht;
};

ir_visitor_status
ir_validate::visit(ir_dereference_variable *ir)
{
   if ((ir->var == NULL) || (ir->var->as_variable() == NULL)) {
      printf("ir_dereference_variable @ %p does not specify a variable %p\n",
	     ir, ir->var);
      abort();
   }

   if (hash_table_find(ht, ir->var) == NULL) {
      printf("ir_dereference_variable @ %p specifies undeclared variable "
	     "`%s' @ %p\n",
	     ir, ir->var->name, ir->var);
      abort();
   }

   this->validate_ir(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_validate::visit_enter(ir_function *ir)
{
   /* Function definitions cannot be nested.
    */
   if (this->current_function != NULL) {
      printf("Function definition nested inside another function "
	     "definition:\n");
      printf("%s %p inside %s %p\n",
	     ir->name, ir,
	     this->current_function->name, this->current_function);
      abort();
   }

   /* Store the current function hierarchy being traversed.  This is used
    * by the function signature visitor to ensure that the signatures are
    * linked with the correct functions.
    */
   this->current_function = ir;

   this->validate_ir(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_validate::visit_leave(ir_function *ir)
{
   (void) ir;

   this->current_function = NULL;
   return visit_continue;
}

ir_visitor_status
ir_validate::visit_enter(ir_function_signature *ir)
{
   if (this->current_function != ir->function()) {
      printf("Function signature nested inside wrong function "
	     "definition:\n");
      printf("%p inside %s %p instead of %s %p\n",
	     ir,
	     this->current_function->name, this->current_function,
	     ir->function_name(), ir->function());
      abort();
   }

   this->validate_ir(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_validate::visit(ir_variable *ir)
{
   /* An ir_variable is the one thing that can (and will) appear multiple times
    * in an IR tree.  It is added to the hashtable so that it can be used
    * in the ir_dereference_variable handler to ensure that a variable is
    * declared before it is dereferenced.
    */
   hash_table_insert(ht, ir, ir);
   return visit_continue;
}

void
ir_validate::validate_ir(ir_instruction *ir, void *data)
{
   struct hash_table *ht = (struct hash_table *) data;

   if (hash_table_find(ht, ir)) {
      printf("Instruction node present twice in ir tree:\n");
      ir->print();
      printf("\n");
      abort();
   }
   hash_table_insert(ht, ir, ir);
}

void
check_node_type(ir_instruction *ir, void *data)
{
   if (ir->ir_type <= ir_type_unset || ir->ir_type >= ir_type_max) {
      printf("Instruction node with unset type\n");
      ir->print(); printf("\n");
   }
}

void
validate_ir_tree(exec_list *instructions)
{
   ir_validate v;

   v.run(instructions);

   foreach_iter(exec_list_iterator, iter, *instructions) {
      ir_instruction *ir = (ir_instruction *)iter.get();

      visit_tree(ir, check_node_type, NULL);
   }
}
<commit_msg>glsl2: Check that nodes in a valid tree aren't error-type.<commit_after>/*
 * Copyright © 2010 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

/**
 * \file ir_validate.cpp
 *
 * Attempts to verify that various invariants of the IR tree are true.
 *
 * In particular, at the moment it makes sure that no single
 * ir_instruction node except for ir_variable appears multiple times
 * in the ir tree.  ir_variable does appear multiple times: Once as a
 * declaration in an exec_list, and multiple times as the endpoint of
 * a dereference chain.
 */

#include <inttypes.h>
#include "ir.h"
#include "ir_hierarchical_visitor.h"
#include "hash_table.h"
#include "glsl_types.h"

class ir_validate : public ir_hierarchical_visitor {
public:
   ir_validate()
   {
      this->ht = hash_table_ctor(0, hash_table_pointer_hash,
				 hash_table_pointer_compare);

      this->current_function = NULL;

      this->callback = ir_validate::validate_ir;
      this->data = ht;
   }

   ~ir_validate()
   {
      hash_table_dtor(this->ht);
   }

   virtual ir_visitor_status visit(ir_variable *v);
   virtual ir_visitor_status visit(ir_dereference_variable *ir);

   virtual ir_visitor_status visit_enter(ir_function *ir);
   virtual ir_visitor_status visit_leave(ir_function *ir);
   virtual ir_visitor_status visit_enter(ir_function_signature *ir);

   static void validate_ir(ir_instruction *ir, void *data);

   ir_function *current_function;

   struct hash_table *ht;
};

ir_visitor_status
ir_validate::visit(ir_dereference_variable *ir)
{
   if ((ir->var == NULL) || (ir->var->as_variable() == NULL)) {
      printf("ir_dereference_variable @ %p does not specify a variable %p\n",
	     ir, ir->var);
      abort();
   }

   if (hash_table_find(ht, ir->var) == NULL) {
      printf("ir_dereference_variable @ %p specifies undeclared variable "
	     "`%s' @ %p\n",
	     ir, ir->var->name, ir->var);
      abort();
   }

   this->validate_ir(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_validate::visit_enter(ir_function *ir)
{
   /* Function definitions cannot be nested.
    */
   if (this->current_function != NULL) {
      printf("Function definition nested inside another function "
	     "definition:\n");
      printf("%s %p inside %s %p\n",
	     ir->name, ir,
	     this->current_function->name, this->current_function);
      abort();
   }

   /* Store the current function hierarchy being traversed.  This is used
    * by the function signature visitor to ensure that the signatures are
    * linked with the correct functions.
    */
   this->current_function = ir;

   this->validate_ir(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_validate::visit_leave(ir_function *ir)
{
   (void) ir;

   this->current_function = NULL;
   return visit_continue;
}

ir_visitor_status
ir_validate::visit_enter(ir_function_signature *ir)
{
   if (this->current_function != ir->function()) {
      printf("Function signature nested inside wrong function "
	     "definition:\n");
      printf("%p inside %s %p instead of %s %p\n",
	     ir,
	     this->current_function->name, this->current_function,
	     ir->function_name(), ir->function());
      abort();
   }

   this->validate_ir(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_validate::visit(ir_variable *ir)
{
   /* An ir_variable is the one thing that can (and will) appear multiple times
    * in an IR tree.  It is added to the hashtable so that it can be used
    * in the ir_dereference_variable handler to ensure that a variable is
    * declared before it is dereferenced.
    */
   hash_table_insert(ht, ir, ir);
   return visit_continue;
}

void
ir_validate::validate_ir(ir_instruction *ir, void *data)
{
   struct hash_table *ht = (struct hash_table *) data;

   if (hash_table_find(ht, ir)) {
      printf("Instruction node present twice in ir tree:\n");
      ir->print();
      printf("\n");
      abort();
   }
   hash_table_insert(ht, ir, ir);
}

void
check_node_type(ir_instruction *ir, void *data)
{
   if (ir->ir_type <= ir_type_unset || ir->ir_type >= ir_type_max) {
      printf("Instruction node with unset type\n");
      ir->print(); printf("\n");
   }
   assert(ir->type != glsl_type::error_type);
}

void
validate_ir_tree(exec_list *instructions)
{
   ir_validate v;

   v.run(instructions);

   foreach_iter(exec_list_iterator, iter, *instructions) {
      ir_instruction *ir = (ir_instruction *)iter.get();

      visit_tree(ir, check_node_type, NULL);
   }
}
<|endoftext|>


<commit_before>/*****************************************************************************/
/* Sockets.cpp                            Copyright (c) Ladislav Zezula 2021 */
/*---------------------------------------------------------------------------*/
/* Don't call this module "Socket.cpp", otherwise VS 2019 will not link it   */
/* Socket functions for CascLib.                                             */
/*---------------------------------------------------------------------------*/
/*   Date    Ver   Who  Comment                                              */
/* --------  ----  ---  -------                                              */
/* 13.02.21  1.00  Lad  Created                                              */
/*****************************************************************************/

#define __CASCLIB_SELF__
#include "../CascLib.h"
#include "../CascCommon.h"

//-----------------------------------------------------------------------------
// Local variables

CASC_SOCKET_CACHE SocketCache;

//-----------------------------------------------------------------------------
// CASC_SOCKET functions

// Guarantees that there is zero terminator after the response
char * CASC_SOCKET::ReadResponse(const char * request, size_t request_length, size_t * PtrLength)
{
    CASC_MIME_HTTP HttpInfo;
    char * server_response = NULL;
    size_t total_received = 0;
    size_t block_increment = 0x8000;
    size_t buffer_size = block_increment;
    int bytes_received = 0;

    // Pre-set the result length
    if(PtrLength != NULL)
        PtrLength[0] = 0;
    if(request_length == 0)
        request_length = strlen(request);

    // Lock the socket
    CascLock(Lock);

    // Send the request to the remote host. On Linux, this call may send signal(SIGPIPE),
    // we need to prevend that by using the MSG_NOSIGNAL flag. On Windows, it fails normally.
    while(send(sock, request, (int)request_length, MSG_NOSIGNAL) == SOCKET_ERROR)
    {
        // If the connection was closed by the remote host, we try to reconnect
        if(ReconnectAfterShutdown(sock, remoteItem) == INVALID_SOCKET)
        {
            SetCascError(ERROR_NETWORK_NOT_AVAILABLE);
            CascUnlock(Lock);
            return NULL;
        }
    }

    // Allocate buffer for server response. Allocate one extra byte for zero terminator
    if((server_response = CASC_ALLOC<char>(buffer_size + 1)) != NULL)
    {
        for(;;)
        {
            // Reallocate the buffer size, if needed
            if(total_received == buffer_size)
            {
                if((server_response = CASC_REALLOC(char, server_response, buffer_size + block_increment + 1)) == NULL)
                {
                    SetCascError(ERROR_NOT_ENOUGH_MEMORY);
                    CascUnlock(Lock);
                    return NULL;
                }
                buffer_size += block_increment;
            }

            // Receive the next part of the response, up to buffer size
            // Return value 0 means "connection closed", -1 means an error
            bytes_received = recv(sock, server_response + total_received, (int)(buffer_size - total_received), 0);
            if(bytes_received <= 0)
                break;

            // Append the number of bytes received. Also terminate response with zero
            total_received += bytes_received;
            server_response[total_received] = 0;

            // On a HTTP protocol, we need to check whether we received all data
            if(HttpInfo.IsDataComplete(server_response, total_received))
                break;
        }
    }

    // Unlock the socket
    CascUnlock(Lock);

    // Give the result to the caller
    if(PtrLength != NULL)
        PtrLength[0] = total_received;
    return server_response;
}

DWORD CASC_SOCKET::AddRef()
{
    return CascInterlockedIncrement(&dwRefCount);
}

void CASC_SOCKET::Release()
{
    // Note: If this is a cached socket, there will be extra reference from the cache
    if(CascInterlockedDecrement(&dwRefCount) == 0)
    {
        Delete();
    }
}

int CASC_SOCKET::GetSockError()
{
#ifdef CASCLIB_PLATFORM_WINDOWS
    return WSAGetLastError();
#else
    return errno;
#endif
}

DWORD CASC_SOCKET::GetAddrInfoWrapper(const char * hostName, unsigned portNum, PADDRINFO hints, PADDRINFO * ppResult)
{
    char portNumString[16];

    // Prepare the port number
    CascStrPrintf(portNumString, _countof(portNumString), "%d", portNum);

    // Attempt to connect
    for(;;)
    {
        // Attempt to call the addrinfo
        DWORD dwErrCode = getaddrinfo(hostName, portNumString, hints, ppResult);

        // Error-specific handling
        switch(dwErrCode)
        {
#ifdef CASCLIB_PLATFORM_WINDOWS
            case WSANOTINITIALISED:     // Windows-specific: WSAStartup not called
            {
                WSADATA wsd;

                WSAStartup(MAKEWORD(2, 2), &wsd);
                continue;
            }
#endif
            case EAI_AGAIN:             // Temporary error, try again
                continue;

            default:                    // Any other result, incl. ERROR_SUCCESS
                return dwErrCode;
        }
    }
}

SOCKET CASC_SOCKET::CreateAndConnect(addrinfo * remoteItem)
{
    SOCKET sock;

    // Create new socket
    // On error, returns returns INVALID_SOCKET (-1) on Windows, -1 on Linux
    if((sock = socket(remoteItem->ai_family, remoteItem->ai_socktype, remoteItem->ai_protocol)) > 0)
    {
        // Connect to the remote host
        // On error, returns SOCKET_ERROR (-1) on Windows, -1 on Linux
        if(connect(sock, remoteItem->ai_addr, (int)remoteItem->ai_addrlen) == 0)
            return sock;

        // Failed. Close the socket and return 0
        closesocket(sock);
        sock = INVALID_SOCKET;
    }

    return sock;
}

SOCKET CASC_SOCKET::ReconnectAfterShutdown(SOCKET & sock, addrinfo * remoteItem)
{
    // Retrieve the error code related to previous socket operation
    switch(GetSockError())
    {
        case EPIPE:         // Non-Windows
        case WSAECONNRESET: // Windows
        {
            // Close the old socket
            if(sock != INVALID_SOCKET)
                closesocket(sock);

            // Attempt to reconnect
            sock = CreateAndConnect(remoteItem);
            return sock;
        }
    }

    // Another problem
    return INVALID_SOCKET;
}

PCASC_SOCKET CASC_SOCKET::New(addrinfo * remoteList, addrinfo * remoteItem, const char * hostName, unsigned portNum, SOCKET sock)
{
    PCASC_SOCKET pSocket;
    size_t length = strlen(hostName);

    // Allocate enough bytes
    pSocket = (PCASC_SOCKET)CASC_ALLOC<BYTE>(sizeof(CASC_SOCKET) + length);
    if(pSocket != NULL)
    {
        // Fill the entire object with zero
        memset(pSocket, 0, sizeof(CASC_SOCKET) + length);
        pSocket->remoteList = remoteList;
        pSocket->remoteItem = remoteItem;
        pSocket->dwRefCount = 1;
        pSocket->portNum = portNum;
        pSocket->sock = sock;

        // Init the remote host name
        CascStrCopy((char *)pSocket->hostName, length + 1, hostName);

        // Init the socket lock
        CascInitLock(pSocket->Lock);
    }

    return pSocket;
}

PCASC_SOCKET CASC_SOCKET::Connect(const char * hostName, unsigned portNum)
{
    PCASC_SOCKET pSocket;
    addrinfo * remoteList;
    addrinfo * remoteItem;
    addrinfo hints = {0};
    SOCKET sock;
    int nErrCode;

    // Retrieve the information about the remote host
    // This will fail immediately if there is no connection to the internet
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    nErrCode = GetAddrInfoWrapper(hostName, portNum, &hints, &remoteList);

    // Handle error code
    if(nErrCode == 0)
    {
        // Try to connect to any address provided by the getaddrinfo()
        for(remoteItem = remoteList; remoteItem != NULL; remoteItem = remoteItem->ai_next)
        {
            // Create new socket and connect to the remote host
            if((sock = CreateAndConnect(remoteItem)) != 0)
            {
                // Create new instance of the CASC_SOCKET structure
                if((pSocket = CASC_SOCKET::New(remoteList, remoteItem, hostName, portNum, sock)) != NULL)
                {
                    return pSocket;
                }

                // Close the socket
                closesocket(sock);
            }
        }

        // Couldn't find a network
        nErrCode = ERROR_NETWORK_NOT_AVAILABLE;
    }

    SetCascError(nErrCode);
    return NULL;
}

void CASC_SOCKET::Delete()
{
    PCASC_SOCKET pThis = this;

    // Remove the socket from the cache
    if(pCache != NULL)
        pCache->UnlinkSocket(this);
    pCache = NULL;

    // Close the socket, if any
    if(sock != 0)
        closesocket(sock);
    sock = 0;

    // Free the lock
    CascFreeLock(Lock);

    // Free the socket itself
    CASC_FREE(pThis);
}

//-----------------------------------------------------------------------------
// The CASC_SOCKET_CACHE class

CASC_SOCKET_CACHE::CASC_SOCKET_CACHE()
{
    pFirst = pLast = NULL;
    dwRefCount = 0;
}

CASC_SOCKET_CACHE::~CASC_SOCKET_CACHE()
{
    PurgeAll();
}

PCASC_SOCKET CASC_SOCKET_CACHE::Find(const char * hostName, unsigned portNum)
{
    PCASC_SOCKET pSocket;

    for(pSocket = pFirst; pSocket != NULL; pSocket = pSocket->pNext)
    {
        if(!_stricmp(pSocket->hostName, hostName) && (pSocket->portNum == portNum))
            break;
    }

    return pSocket;
}

PCASC_SOCKET CASC_SOCKET_CACHE::InsertSocket(PCASC_SOCKET pSocket)
{
    if(pSocket != NULL && pSocket->pCache == NULL)
    {
        // Do we have caching turned on?
        if(dwRefCount > 0)
        {
            // Insert one reference to the socket to mark it as cached
            pSocket->AddRef();

            // Insert the socket to the chain
            if(pFirst == NULL && pLast == NULL)
            {
                pFirst = pLast = pSocket;
            }
            else
            {
                pSocket->pPrev = pLast;
                pLast->pNext = pSocket;
                pLast = pSocket;
            }

            // Mark the socket as cached
            pSocket->pCache = this;
        }
    }

    return pSocket;
}

void CASC_SOCKET_CACHE::UnlinkSocket(PCASC_SOCKET pSocket)
{
    // Only if it's a valid socket
    if(pSocket != NULL)
    {
        // Check the first and the last items
        if(pSocket == pFirst)
            pFirst = pSocket->pNext;
        if(pSocket == pLast)
            pLast = pSocket->pPrev;

        // Disconnect the socket from the chain
        if(pSocket->pPrev != NULL)
            pSocket->pPrev->pNext = pSocket->pNext;
        if(pSocket->pNext != NULL)
            pSocket->pNext->pPrev = pSocket->pPrev;
    }
}

void CASC_SOCKET_CACHE::SetCaching(bool bAddRef)
{
    PCASC_SOCKET pSocket;
    PCASC_SOCKET pNext;

    // We need to increment reference count for each enabled caching
    if(bAddRef)
    {
        // Add one reference to all currently held sockets
        if(dwRefCount == 0)
        {
            for(pSocket = pFirst; pSocket != NULL; pSocket = pSocket->pNext)
                pSocket->AddRef();
        }

        // Increment of references for the future sockets
        CascInterlockedIncrement(&dwRefCount);
    }
    else
    {
        // Sanity check for multiple calls to dereference
        assert(dwRefCount > 0);

        // Dereference the reference count. If drops to zero, dereference all sockets as well
        if(CascInterlockedDecrement(&dwRefCount) == 0)
        {
            for(pSocket = pFirst; pSocket != NULL; pSocket = pNext)
            {
                pNext = pSocket->pNext;
                pSocket->Release();
            }
        }
    }
}

void CASC_SOCKET_CACHE::PurgeAll()
{
    PCASC_SOCKET pSocket;
    PCASC_SOCKET pNext;

    // Dereference all current sockets
    for(pSocket = pFirst; pSocket != NULL; pSocket = pNext)
    {
        pNext = pSocket->pNext;
        pSocket->Delete();
    }
}

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

PCASC_SOCKET sockets_connect(const char * hostName, unsigned portNum)
{
    PCASC_SOCKET pSocket;

    // Try to find the item in the cache
    if((pSocket = SocketCache.Find(hostName, portNum)) != NULL)
    {
        pSocket->AddRef();
    }
    else
    {
        // Create new socket and connect it to the remote host
        pSocket = CASC_SOCKET::Connect(hostName, portNum);

        // Insert it to the cache, if it's a HTTP connection
        if(pSocket->portNum == CASC_PORT_HTTP)
            pSocket = SocketCache.InsertSocket(pSocket);
    }

    return pSocket;
}

void sockets_set_caching(bool caching)
{
    SocketCache.SetCaching(caching);
}
<commit_msg>Fix build with clang<commit_after>/*****************************************************************************/
/* Sockets.cpp                            Copyright (c) Ladislav Zezula 2021 */
/*---------------------------------------------------------------------------*/
/* Don't call this module "Socket.cpp", otherwise VS 2019 will not link it   */
/* Socket functions for CascLib.                                             */
/*---------------------------------------------------------------------------*/
/*   Date    Ver   Who  Comment                                              */
/* --------  ----  ---  -------                                              */
/* 13.02.21  1.00  Lad  Created                                              */
/*****************************************************************************/

#define __CASCLIB_SELF__
#include "../CascLib.h"
#include "../CascCommon.h"

//-----------------------------------------------------------------------------
// Local variables

CASC_SOCKET_CACHE SocketCache;

//-----------------------------------------------------------------------------
// CASC_SOCKET functions

// Guarantees that there is zero terminator after the response
char * CASC_SOCKET::ReadResponse(const char * request, size_t request_length, size_t * PtrLength)
{
    CASC_MIME_HTTP HttpInfo;
    char * server_response = NULL;
    size_t total_received = 0;
    size_t block_increment = 0x8000;
    size_t buffer_size = block_increment;
    int bytes_received = 0;

    // Pre-set the result length
    if(PtrLength != NULL)
        PtrLength[0] = 0;
    if(request_length == 0)
        request_length = strlen(request);

    // Lock the socket
    CascLock(Lock);

    // Send the request to the remote host. On Linux, this call may send signal(SIGPIPE),
    // we need to prevend that by using the MSG_NOSIGNAL flag. On Windows, it fails normally.
    while(send(sock, request, (int)request_length, MSG_NOSIGNAL) == SOCKET_ERROR)
    {
        // If the connection was closed by the remote host, we try to reconnect
        if(ReconnectAfterShutdown(sock, remoteItem) == INVALID_SOCKET)
        {
            SetCascError(ERROR_NETWORK_NOT_AVAILABLE);
            CascUnlock(Lock);
            return NULL;
        }
    }

    // Allocate buffer for server response. Allocate one extra byte for zero terminator
    if((server_response = CASC_ALLOC<char>(buffer_size + 1)) != NULL)
    {
        for(;;)
        {
            // Reallocate the buffer size, if needed
            if(total_received == buffer_size)
            {
                if((server_response = CASC_REALLOC(char, server_response, buffer_size + block_increment + 1)) == NULL)
                {
                    SetCascError(ERROR_NOT_ENOUGH_MEMORY);
                    CascUnlock(Lock);
                    return NULL;
                }
                buffer_size += block_increment;
            }

            // Receive the next part of the response, up to buffer size
            // Return value 0 means "connection closed", -1 means an error
            bytes_received = recv(sock, server_response + total_received, (int)(buffer_size - total_received), 0);
            if(bytes_received <= 0)
                break;

            // Append the number of bytes received. Also terminate response with zero
            total_received += bytes_received;
            server_response[total_received] = 0;

            // On a HTTP protocol, we need to check whether we received all data
            if(HttpInfo.IsDataComplete(server_response, total_received))
                break;
        }
    }

    // Unlock the socket
    CascUnlock(Lock);

    // Give the result to the caller
    if(PtrLength != NULL)
        PtrLength[0] = total_received;
    return server_response;
}

DWORD CASC_SOCKET::AddRef()
{
    return CascInterlockedIncrement(&dwRefCount);
}

void CASC_SOCKET::Release()
{
    // Note: If this is a cached socket, there will be extra reference from the cache
    if(CascInterlockedDecrement(&dwRefCount) == 0)
    {
        Delete();
    }
}

int CASC_SOCKET::GetSockError()
{
#ifdef CASCLIB_PLATFORM_WINDOWS
    return WSAGetLastError();
#else
    return errno;
#endif
}

DWORD CASC_SOCKET::GetAddrInfoWrapper(const char * hostName, unsigned portNum, PADDRINFO hints, PADDRINFO * ppResult)
{
    char portNumString[16];

    // Prepare the port number
    CascStrPrintf(portNumString, _countof(portNumString), "%d", portNum);

    // Attempt to connect
    for(;;)
    {
        // Attempt to call the addrinfo
        DWORD dwErrCode = getaddrinfo(hostName, portNumString, hints, ppResult);

        // Error-specific handling
        switch(dwErrCode)
        {
#ifdef CASCLIB_PLATFORM_WINDOWS
            case WSANOTINITIALISED:     // Windows-specific: WSAStartup not called
            {
                WSADATA wsd;

                WSAStartup(MAKEWORD(2, 2), &wsd);
                continue;
            }
#endif
            case (DWORD)EAI_AGAIN:             // Temporary error, try again
                continue;

            default:                    // Any other result, incl. ERROR_SUCCESS
                return dwErrCode;
        }
    }
}

SOCKET CASC_SOCKET::CreateAndConnect(addrinfo * remoteItem)
{
    SOCKET sock;

    // Create new socket
    // On error, returns returns INVALID_SOCKET (-1) on Windows, -1 on Linux
    if((sock = socket(remoteItem->ai_family, remoteItem->ai_socktype, remoteItem->ai_protocol)) > 0)
    {
        // Connect to the remote host
        // On error, returns SOCKET_ERROR (-1) on Windows, -1 on Linux
        if(connect(sock, remoteItem->ai_addr, (int)remoteItem->ai_addrlen) == 0)
            return sock;

        // Failed. Close the socket and return 0
        closesocket(sock);
        sock = INVALID_SOCKET;
    }

    return sock;
}

SOCKET CASC_SOCKET::ReconnectAfterShutdown(SOCKET & sock, addrinfo * remoteItem)
{
    // Retrieve the error code related to previous socket operation
    switch(GetSockError())
    {
        case EPIPE:         // Non-Windows
        case WSAECONNRESET: // Windows
        {
            // Close the old socket
            if(sock != INVALID_SOCKET)
                closesocket(sock);

            // Attempt to reconnect
            sock = CreateAndConnect(remoteItem);
            return sock;
        }
    }

    // Another problem
    return INVALID_SOCKET;
}

PCASC_SOCKET CASC_SOCKET::New(addrinfo * remoteList, addrinfo * remoteItem, const char * hostName, unsigned portNum, SOCKET sock)
{
    PCASC_SOCKET pSocket;
    size_t length = strlen(hostName);

    // Allocate enough bytes
    pSocket = (PCASC_SOCKET)CASC_ALLOC<BYTE>(sizeof(CASC_SOCKET) + length);
    if(pSocket != NULL)
    {
        // Fill the entire object with zero
        memset(pSocket, 0, sizeof(CASC_SOCKET) + length);
        pSocket->remoteList = remoteList;
        pSocket->remoteItem = remoteItem;
        pSocket->dwRefCount = 1;
        pSocket->portNum = portNum;
        pSocket->sock = sock;

        // Init the remote host name
        CascStrCopy((char *)pSocket->hostName, length + 1, hostName);

        // Init the socket lock
        CascInitLock(pSocket->Lock);
    }

    return pSocket;
}

PCASC_SOCKET CASC_SOCKET::Connect(const char * hostName, unsigned portNum)
{
    PCASC_SOCKET pSocket;
    addrinfo * remoteList;
    addrinfo * remoteItem;
    addrinfo hints = {0};
    SOCKET sock;
    int nErrCode;

    // Retrieve the information about the remote host
    // This will fail immediately if there is no connection to the internet
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    nErrCode = GetAddrInfoWrapper(hostName, portNum, &hints, &remoteList);

    // Handle error code
    if(nErrCode == 0)
    {
        // Try to connect to any address provided by the getaddrinfo()
        for(remoteItem = remoteList; remoteItem != NULL; remoteItem = remoteItem->ai_next)
        {
            // Create new socket and connect to the remote host
            if((sock = CreateAndConnect(remoteItem)) != 0)
            {
                // Create new instance of the CASC_SOCKET structure
                if((pSocket = CASC_SOCKET::New(remoteList, remoteItem, hostName, portNum, sock)) != NULL)
                {
                    return pSocket;
                }

                // Close the socket
                closesocket(sock);
            }
        }

        // Couldn't find a network
        nErrCode = ERROR_NETWORK_NOT_AVAILABLE;
    }

    SetCascError(nErrCode);
    return NULL;
}

void CASC_SOCKET::Delete()
{
    PCASC_SOCKET pThis = this;

    // Remove the socket from the cache
    if(pCache != NULL)
        pCache->UnlinkSocket(this);
    pCache = NULL;

    // Close the socket, if any
    if(sock != 0)
        closesocket(sock);
    sock = 0;

    // Free the lock
    CascFreeLock(Lock);

    // Free the socket itself
    CASC_FREE(pThis);
}

//-----------------------------------------------------------------------------
// The CASC_SOCKET_CACHE class

CASC_SOCKET_CACHE::CASC_SOCKET_CACHE()
{
    pFirst = pLast = NULL;
    dwRefCount = 0;
}

CASC_SOCKET_CACHE::~CASC_SOCKET_CACHE()
{
    PurgeAll();
}

PCASC_SOCKET CASC_SOCKET_CACHE::Find(const char * hostName, unsigned portNum)
{
    PCASC_SOCKET pSocket;

    for(pSocket = pFirst; pSocket != NULL; pSocket = pSocket->pNext)
    {
        if(!_stricmp(pSocket->hostName, hostName) && (pSocket->portNum == portNum))
            break;
    }

    return pSocket;
}

PCASC_SOCKET CASC_SOCKET_CACHE::InsertSocket(PCASC_SOCKET pSocket)
{
    if(pSocket != NULL && pSocket->pCache == NULL)
    {
        // Do we have caching turned on?
        if(dwRefCount > 0)
        {
            // Insert one reference to the socket to mark it as cached
            pSocket->AddRef();

            // Insert the socket to the chain
            if(pFirst == NULL && pLast == NULL)
            {
                pFirst = pLast = pSocket;
            }
            else
            {
                pSocket->pPrev = pLast;
                pLast->pNext = pSocket;
                pLast = pSocket;
            }

            // Mark the socket as cached
            pSocket->pCache = this;
        }
    }

    return pSocket;
}

void CASC_SOCKET_CACHE::UnlinkSocket(PCASC_SOCKET pSocket)
{
    // Only if it's a valid socket
    if(pSocket != NULL)
    {
        // Check the first and the last items
        if(pSocket == pFirst)
            pFirst = pSocket->pNext;
        if(pSocket == pLast)
            pLast = pSocket->pPrev;

        // Disconnect the socket from the chain
        if(pSocket->pPrev != NULL)
            pSocket->pPrev->pNext = pSocket->pNext;
        if(pSocket->pNext != NULL)
            pSocket->pNext->pPrev = pSocket->pPrev;
    }
}

void CASC_SOCKET_CACHE::SetCaching(bool bAddRef)
{
    PCASC_SOCKET pSocket;
    PCASC_SOCKET pNext;

    // We need to increment reference count for each enabled caching
    if(bAddRef)
    {
        // Add one reference to all currently held sockets
        if(dwRefCount == 0)
        {
            for(pSocket = pFirst; pSocket != NULL; pSocket = pSocket->pNext)
                pSocket->AddRef();
        }

        // Increment of references for the future sockets
        CascInterlockedIncrement(&dwRefCount);
    }
    else
    {
        // Sanity check for multiple calls to dereference
        assert(dwRefCount > 0);

        // Dereference the reference count. If drops to zero, dereference all sockets as well
        if(CascInterlockedDecrement(&dwRefCount) == 0)
        {
            for(pSocket = pFirst; pSocket != NULL; pSocket = pNext)
            {
                pNext = pSocket->pNext;
                pSocket->Release();
            }
        }
    }
}

void CASC_SOCKET_CACHE::PurgeAll()
{
    PCASC_SOCKET pSocket;
    PCASC_SOCKET pNext;

    // Dereference all current sockets
    for(pSocket = pFirst; pSocket != NULL; pSocket = pNext)
    {
        pNext = pSocket->pNext;
        pSocket->Delete();
    }
}

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

PCASC_SOCKET sockets_connect(const char * hostName, unsigned portNum)
{
    PCASC_SOCKET pSocket;

    // Try to find the item in the cache
    if((pSocket = SocketCache.Find(hostName, portNum)) != NULL)
    {
        pSocket->AddRef();
    }
    else
    {
        // Create new socket and connect it to the remote host
        pSocket = CASC_SOCKET::Connect(hostName, portNum);

        // Insert it to the cache, if it's a HTTP connection
        if(pSocket->portNum == CASC_PORT_HTTP)
            pSocket = SocketCache.InsertSocket(pSocket);
    }

    return pSocket;
}

void sockets_set_caching(bool caching)
{
    SocketCache.SetCaching(caching);
}
<|endoftext|>