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

  Program:   Visualization Toolkit
  Module:    vtkImageMirrorPad.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$
  Thanks:    Thanks to C. Charles Law who developed this class.

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

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

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

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

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

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

#include "vtkImageMirrorPad.h"

//----------------------------------------------------------------------------
// Just clip the request.
void vtkImageMirrorPad::ComputeRequiredInputUpdateExtent(int inExt[6],
							 int outExt[6])
{
  int *wExtent = this->GetInput()->GetWholeExtent();
  int idx;

  // initialize inExt
  memcpy(inExt,wExtent,6*sizeof(int));

  // a simple approximation to the required extent
  // basically get the whole extent for an axis unless a fully
  // contained subset is being requested. If so then use that.
  for (idx = 0; idx < 3; idx++)
    {
    if (outExt[idx*2] >= wExtent[idx*2] &&
	outExt[idx*2+1] <= wExtent[idx*2+1])
      {
      inExt[idx*2] = outExt[idx*2];
      inExt[idx*2+1] = outExt[idx*2+1];
      }
    }
}

//----------------------------------------------------------------------------
template <class T>
static void vtkImageMirrorPadExecute(vtkImageMirrorPad *self,
				     vtkImageData *inData,
				     vtkImageData *outData, T *outPtr,
				     int outExt[6], int id)
{
  int idxC, idxX, idxY, idxZ;
  int maxX, maxY, maxZ;
  int inInc[3];
  int inIncStart[3];
  int inIncX, inIncY, inIncZ;
  int outIncX, outIncY, outIncZ;
  unsigned long count = 0;
  unsigned long target;
  int *wExtent = self->GetInput()->GetWholeExtent();
  int pad[6], idx;
  int inIdxStart[3];
  int inIdx[3];
  T *inPtr, *inPtrX, *inPtrY, *inPtrZ;
  int maxC, inMaxC;

  // find the region to loop over
  inMaxC = inData->GetNumberOfScalarComponents();
  maxC = outData->GetNumberOfScalarComponents();
  maxX = outExt[1] - outExt[0];
  maxY = outExt[3] - outExt[2];
  maxZ = outExt[5] - outExt[4];
  target = (unsigned long)((maxZ+1)*(maxY+1)/50.0);
  target++;

  // Get increments to march through data
  inData->GetIncrements(inIncX, inIncY, inIncZ);
  outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ);

  // how much padding is required ?
  // if padding is required on a boundary then we know we need the whole extent
  // for that boundary. The following code handles the cases where the outputextent
  // is all inside or outside of the whole extent
  for (idx = 0; idx < 3; idx++)
    {
    pad[idx*2] = 0;
    pad[idx*2+1] = 0;
    if (outExt[idx*2] < wExtent[idx*2])
      {
      pad[idx*2] = wExtent[idx*2] - outExt[idx*2];
      }
    if (outExt[idx*2+1] > wExtent[idx*2+1])
      {
      pad[idx*2+1] = outExt[idx*2+1] - wExtent[idx*2+1];
      }
    }

  // find the starting point
  for (idx = 0; idx < 3; idx++)
    {
    inIdxStart[idx] = outExt[idx*2];
    inIncStart[idx] = 1;
    while (inIdxStart[idx] < wExtent[idx*2])
      {
      inIncStart[idx] = -inIncStart[idx];
      inIdxStart[idx] = inIdxStart[idx] + (wExtent[idx*2+1] - wExtent[idx*2] + 1);
      }
    while (inIdxStart[idx] > wExtent[idx*2+1])
      {
      inIncStart[idx] = -inIncStart[idx];
      inIdxStart[idx] = inIdxStart[idx] - (wExtent[idx*2+1] - wExtent[idx*2] + 1);
      }
    // if we are heading negative then we need to mirror the offset
    if (inIncStart[idx] < 0)
      {
      inIdxStart[idx] = wExtent[idx*2+1] - inIdxStart[idx] + wExtent[idx*2];
      }
    }
  inPtr = (T *)inData->GetScalarPointer(inIdxStart[0], inIdxStart[1], inIdxStart[2]);

  // Loop through ouput pixels
  inPtrZ = inPtr;
  inIdx[2] = inIdxStart[2];
  inInc[2] = inIncStart[2];
  for (idxZ = 0; idxZ <= maxZ; idxZ++)
    {
    inPtrY = inPtrZ;
    inIdx[1] = inIdxStart[1];
    inInc[1] = inIncStart[1];
    for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++)
      {
      inPtrX = inPtrY;
      inIdx[0] = inIdxStart[0];
      inInc[0] = inIncStart[0];
      if (!id)
	{
	if (!(count%target))
	  {
	  self->UpdateProgress(count/(50.0*target));
	  }
	count++;
	}

      // if components are same much faster
      if ((maxC == inMaxC) && (maxC == 1))
	{
	for (idxX = 0; idxX <= maxX; idxX++)
	  {
	  // Pixel operation
	  *outPtr = *inPtrX;
	  outPtr++;
	  inIdx[0] += inInc[0];
	  inPtrX = inPtrX + inInc[0]*inIncX;
	  if (inIdx[0] < wExtent[0] || inIdx[0] > wExtent[1])
	    {
	    inInc[0] *= -1;
	    inIdx[0] += inInc[0];
	    inPtrX = inPtrX + inInc[0]*inIncX;
	    }
	  }
	}
      else // components are not the same
	{
	for (idxX = 0; idxX <= maxX; idxX++)
	  {
	  for (idxC = 0; idxC < maxC; idxC++)
	    {
	    // Pixel operation
	    if (idxC < inMaxC)
	      {
	      *outPtr = *(inPtrX + idxC);
	      }
	    else
	      {
	      *outPtr = *(inPtrX + idxC%inMaxC);
	      }
	    outPtr++;
	    }
	  inIdx[0] += inInc[0];
	  inPtrX = inPtrX + inInc[0]*inIncX;
	  if (inIdx[0] < wExtent[0] || inIdx[0] > wExtent[1])
	    {
	    inInc[0] *= -1;
	    inIdx[0] += inInc[0];
	    inPtrX = inPtrX + inInc[0]*inIncX;
	    }
	  }
	}

      outPtr += outIncY;
      inIdx[1] += inInc[1];
      inPtrY = inPtrY + inInc[1]*inIncY;
      if (inIdx[1] < wExtent[2] || inIdx[1] > wExtent[3])
	{
	inInc[1] *= -1;
	inIdx[1] += inInc[1];
	inPtrY = inPtrY + inInc[1]*inIncY;
	}
      }
    outPtr += outIncZ;
    inIdx[2] += inInc[2];
    inPtrZ = inPtrZ + inInc[2]*inIncZ;
    if (inIdx[2] < wExtent[4] || inIdx[2] > wExtent[5])
      {
      inInc[2] *= -1;
      inIdx[2] += inInc[2];
      inPtrZ = inPtrZ + inInc[2]*inIncZ;
      }
    }
}

//----------------------------------------------------------------------------
// This method is passed a input and output data, and executes the filter
// algorithm to fill the output from the input.
// It just executes a switch statement to call the correct function for
// the regions data types.
void vtkImageMirrorPad::ThreadedExecute(vtkImageData *inData,
					vtkImageData *outData,
					int outExt[6], int id)
{
  void *outPtr = outData->GetScalarPointerForExtent(outExt);

  vtkDebugMacro(<< "Execute: inData = " << inData
		<< ", outData = " << outData);

  // this filter expects that input is the same type as output.
  if (inData->GetScalarType() != outData->GetScalarType())
    {
    vtkErrorMacro(<< "Execute: input ScalarType, " << inData->GetScalarType()
                  << ", must match out ScalarType " << outData->GetScalarType());
    return;
    }

  switch (inData->GetScalarType())
    {
    case VTK_DOUBLE:
      vtkImageMirrorPadExecute(this, inData, outData,
			       (double *)(outPtr), outExt, id);
      break;
    case VTK_FLOAT:
      vtkImageMirrorPadExecute(this, inData, outData,
			       (float *)(outPtr), outExt, id);
      break;
    case VTK_LONG:
      vtkImageMirrorPadExecute(this, inData, outData,
			       (long *)(outPtr), outExt, id);
      break;
    case VTK_UNSIGNED_LONG:
      vtkImageMirrorPadExecute(this, inData, outData,
			       (unsigned long *)(outPtr), outExt, id);
      break;
    case VTK_INT:
      vtkImageMirrorPadExecute(this, inData, outData,
			       (int *)(outPtr), outExt, id);
      break;
    case VTK_UNSIGNED_INT:
      vtkImageMirrorPadExecute(this, inData, outData,
			       (unsigned int *)(outPtr), outExt, id);
      break;
    case VTK_SHORT:
      vtkImageMirrorPadExecute(this, inData, outData,
			       (short *)(outPtr), outExt, id);
      break;
    case VTK_UNSIGNED_SHORT:
      vtkImageMirrorPadExecute(this, inData, outData,
			       (unsigned short *)(outPtr), outExt, id);
      break;
    case VTK_CHAR:
      vtkImageMirrorPadExecute(this, inData, outData,
			       (char *)(outPtr), outExt, id);
      break;
    case VTK_UNSIGNED_CHAR:
      vtkImageMirrorPadExecute(this, inData, outData,
			       (unsigned char *)(outPtr), outExt, id);
      break;
    default:
      vtkErrorMacro(<< "Execute: Unknown ScalarType");
      return;
    }
}

<commit_msg>ERR: removed warnings.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkImageMirrorPad.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$
  Thanks:    Thanks to C. Charles Law who developed this class.

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

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

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

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

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

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

#include "vtkImageMirrorPad.h"

//----------------------------------------------------------------------------
// Just clip the request.
void vtkImageMirrorPad::ComputeRequiredInputUpdateExtent(int inExt[6],
							 int outExt[6])
{
  int *wExtent = this->GetInput()->GetWholeExtent();
  int idx;

  // initialize inExt
  memcpy(inExt,wExtent,6*sizeof(int));

  // a simple approximation to the required extent
  // basically get the whole extent for an axis unless a fully
  // contained subset is being requested. If so then use that.
  for (idx = 0; idx < 3; idx++)
    {
    if (outExt[idx*2] >= wExtent[idx*2] &&
	outExt[idx*2+1] <= wExtent[idx*2+1])
      {
      inExt[idx*2] = outExt[idx*2];
      inExt[idx*2+1] = outExt[idx*2+1];
      }
    }
}

//----------------------------------------------------------------------------
template <class T>
static void vtkImageMirrorPadExecute(vtkImageMirrorPad *self,
				     vtkImageData *inData,
				     vtkImageData *outData, T *outPtr,
				     int outExt[6], int id)
{
  int idxC, idxX, idxY, idxZ;
  int maxX, maxY, maxZ;
  int inInc[3];
  int inIncStart[3];
  int inIncX, inIncY, inIncZ;
  int outIncX, outIncY, outIncZ;
  unsigned long count = 0;
  unsigned long target;
  int *wExtent = self->GetInput()->GetWholeExtent();
  int idx;
  int inIdxStart[3];
  int inIdx[3];
  T *inPtr, *inPtrX, *inPtrY, *inPtrZ;
  int maxC, inMaxC;

  // find the region to loop over
  inMaxC = inData->GetNumberOfScalarComponents();
  maxC = outData->GetNumberOfScalarComponents();
  maxX = outExt[1] - outExt[0];
  maxY = outExt[3] - outExt[2];
  maxZ = outExt[5] - outExt[4];
  target = (unsigned long)((maxZ+1)*(maxY+1)/50.0);
  target++;

  // Get increments to march through data
  inData->GetIncrements(inIncX, inIncY, inIncZ);
  outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ);

  // find the starting point
  for (idx = 0; idx < 3; idx++)
    {
    inIdxStart[idx] = outExt[idx*2];
    inIncStart[idx] = 1;
    while (inIdxStart[idx] < wExtent[idx*2])
      {
      inIncStart[idx] = -inIncStart[idx];
      inIdxStart[idx] = inIdxStart[idx] + (wExtent[idx*2+1] - wExtent[idx*2] + 1);
      }
    while (inIdxStart[idx] > wExtent[idx*2+1])
      {
      inIncStart[idx] = -inIncStart[idx];
      inIdxStart[idx] = inIdxStart[idx] - (wExtent[idx*2+1] - wExtent[idx*2] + 1);
      }
    // if we are heading negative then we need to mirror the offset
    if (inIncStart[idx] < 0)
      {
      inIdxStart[idx] = wExtent[idx*2+1] - inIdxStart[idx] + wExtent[idx*2];
      }
    }
  inPtr = (T *)inData->GetScalarPointer(inIdxStart[0], inIdxStart[1], inIdxStart[2]);

  // Loop through ouput pixels
  inPtrZ = inPtr;
  inIdx[2] = inIdxStart[2];
  inInc[2] = inIncStart[2];
  for (idxZ = 0; idxZ <= maxZ; idxZ++)
    {
    inPtrY = inPtrZ;
    inIdx[1] = inIdxStart[1];
    inInc[1] = inIncStart[1];
    for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++)
      {
      inPtrX = inPtrY;
      inIdx[0] = inIdxStart[0];
      inInc[0] = inIncStart[0];
      if (!id)
	{
	if (!(count%target))
	  {
	  self->UpdateProgress(count/(50.0*target));
	  }
	count++;
	}

      // if components are same much faster
      if ((maxC == inMaxC) && (maxC == 1))
	{
	for (idxX = 0; idxX <= maxX; idxX++)
	  {
	  // Pixel operation
	  *outPtr = *inPtrX;
	  outPtr++;
	  inIdx[0] += inInc[0];
	  inPtrX = inPtrX + inInc[0]*inIncX;
	  if (inIdx[0] < wExtent[0] || inIdx[0] > wExtent[1])
	    {
	    inInc[0] *= -1;
	    inIdx[0] += inInc[0];
	    inPtrX = inPtrX + inInc[0]*inIncX;
	    }
	  }
	}
      else // components are not the same
	{
	for (idxX = 0; idxX <= maxX; idxX++)
	  {
	  for (idxC = 0; idxC < maxC; idxC++)
	    {
	    // Pixel operation
	    if (idxC < inMaxC)
	      {
	      *outPtr = *(inPtrX + idxC);
	      }
	    else
	      {
	      *outPtr = *(inPtrX + idxC%inMaxC);
	      }
	    outPtr++;
	    }
	  inIdx[0] += inInc[0];
	  inPtrX = inPtrX + inInc[0]*inIncX;
	  if (inIdx[0] < wExtent[0] || inIdx[0] > wExtent[1])
	    {
	    inInc[0] *= -1;
	    inIdx[0] += inInc[0];
	    inPtrX = inPtrX + inInc[0]*inIncX;
	    }
	  }
	}

      outPtr += outIncY;
      inIdx[1] += inInc[1];
      inPtrY = inPtrY + inInc[1]*inIncY;
      if (inIdx[1] < wExtent[2] || inIdx[1] > wExtent[3])
	{
	inInc[1] *= -1;
	inIdx[1] += inInc[1];
	inPtrY = inPtrY + inInc[1]*inIncY;
	}
      }
    outPtr += outIncZ;
    inIdx[2] += inInc[2];
    inPtrZ = inPtrZ + inInc[2]*inIncZ;
    if (inIdx[2] < wExtent[4] || inIdx[2] > wExtent[5])
      {
      inInc[2] *= -1;
      inIdx[2] += inInc[2];
      inPtrZ = inPtrZ + inInc[2]*inIncZ;
      }
    }
}

//----------------------------------------------------------------------------
// This method is passed a input and output data, and executes the filter
// algorithm to fill the output from the input.
// It just executes a switch statement to call the correct function for
// the regions data types.
void vtkImageMirrorPad::ThreadedExecute(vtkImageData *inData,
					vtkImageData *outData,
					int outExt[6], int id)
{
  void *outPtr = outData->GetScalarPointerForExtent(outExt);

  vtkDebugMacro(<< "Execute: inData = " << inData
		<< ", outData = " << outData);

  // this filter expects that input is the same type as output.
  if (inData->GetScalarType() != outData->GetScalarType())
    {
    vtkErrorMacro(<< "Execute: input ScalarType, " << inData->GetScalarType()
                  << ", must match out ScalarType " << outData->GetScalarType());
    return;
    }

  switch (inData->GetScalarType())
    {
    case VTK_DOUBLE:
      vtkImageMirrorPadExecute(this, inData, outData,
			       (double *)(outPtr), outExt, id);
      break;
    case VTK_FLOAT:
      vtkImageMirrorPadExecute(this, inData, outData,
			       (float *)(outPtr), outExt, id);
      break;
    case VTK_LONG:
      vtkImageMirrorPadExecute(this, inData, outData,
			       (long *)(outPtr), outExt, id);
      break;
    case VTK_UNSIGNED_LONG:
      vtkImageMirrorPadExecute(this, inData, outData,
			       (unsigned long *)(outPtr), outExt, id);
      break;
    case VTK_INT:
      vtkImageMirrorPadExecute(this, inData, outData,
			       (int *)(outPtr), outExt, id);
      break;
    case VTK_UNSIGNED_INT:
      vtkImageMirrorPadExecute(this, inData, outData,
			       (unsigned int *)(outPtr), outExt, id);
      break;
    case VTK_SHORT:
      vtkImageMirrorPadExecute(this, inData, outData,
			       (short *)(outPtr), outExt, id);
      break;
    case VTK_UNSIGNED_SHORT:
      vtkImageMirrorPadExecute(this, inData, outData,
			       (unsigned short *)(outPtr), outExt, id);
      break;
    case VTK_CHAR:
      vtkImageMirrorPadExecute(this, inData, outData,
			       (char *)(outPtr), outExt, id);
      break;
    case VTK_UNSIGNED_CHAR:
      vtkImageMirrorPadExecute(this, inData, outData,
			       (unsigned char *)(outPtr), outExt, id);
      break;
    default:
      vtkErrorMacro(<< "Execute: Unknown ScalarType");
      return;
    }
}

<|endoftext|>


<commit_before>#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

#include <cstdio>
#include <iostream>

using namespace cv;
using namespace std;

Mat markerMask, img;
Point prevPt(-1, -1);

void onMouse( int event, int x, int y, int flags, void* )
{
    if( x < 0 || x >= img.cols || y < 0 || y >= img.rows )
        return;
    if( event == CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON) )
        prevPt = Point(-1,-1);
    else if( event == CV_EVENT_LBUTTONDOWN )
        prevPt = Point(x,y);
    else if( event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON) )
    {
        Point pt(x, y);
        if( prevPt.x < 0 )
            prevPt = pt;
        line( markerMask, prevPt, pt, Scalar::all(255), 5, 8, 0 );
        line( img, prevPt, pt, Scalar::all(255), 5, 8, 0 );
        prevPt = pt;
        imshow("image", img);
    }
}

int main( int argc, char** argv )
{
    char* filename = argc >= 2 ? argv[1] : (char*)"fruits.jpg";
    Mat img0 = imread(filename, 1), imgGray;

    if( img0.empty() )
    {
        cout << "Usage: watershed <image_name>\n";
        return 0;
    }

    cout << "Hot keys: \n"
            "\tESC - quit the program\n"
            "\tr - restore the original image\n"
            "\tw or SPACE - run watershed algorithm\n"
            "\t\t(before running it, roughly mark the areas on the image)\n"
            "\t  (before that, roughly outline several markers on the image)\n";

    namedWindow( "image", 1 );

    img0.copyTo(img);
    cvtColor(img, markerMask, CV_BGR2GRAY);
    cvtColor(markerMask, imgGray, CV_GRAY2BGR);
    markerMask = Scalar::all(0);
    imshow( "image", img );
    setMouseCallback( "image", onMouse, 0 );

    for(;;)
    {
        int c = waitKey(0);

        if( (char)c == 27 )
            break;

        if( (char)c == 'r' )
        {
            markerMask = Scalar::all(0);
            img0.copyTo(img);
            imshow( "image", img );
        }

        if( (char)c == 'w' || (char)c == ' ' )
        {
            int i, j, compCount = 0;
            vector<vector<Point> > contours;
            vector<Vec4i> hierarchy;

            findContours(markerMask, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);

            Mat markers(markerMask.size(), CV_32S);
            markers = Scalar::all(0);
            int idx = 0;
            for( ; idx >= 0; idx = hierarchy[idx][0], compCount++ )
                drawContours(markers, contours, idx, Scalar::all(compCount+1), -1, 8, hierarchy, INT_MAX);

            if( compCount == 0 )
                continue;

            vector<Vec3b> colorTab;
            for( i = 0; i < compCount; i++ )
            {
                int b = theRNG().uniform(0, 255);
                int g = theRNG().uniform(0, 255);
                int r = theRNG().uniform(0, 255);

                colorTab.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));
            }

            double t = (double)getTickCount();
            watershed( img0, markers );
            t = (double)getTickCount() - t;
            printf( "execution time = %gms\n", t*1000./getTickFrequency() );

            Mat wshed(markers.size(), CV_8UC3);

            // paint the watershed image
            for( i = 0; i < markers.rows; i++ )
                for( j = 0; j < markers.cols; j++ )
                {
                    int idx = markers.at<int>(i,j);
                    if( idx == -1 )
                        wshed.at<Vec3b>(i,j) = Vec3b(255,255,255);
                    else if( idx <= 0 || idx > compCount )
                        wshed.at<Vec3b>(i,j) = Vec3b(0,0,0);
                    else
                        wshed.at<Vec3b>(i,j) = colorTab[idx - 1];
                }

            wshed = wshed*0.5 + imgGray*0.5;
            imshow( "watershed transform", wshed );
        }
    }

    return 0;
}
<commit_msg>revamped<commit_after>#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

#include <cstdio>
#include <iostream>

using namespace cv;
using namespace std;

void help()
{
	cout << "\nThis program demonstrates the famous watershed segmentation algorithm in OpenCV: watershed()\n"
			"Usage:\n"
			"./watershed [image_name -- default is fruits.jpg]\n" << endl;

	cout << "Hot keys: \n"
		"\tESC - quit the program\n"
		"\tr - restore the original image\n"
		"\tw or SPACE - run watershed segmentation algorithm\n"
		"\t\t(before running it, *roughly* mark the areas to segment on the image)\n"
		"\t  (before that, roughly outline several markers on the image)\n";
}
Mat markerMask, img;
Point prevPt(-1, -1);

void onMouse( int event, int x, int y, int flags, void* )
{
    if( x < 0 || x >= img.cols || y < 0 || y >= img.rows )
        return;
    if( event == CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON) )
        prevPt = Point(-1,-1);
    else if( event == CV_EVENT_LBUTTONDOWN )
        prevPt = Point(x,y);
    else if( event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON) )
    {
        Point pt(x, y);
        if( prevPt.x < 0 )
            prevPt = pt;
        line( markerMask, prevPt, pt, Scalar::all(255), 5, 8, 0 );
        line( img, prevPt, pt, Scalar::all(255), 5, 8, 0 );
        prevPt = pt;
        imshow("image", img);
    }
}

int main( int argc, char** argv )
{
    char* filename = argc >= 2 ? argv[1] : (char*)"fruits.jpg";
    Mat img0 = imread(filename, 1), imgGray;

    if( img0.empty() )
    {
        cout << "Couldn'g open image " << filename << ". Usage: watershed <image_name>\n";
        return 0;
    }
    help();
    namedWindow( "image", 1 );

    img0.copyTo(img);
    cvtColor(img, markerMask, CV_BGR2GRAY);
    cvtColor(markerMask, imgGray, CV_GRAY2BGR);
    markerMask = Scalar::all(0);
    imshow( "image", img );
    setMouseCallback( "image", onMouse, 0 );

    for(;;)
    {
        int c = waitKey(0);

        if( (char)c == 27 )
            break;

        if( (char)c == 'r' )
        {
            markerMask = Scalar::all(0);
            img0.copyTo(img);
            imshow( "image", img );
        }

        if( (char)c == 'w' || (char)c == ' ' )
        {
            int i, j, compCount = 0;
            vector<vector<Point> > contours;
            vector<Vec4i> hierarchy;

            findContours(markerMask, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);

            Mat markers(markerMask.size(), CV_32S);
            markers = Scalar::all(0);
            int idx = 0;
            for( ; idx >= 0; idx = hierarchy[idx][0], compCount++ )
                drawContours(markers, contours, idx, Scalar::all(compCount+1), -1, 8, hierarchy, INT_MAX);

            if( compCount == 0 )
                continue;

            vector<Vec3b> colorTab;
            for( i = 0; i < compCount; i++ )
            {
                int b = theRNG().uniform(0, 255);
                int g = theRNG().uniform(0, 255);
                int r = theRNG().uniform(0, 255);

                colorTab.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));
            }

            double t = (double)getTickCount();
            watershed( img0, markers );
            t = (double)getTickCount() - t;
            printf( "execution time = %gms\n", t*1000./getTickFrequency() );

            Mat wshed(markers.size(), CV_8UC3);

            // paint the watershed image
            for( i = 0; i < markers.rows; i++ )
                for( j = 0; j < markers.cols; j++ )
                {
                    int idx = markers.at<int>(i,j);
                    if( idx == -1 )
                        wshed.at<Vec3b>(i,j) = Vec3b(255,255,255);
                    else if( idx <= 0 || idx > compCount )
                        wshed.at<Vec3b>(i,j) = Vec3b(0,0,0);
                    else
                        wshed.at<Vec3b>(i,j) = colorTab[idx - 1];
                }

            wshed = wshed*0.5 + imgGray*0.5;
            imshow( "watershed transform", wshed );
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>#ifndef IMPORTER_NODESTORESPARSE_HPP
#define IMPORTER_NODESTORESPARSE_HPP

#include <google/sparsetable>
#include <memory>

class NodestoreSparse : public Nodestore {
private:
    /**
     * Size of one allocated memory block
     */
    const static size_t BLOCK_SIZE = 512*1024*1024;

    typedef std::vector< char* > memoryBlocks_t;
    typedef std::vector< char* >::const_iterator memoryBlocks_cit;

    /**
     * list of all allocated memory blocks
     */
    memoryBlocks_t memoryBlocks;

    /**
     * pointer to the first byte of the currently used memory block
     */
    char* currentMemoryBlock;

    /**
     * number of bytes already used in the currentMemoryBlock
     */
    size_t currentMemoryBlockPosition;

    char* allocateNewMemoryBlock() {
        currentMemoryBlock = static_cast< char* >(malloc(BLOCK_SIZE));
        currentMemoryBlockPosition = 0;
        memoryBlocks.push_back(currentMemoryBlock);
        return currentMemoryBlock;
    }

    void freeAllMemoryBlocks() {
        memoryBlocks_cit end = memoryBlocks.end();
        for(memoryBlocks_cit it = memoryBlocks.begin(); it != end; ++it) {
            free(*it);
        }
        memoryBlocks.clear();
    }

    /**
     * the information stored for each node, packed into ints
     */
    struct PackedNodeTimeinfo {
        /**
         * osmium gives us a time_t which is a signed int
         * on 32 bit platformsm time_t is 4 bytes wide and it will overflow on year 2038
         * on 64 bit platforms, time_t is 8 bytes wide and will not overflow during the next decades
         * we know that osm did not exists before 1970, so there is no need to encode times prior to that point
         * using this knowledge we can extend the reach of our unix timestamp by ~60 years by using an unsigned
         * 8 byte int. this gives us best of both worlds: a smaller memory footprint and enough time to buy more ram
         * (as of today's 2013: 93 years. should be enough for everybody.)
         */
        uint32_t t;

        /**
         * the version is not really required and only required for debugging output
         */
        uint32_t v;

        /**
         * osmium handles lat/lon either as double (8 bytes) or as int32_t (4 byted). So we choose the smaller one.
         */
        int32_t lat;

        /**
         * same as for lat
         */
        int32_t lon;
    };

    static const int nodeSeparatorSite = sizeof(((PackedNodeTimeinfo *)0)->t);

    /**
     * sparse table, mapping node ids to their positions in a memory block
     */
    google::sparsetable< PackedNodeTimeinfo* > idMap;

    osm_object_id_t lastNodeId;

public:
    NodestoreSparse() : Nodestore(), memoryBlocks(), idMap(), lastNodeId() {
        allocateNewMemoryBlock();
    }
    ~NodestoreSparse() {
        freeAllMemoryBlocks();
    }

    void record(osm_object_id_t id, osm_version_t v, time_t t, double lon, double lat) {
        // remember: sorting is guaranteed nodes, ways relations in ascending id and then version order
        PackedNodeTimeinfo *infoPtr;

        // test if there is enough space for another PackedNodeTimeinfo
        if(currentMemoryBlockPosition + sizeof(PackedNodeTimeinfo) >= BLOCK_SIZE) {
            std::cerr << "memory block is full, repaging is nyi" << std::endl;
            throw new std::runtime_error("nyi");
        }

        if(lastNodeId != id) {
            // new node
            if(currentMemoryBlockPosition > 0) {
                if(isPrintingDebugMessages()) {
                    std::cerr << "adding 0-separator of " << nodeSeparatorSite << " bytes after memory position " << currentMemoryBlockPosition << std::endl;
                }
                currentMemoryBlockPosition += nodeSeparatorSite;

            }

            // no memory segment for this node yet
            infoPtr = reinterpret_cast< PackedNodeTimeinfo* >(currentMemoryBlock + currentMemoryBlockPosition);

            if(isPrintingDebugMessages()) {
                std::cerr << "assigning memory position " << infoPtr << " (offset: " << currentMemoryBlockPosition << ") to node id #" << id << std::endl;
            }

            idMap.resize(id+1);
            idMap[id] = infoPtr;
        }
        else {
            // no memory segment for this node yet
            infoPtr = reinterpret_cast< PackedNodeTimeinfo* >(currentMemoryBlock + currentMemoryBlockPosition);
        }

        if(isPrintingDebugMessages()) {
            std::cerr << "storing node id #" << id << "v" << v << " at memory position " << infoPtr << " (offset: " << currentMemoryBlockPosition << ")" << std::endl;
        }

        infoPtr->t = t;
        infoPtr->v = v;
        infoPtr->lat = Osmium::OSM::double_to_fix(lat);
        infoPtr->lon = Osmium::OSM::double_to_fix(lon);

        // mark end of memory for this node
        infoPtr++;
        infoPtr->t = 0;

        currentMemoryBlockPosition += sizeof(PackedNodeTimeinfo);
        lastNodeId = id;
    }

    // actually we don't need the coordinates here, only the time stamps
    // so we could return a simple time vector. it actually is only a timemap
    // because this was more easy to implement in the stl store, but once we
    // change the default from stl to sparse, we can change the return value, too
    timemap_ptr lookup(osm_object_id_t id, bool &found) {
        if(!idMap.test(id)) {
           if(isPrintingStoreErrors()) {
                std::cerr << "no timemap for node #" << id << ", skipping node" << std::endl;
            }

            found = false;
            return timemap_ptr();
        }

        PackedNodeTimeinfo *infoPtr = idMap[id];
        timemap_ptr tMap(new timemap());

        if(isPrintingDebugMessages()) {
            std::cerr << "acessing node id #" << id << " starting from memory position " << infoPtr << std::endl;
        }

        Nodeinfo info;
        do {
            if(isPrintingDebugMessages()) {
                std::cerr << "found node id #" << id << "v" << infoPtr->v << " at memory position " << infoPtr << std::endl;
            }
            info.lat = Osmium::OSM::fix_to_double(infoPtr->lat);
            info.lon = Osmium::OSM::fix_to_double(infoPtr->lon);
            tMap->insert(timepair(infoPtr->t, info));
        } while((++infoPtr)->t != 0);

        found = true;
        return tMap;
    }

    Nodeinfo lookup(osm_object_id_t id, time_t t, bool &found) {
        if(!idMap.test(id)) {
           if(isPrintingStoreErrors()) {
                std::cerr << "no timemap for node #" << id << ", skipping node" << std::endl;
            }

            found = false;
            return nullinfo;
        }

        PackedNodeTimeinfo *infoPtr = idMap[id];
        if(isPrintingDebugMessages()) {
            std::cerr << "acessing node id #" << id << " starting from memory position " << infoPtr << std::endl;
        }

        Nodeinfo info = nullinfo;
        time_t infoTime = 0;

        // find the oldest node-version younger then t
        do {
            if(infoPtr->t <= t && infoPtr->t >= infoTime) {
                info.lat = Osmium::OSM::fix_to_double(infoPtr->lat);
                info.lon = Osmium::OSM::fix_to_double(infoPtr->lon);
                infoTime = infoPtr->t;
            }
        } while((++infoPtr)->t != 0);

        if(isPrintingDebugMessages()) {
            std::cerr << "found node-info from t=" << infoTime << std::endl;
        }

        found = (infoTime > 0);
        return info;
    }
};

#endif // IMPORTER_NODESTORESPARSE_HPP
<commit_msg>use bigger steps to increment map size<commit_after>#ifndef IMPORTER_NODESTORESPARSE_HPP
#define IMPORTER_NODESTORESPARSE_HPP

#include <google/sparsetable>
#include <memory>

class NodestoreSparse : public Nodestore {
private:
    /**
     * Size of one allocated memory block
     */
    const static size_t BLOCK_SIZE = 512*1024*1024;
    const static osm_object_id_t EST_MAX_NODE_ID = 2^31; // soon 2^32
    const static osm_object_id_t NODE_BUFFER_STEPS = 2^16; // soon 2^32

    typedef std::vector< char* > memoryBlocks_t;
    typedef std::vector< char* >::const_iterator memoryBlocks_cit;

    /**
     * list of all allocated memory blocks
     */
    memoryBlocks_t memoryBlocks;

    /**
     * pointer to the first byte of the currently used memory block
     */
    char* currentMemoryBlock;

    /**
     * number of bytes already used in the currentMemoryBlock
     */
    size_t currentMemoryBlockPosition;

    char* allocateNewMemoryBlock() {
        currentMemoryBlock = static_cast< char* >(malloc(BLOCK_SIZE));
        currentMemoryBlockPosition = 0;
        memoryBlocks.push_back(currentMemoryBlock);
        return currentMemoryBlock;
    }

    void freeAllMemoryBlocks() {
        memoryBlocks_cit end = memoryBlocks.end();
        for(memoryBlocks_cit it = memoryBlocks.begin(); it != end; ++it) {
            free(*it);
        }
        memoryBlocks.clear();
    }

    /**
     * the information stored for each node, packed into ints
     */
    struct PackedNodeTimeinfo {
        /**
         * osmium gives us a time_t which is a signed int
         * on 32 bit platformsm time_t is 4 bytes wide and it will overflow on year 2038
         * on 64 bit platforms, time_t is 8 bytes wide and will not overflow during the next decades
         * we know that osm did not exists before 1970, so there is no need to encode times prior to that point
         * using this knowledge we can extend the reach of our unix timestamp by ~60 years by using an unsigned
         * 8 byte int. this gives us best of both worlds: a smaller memory footprint and enough time to buy more ram
         * (as of today's 2013: 93 years. should be enough for everybody.)
         */
        uint32_t t;

        /**
         * the version is not really required and only required for debugging output
         */
        uint32_t v;

        /**
         * osmium handles lat/lon either as double (8 bytes) or as int32_t (4 byted). So we choose the smaller one.
         */
        int32_t lat;

        /**
         * same as for lat
         */
        int32_t lon;
    };

    static const int nodeSeparatorSite = sizeof(((PackedNodeTimeinfo *)0)->t);

    /**
     * sparse table, mapping node ids to their positions in a memory block
     */
    google::sparsetable< PackedNodeTimeinfo* > idMap;

    osm_object_id_t maxNodeId;
    osm_object_id_t lastNodeId;

public:
    NodestoreSparse() : Nodestore(), memoryBlocks(), idMap(EST_MAX_NODE_ID), maxNodeId(EST_MAX_NODE_ID), lastNodeId() {
        allocateNewMemoryBlock();
    }
    ~NodestoreSparse() {
        freeAllMemoryBlocks();
    }

    void record(osm_object_id_t id, osm_version_t v, time_t t, double lon, double lat) {
        // remember: sorting is guaranteed nodes, ways relations in ascending id and then version order
        PackedNodeTimeinfo *infoPtr;

        // test if there is enough space for another PackedNodeTimeinfo
        if(currentMemoryBlockPosition + sizeof(PackedNodeTimeinfo) >= BLOCK_SIZE) {
            std::cerr << "memory block is full, repaging is nyi" << std::endl;
            throw new std::runtime_error("nyi");
        }

        if(lastNodeId != id) {
            // new node
            if(currentMemoryBlockPosition > 0) {
                if(isPrintingDebugMessages()) {
                    std::cerr << "adding 0-separator of " << nodeSeparatorSite << " bytes after memory position " << currentMemoryBlockPosition << std::endl;
                }
                currentMemoryBlockPosition += nodeSeparatorSite;

            }

            // no memory segment for this node yet
            infoPtr = reinterpret_cast< PackedNodeTimeinfo* >(currentMemoryBlock + currentMemoryBlockPosition);

            if(isPrintingDebugMessages()) {
                std::cerr << "assigning memory position " << infoPtr << " (offset: " << currentMemoryBlockPosition << ") to node id #" << id << std::endl;
            }

            if(id > maxNodeId) {
                idMap.resize(id + NODE_BUFFER_STEPS + 1);
                maxNodeId = id + NODE_BUFFER_STEPS;
            }
            idMap[id] = infoPtr;
        }
        else {
            // no memory segment for this node yet
            infoPtr = reinterpret_cast< PackedNodeTimeinfo* >(currentMemoryBlock + currentMemoryBlockPosition);
        }

        if(isPrintingDebugMessages()) {
            std::cerr << "storing node id #" << id << "v" << v << " at memory position " << infoPtr << " (offset: " << currentMemoryBlockPosition << ")" << std::endl;
        }

        infoPtr->t = t;
        infoPtr->v = v;
        infoPtr->lat = Osmium::OSM::double_to_fix(lat);
        infoPtr->lon = Osmium::OSM::double_to_fix(lon);

        // mark end of memory for this node
        infoPtr++;
        infoPtr->t = 0;

        currentMemoryBlockPosition += sizeof(PackedNodeTimeinfo);
        lastNodeId = id;
    }

    // actually we don't need the coordinates here, only the time stamps
    // so we could return a simple time vector. it actually is only a timemap
    // because this was more easy to implement in the stl store, but once we
    // change the default from stl to sparse, we can change the return value, too
    timemap_ptr lookup(osm_object_id_t id, bool &found) {
        if(!idMap.test(id)) {
           if(isPrintingStoreErrors()) {
                std::cerr << "no timemap for node #" << id << ", skipping node" << std::endl;
            }

            found = false;
            return timemap_ptr();
        }

        PackedNodeTimeinfo *infoPtr = idMap[id];
        timemap_ptr tMap(new timemap());

        if(isPrintingDebugMessages()) {
            std::cerr << "acessing node id #" << id << " starting from memory position " << infoPtr << std::endl;
        }

        Nodeinfo info;
        do {
            if(isPrintingDebugMessages()) {
                std::cerr << "found node id #" << id << "v" << infoPtr->v << " at memory position " << infoPtr << std::endl;
            }
            info.lat = Osmium::OSM::fix_to_double(infoPtr->lat);
            info.lon = Osmium::OSM::fix_to_double(infoPtr->lon);
            tMap->insert(timepair(infoPtr->t, info));
        } while((++infoPtr)->t != 0);

        found = true;
        return tMap;
    }

    Nodeinfo lookup(osm_object_id_t id, time_t t, bool &found) {
        if(!idMap.test(id)) {
           if(isPrintingStoreErrors()) {
                std::cerr << "no timemap for node #" << id << ", skipping node" << std::endl;
            }

            found = false;
            return nullinfo;
        }

        PackedNodeTimeinfo *infoPtr = idMap[id];
        if(isPrintingDebugMessages()) {
            std::cerr << "acessing node id #" << id << " starting from memory position " << infoPtr << std::endl;
        }

        Nodeinfo info = nullinfo;
        time_t infoTime = 0;

        // find the oldest node-version younger then t
        do {
            if(infoPtr->t <= t && infoPtr->t >= infoTime) {
                info.lat = Osmium::OSM::fix_to_double(infoPtr->lat);
                info.lon = Osmium::OSM::fix_to_double(infoPtr->lon);
                infoTime = infoPtr->t;
            }
        } while((++infoPtr)->t != 0);

        if(isPrintingDebugMessages()) {
            std::cerr << "found node-info from t=" << infoTime << std::endl;
        }

        found = (infoTime > 0);
        return info;
    }
};

#endif // IMPORTER_NODESTORESPARSE_HPP
<|endoftext|>


<commit_before>/**************************************************************************
 * celestialBody.cxx
 * Written by Durk Talsma. Originally started October 1997, for distribution
 * with the FlightGear project. Version 2 was written in August and
 * September 1998. This code is based upon algorithms and data kindly
 * provided by Mr. Paul Schlyter. (pausch@saaf.se).
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id$
 * (Log is kept at end of this file)
 **************************************************************************/

#include "celestialBody.hxx"
#include "star.hxx"
#include <Debug/logstream.hxx>

#ifdef __BORLANDC__
#  define exception c_exception
#endif
#include <math.h>

/**************************************************************************
 * void CelestialBody::updatePosition(fgTIME *t, Star *ourSun)
 *
 * Basically, this member function provides a general interface for
 * calculating the right ascension and declinaion. This function is
 * used for calculating the planetary positions. For the planets, an
 * overloaded member function is provided to additionally calculate the
 * planet's magnitude.
 * The sun and moon have their own overloaded updatePosition member, as their
 * position is calculated an a slightly different manner.
 *
 * arguments:
 * fgTIME t: provides the current time.
 * Star *ourSun: the sun's position is needed to convert heliocentric
 *               coordinates into geocentric coordinates.
 *
 * return value: none
 *
 *************************************************************************/
void CelestialBody::updatePosition(fgTIME *t, Star *ourSun)
{
  double eccAnom, v, ecl, actTime,
    xv, yv, xh, yh, zh, xg, yg, zg, xe, ye, ze;

  updateOrbElements(t);
  actTime = fgCalcActTime(t);

  // calcualate the angle bewteen ecliptic and equatorial coordinate system
  ecl = DEG_TO_RAD * (23.4393 - 3.563E-7 *actTime);

  eccAnom = fgCalcEccAnom(M, e);  //calculate the eccentric anomaly
  xv = a * (cos(eccAnom) - e);
  yv = a * (sqrt (1.0 - e*e) * sin(eccAnom));
  v = atan2(yv, xv);           // the planet's true anomaly
  r = sqrt (xv*xv + yv*yv);    // the planet's distance

  // calculate the planet's position in 3D space
  xh = r * (cos(N) * cos(v+w) - sin(N) * sin(v+w) * cos(i));
  yh = r * (sin(N) * cos(v+w) + cos(N) * sin(v+w) * cos(i));
  zh = r * (sin(v+w) * sin(i));

  // calculate the ecliptic longitude and latitude
  xg = xh + ourSun->getxs();
  yg = yh + ourSun->getys();
  zg = zh;

  xe = xg;
  ye = yg * cos(ecl) - zg * sin(ecl);
  ze = yg * sin(ecl) + zg * cos(ecl);
  rightAscension = atan2(ye, xe);
  declination = atan2(ze, sqrt(xe*xe + ye*ye));
  FG_LOG(FG_GENERAL, FG_INFO, "Planet found at : "
	 << rightAscension << " (ra), " << declination << " (dec)" );

  //calculate some variables specific to calculating the magnitude
  //of the planet
  R = sqrt (xg*xg + yg*yg + zg*zg);
  s = ourSun->getDistance();
  FV = RAD_TO_DEG * acos( (r*r + R*R - s*s) / (2*r*R));
};

/****************************************************************************
 * double CelestialBody::fgCalcEccAnom(double M, double e)
 * this private member calculates the eccentric anomaly of a celestial body,
 * given its mean anomaly and eccentricity.
 *
 * -Mean anomaly: the approximate angle between the perihelion and the current
 *  position. this angle increases uniformly with time.
 *
 * True anomaly: the actual angle between perihelion and current position.
 *
 * Eccentric anomaly: this is an auxilary angle, used in calculating the true
 * anomaly from the mean anomaly.
 *
 * -eccentricity. Indicates the amount in which the orbit deviates from a
 *  circle (0 = circle, 0-1, is ellipse, 1 = parabola, > 1 = hyperbola).
 *
 * This function is also known as solveKeplersEquation()
 *
 * arguments:
 * M: the mean anomaly
 * e: the eccentricity
 *
 * return value:
 * the eccentric anomaly
 *
 ****************************************************************************/
double CelestialBody::fgCalcEccAnom(double M, double e)
{
  double
    eccAnom, E0, E1, diff;

  eccAnom = M + e * sin(M) * (1.0 + e * cos (M));
  // iterate to achieve a greater precision for larger eccentricities
  if (e > 0.05)
    {
      E0 = eccAnom;
      do
	{
	  E1 = E0 - (E0 - e * sin(E0) - M) / (1 - e *cos(E0));
	  diff = fabs(E0 - E1);
	  E0 = E1;
	}
      while (diff > (DEG_TO_RAD * 0.001));
      return E0;
    }
  return eccAnom;
}

<commit_msg>math domain error fix from Charlie Hotchkiss.<commit_after>/**************************************************************************
 * celestialBody.cxx
 * Written by Durk Talsma. Originally started October 1997, for distribution
 * with the FlightGear project. Version 2 was written in August and
 * September 1998. This code is based upon algorithms and data kindly
 * provided by Mr. Paul Schlyter. (pausch@saaf.se).
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id$
 * (Log is kept at end of this file)
 **************************************************************************/

#include "celestialBody.hxx"
#include "star.hxx"
#include <Debug/logstream.hxx>

#ifdef FG_MATH_EXCEPTION_CLASH
#  define exception c_exception
#endif
#include <math.h>

/**************************************************************************
 * void CelestialBody::updatePosition(fgTIME *t, Star *ourSun)
 *
 * Basically, this member function provides a general interface for
 * calculating the right ascension and declinaion. This function is
 * used for calculating the planetary positions. For the planets, an
 * overloaded member function is provided to additionally calculate the
 * planet's magnitude.
 * The sun and moon have their own overloaded updatePosition member, as their
 * position is calculated an a slightly different manner.
 *
 * arguments:
 * fgTIME t: provides the current time.
 * Star *ourSun: the sun's position is needed to convert heliocentric
 *               coordinates into geocentric coordinates.
 *
 * return value: none
 *
 *************************************************************************/
void CelestialBody::updatePosition(fgTIME *t, Star *ourSun)
{
  double eccAnom, v, ecl, actTime,
    xv, yv, xh, yh, zh, xg, yg, zg, xe, ye, ze;

  updateOrbElements(t);
  actTime = fgCalcActTime(t);

  // calcualate the angle bewteen ecliptic and equatorial coordinate system
  ecl = DEG_TO_RAD * (23.4393 - 3.563E-7 *actTime);

  eccAnom = fgCalcEccAnom(M, e);  //calculate the eccentric anomaly
  xv = a * (cos(eccAnom) - e);
  yv = a * (sqrt (1.0 - e*e) * sin(eccAnom));
  v = atan2(yv, xv);           // the planet's true anomaly
  r = sqrt (xv*xv + yv*yv);    // the planet's distance

  // calculate the planet's position in 3D space
  xh = r * (cos(N) * cos(v+w) - sin(N) * sin(v+w) * cos(i));
  yh = r * (sin(N) * cos(v+w) + cos(N) * sin(v+w) * cos(i));
  zh = r * (sin(v+w) * sin(i));

  // calculate the ecliptic longitude and latitude
  xg = xh + ourSun->getxs();
  yg = yh + ourSun->getys();
  zg = zh;

  xe = xg;
  ye = yg * cos(ecl) - zg * sin(ecl);
  ze = yg * sin(ecl) + zg * cos(ecl);
  rightAscension = atan2(ye, xe);
  declination = atan2(ze, sqrt(xe*xe + ye*ye));
  FG_LOG(FG_GENERAL, FG_INFO, "Planet found at : "
	 << rightAscension << " (ra), " << declination << " (dec)" );

  //calculate some variables specific to calculating the magnitude
  //of the planet
  R = sqrt (xg*xg + yg*yg + zg*zg);
  s = ourSun->getDistance();

  // It is possible from these calculations for the argument to acos
  // to exceed the valid range for acos(). So we do a little extra
  // checking.

  double tmp = (r*r + R*R - s*s) / (2*r*R);
  if ( tmp > 1.0) {
      tmp = 1.0;
  } else if ( tmp < -1.0) {
      tmp = -1.0;
  }

  FV = RAD_TO_DEG * acos( tmp );
};

/****************************************************************************
 * double CelestialBody::fgCalcEccAnom(double M, double e)
 * this private member calculates the eccentric anomaly of a celestial body,
 * given its mean anomaly and eccentricity.
 *
 * -Mean anomaly: the approximate angle between the perihelion and the current
 *  position. this angle increases uniformly with time.
 *
 * True anomaly: the actual angle between perihelion and current position.
 *
 * Eccentric anomaly: this is an auxilary angle, used in calculating the true
 * anomaly from the mean anomaly.
 *
 * -eccentricity. Indicates the amount in which the orbit deviates from a
 *  circle (0 = circle, 0-1, is ellipse, 1 = parabola, > 1 = hyperbola).
 *
 * This function is also known as solveKeplersEquation()
 *
 * arguments:
 * M: the mean anomaly
 * e: the eccentricity
 *
 * return value:
 * the eccentric anomaly
 *
 ****************************************************************************/
double CelestialBody::fgCalcEccAnom(double M, double e)
{
  double
    eccAnom, E0, E1, diff;

  eccAnom = M + e * sin(M) * (1.0 + e * cos (M));
  // iterate to achieve a greater precision for larger eccentricities
  if (e > 0.05)
    {
      E0 = eccAnom;
      do
	{
	  E1 = E0 - (E0 - e * sin(E0) - M) / (1 - e *cos(E0));
	  diff = fabs(E0 - E1);
	  E0 = E1;
	}
      while (diff > (DEG_TO_RAD * 0.001));
      return E0;
    }
  return eccAnom;
}

<|endoftext|>


<commit_before>#include "hackypassabilityagent.h"

#include <QQuickItem>
#include <QQuickWindow>

#include "quickentity.h"
#include "utils.h"

HackyPassabilityAgent::HackyPassabilityAgent() :
    mGridItem(nullptr)
{
}

bool HackyPassabilityAgent::isPassable(const QPointF &pos, AbstractEntity *entity)
{
    if (!mGridItem)
        return false;

    QuickEntity *quickEntity = dynamic_cast<QuickEntity*>(entity);
    Q_ASSERT(quickEntity);

    // very basic, hacky check that doesn't take into account a radius.
    QQuickItem *child = mGridItem->childAt(pos.x(), pos.y());
    if (child->property("blocksMovement").toBool()) {
        return false;
    }

    return true;
}

QQuickItem *HackyPassabilityAgent::gridItem() const
{
    return mGridItem;
}

void HackyPassabilityAgent::setGridItem(QQuickItem *gridItem)
{
    if (gridItem == mGridItem)
        return;

    mGridItem = gridItem;
    emit gridItemChanged();
}
<commit_msg>Fix null pointer access in HackyPassabilityAgent<commit_after>#include "hackypassabilityagent.h"

#include <QQuickItem>
#include <QQuickWindow>

#include "quickentity.h"
#include "utils.h"

HackyPassabilityAgent::HackyPassabilityAgent() :
    mGridItem(nullptr)
{
}

bool HackyPassabilityAgent::isPassable(const QPointF &pos, AbstractEntity *entity)
{
    if (!mGridItem)
        return false;

    QuickEntity *quickEntity = dynamic_cast<QuickEntity*>(entity);
    Q_ASSERT(quickEntity);

    // very basic, hacky check that doesn't take into account a radius.
    QQuickItem *child = mGridItem->childAt(pos.x(), pos.y());
    if (child && child->property("blocksMovement").toBool()) {
        return false;
    }

    return true;
}

QQuickItem *HackyPassabilityAgent::gridItem() const
{
    return mGridItem;
}

void HackyPassabilityAgent::setGridItem(QQuickItem *gridItem)
{
    if (gridItem == mGridItem)
        return;

    mGridItem = gridItem;
    emit gridItemChanged();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: fuline.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2004-07-12 15:03:16 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#pragma hdrstop

#include "fuline.hxx"

#include <svx/svxids.hrc>
#ifndef _SVX_TAB_LINE_HXX //autogen
#include <svx/tabline.hxx>
#endif
#ifndef _XENUM_HXX //autogen
#include <svx/xenum.hxx>
#endif
#ifndef _SV_MSGBOX_HXX //autogen
#include <vcl/msgbox.hxx>
#endif
#ifndef _SFXINTITEM_HXX //autogen
#include <svtools/intitem.hxx>
#endif
#ifndef _SFXSTRITEM_HXX //autogen
#include <svtools/stritem.hxx>
#endif
#ifndef _SFXREQUEST_HXX //autogen
#include <sfx2/request.hxx>
#endif
#ifndef _XDEF_HXX //autogen
#include <svx/xdef.hxx>
#endif
#ifndef _SFX_BINDINGS_HXX //autogen
#include <sfx2/bindings.hxx>
#endif
#ifndef _SFXVIEWFRM_HXX
#include <sfx2/viewfrm.hxx>
#endif

#ifndef SD_VIEW_SHELL_HXX
#include "ViewShell.hxx"
#endif
#ifndef SD_VIEW_HXX
#include "View.hxx"
#endif
#ifndef SD_WINDOW_SHELL_HXX
#include "Window.hxx"
#endif
#include "drawdoc.hxx"
#include "app.hrc"
#include <svx/svxdlg.hxx> //CHINA001
#include <svx/dialogs.hrc> //CHINA001

namespace sd {

TYPEINIT1( FuLine, FuPoor );

/*************************************************************************
|*
|* Konstruktor
|*
\************************************************************************/

FuLine::FuLine (
    ViewShell* pViewSh,
    ::sd::Window* pWin,
    ::sd::View* pView,
    SdDrawDocument* pDoc,
    SfxRequest& rReq)
    : FuPoor(pViewSh, pWin, pView, pDoc, rReq)
{
    BOOL        bHasMarked = pView->AreObjectsMarked();

    const SfxItemSet* pArgs = rReq.GetArgs();

    if( !pArgs )
    {
        // erst einmal alle eingabeparameter fuer den dialog retten
        SfxItemSet aInputAttr( pDoc->GetPool() );
        pView->GetAttributes( aInputAttr );

        const XLineStyleItem &rILineStyleItem = (const XLineStyleItem &) aInputAttr.Get (XATTR_LINESTYLE);
        XLineStyle           eILineStyle      = rILineStyleItem.GetValue ();

        const XLineDashItem  &rILineDashItem  = (const XLineDashItem &) aInputAttr.Get (XATTR_LINEDASH);
        const XDash          &rIDash          = rILineDashItem.GetValue ();

        const XLineWidthItem &rILineWidthItem = (const XLineWidthItem &) aInputAttr.Get (XATTR_LINEWIDTH);
        long                 nILineWidth      = rILineWidthItem.GetValue ();

        const XLineColorItem &rILineColorItem = (const XLineColorItem &) aInputAttr.Get (XATTR_LINECOLOR);
        const Color          &rIColor         = rILineColorItem.GetValue ();

        const SdrObject* pObj = NULL;
        const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
        if( rMarkList.GetMarkCount() == 1 )
            pObj = rMarkList.GetMark(0)->GetObj();

        SfxItemSet* pNewAttr = new SfxItemSet( pDoc->GetPool() );
        pView->GetAttributes( *pNewAttr );

        //CHINA001 SvxLineTabDialog* pDlg = new SvxLineTabDialog( NULL, pNewAttr, pDoc, pObj, bHasMarked );
        SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
        DBG_ASSERT(pFact, "Dialogdiet Factory fail!");//CHINA001
        SfxAbstractTabDialog * pDlg = pFact->CreateSvxLineTabDialog(NULL,
                    pNewAttr,
                    pDoc,
                ResId(RID_SVXDLG_LINE),
                pObj,
                bHasMarked);
        DBG_ASSERT(pDlg, "Dialogdiet fail!");//CHINA001
        if ( pDlg->Execute() == RET_OK )
        {
            // die ausgabeparameter des dialogs bestimmen
            SfxItemSet           *pOutputAttr     = (SfxItemSet *) pDlg->GetOutputItemSet();

            const XLineStyleItem &rOLineStyleItem = (const XLineStyleItem &) pOutputAttr->Get (XATTR_LINESTYLE);
            XLineStyle           eOLineStyle      = rOLineStyleItem.GetValue ();

            const XLineDashItem  &rOLineDashItem  = (const XLineDashItem &) pOutputAttr->Get (XATTR_LINEDASH);
            const XDash          &rODash          = rOLineDashItem.GetValue ();

            const XLineWidthItem &rOLineWidthItem = (const XLineWidthItem &) pOutputAttr->Get (XATTR_LINEWIDTH);
            long                 nOLineWidth      = rOLineWidthItem.GetValue ();

            const XLineColorItem &rOLineColorItem = (const XLineColorItem &) pOutputAttr->Get (XATTR_LINECOLOR);
            const Color          &rOColor         = rOLineColorItem.GetValue ();

            pView->SetAttributes (*(pDlg->GetOutputItemSet ()));
        }

        // Attribute wurden geaendert, Listboxes in Objectbars muessen aktualisiert werden
        static USHORT SidArray[] = {
                        SID_ATTR_LINE_STYLE,
                        SID_ATTR_LINE_DASH,
                        SID_ATTR_LINE_WIDTH,
                        SID_ATTR_LINE_COLOR,
                        0 };

        pViewShell->GetViewFrame()->GetBindings().Invalidate( SidArray );

        delete pDlg;
        delete pNewAttr;
    }

    rReq.Ignore ();
}

} // end of namespace sd
<commit_msg>INTEGRATION: CWS ooo19126 (1.5.428); FILE MERGED 2005/09/05 13:22:17 rt 1.5.428.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: fuline.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 04:43:57 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/

#pragma hdrstop

#include "fuline.hxx"

#include <svx/svxids.hrc>
#ifndef _SVX_TAB_LINE_HXX //autogen
#include <svx/tabline.hxx>
#endif
#ifndef _XENUM_HXX //autogen
#include <svx/xenum.hxx>
#endif
#ifndef _SV_MSGBOX_HXX //autogen
#include <vcl/msgbox.hxx>
#endif
#ifndef _SFXINTITEM_HXX //autogen
#include <svtools/intitem.hxx>
#endif
#ifndef _SFXSTRITEM_HXX //autogen
#include <svtools/stritem.hxx>
#endif
#ifndef _SFXREQUEST_HXX //autogen
#include <sfx2/request.hxx>
#endif
#ifndef _XDEF_HXX //autogen
#include <svx/xdef.hxx>
#endif
#ifndef _SFX_BINDINGS_HXX //autogen
#include <sfx2/bindings.hxx>
#endif
#ifndef _SFXVIEWFRM_HXX
#include <sfx2/viewfrm.hxx>
#endif

#ifndef SD_VIEW_SHELL_HXX
#include "ViewShell.hxx"
#endif
#ifndef SD_VIEW_HXX
#include "View.hxx"
#endif
#ifndef SD_WINDOW_SHELL_HXX
#include "Window.hxx"
#endif
#include "drawdoc.hxx"
#include "app.hrc"
#include <svx/svxdlg.hxx> //CHINA001
#include <svx/dialogs.hrc> //CHINA001

namespace sd {

TYPEINIT1( FuLine, FuPoor );

/*************************************************************************
|*
|* Konstruktor
|*
\************************************************************************/

FuLine::FuLine (
    ViewShell* pViewSh,
    ::sd::Window* pWin,
    ::sd::View* pView,
    SdDrawDocument* pDoc,
    SfxRequest& rReq)
    : FuPoor(pViewSh, pWin, pView, pDoc, rReq)
{
    BOOL        bHasMarked = pView->AreObjectsMarked();

    const SfxItemSet* pArgs = rReq.GetArgs();

    if( !pArgs )
    {
        // erst einmal alle eingabeparameter fuer den dialog retten
        SfxItemSet aInputAttr( pDoc->GetPool() );
        pView->GetAttributes( aInputAttr );

        const XLineStyleItem &rILineStyleItem = (const XLineStyleItem &) aInputAttr.Get (XATTR_LINESTYLE);
        XLineStyle           eILineStyle      = rILineStyleItem.GetValue ();

        const XLineDashItem  &rILineDashItem  = (const XLineDashItem &) aInputAttr.Get (XATTR_LINEDASH);
        const XDash          &rIDash          = rILineDashItem.GetValue ();

        const XLineWidthItem &rILineWidthItem = (const XLineWidthItem &) aInputAttr.Get (XATTR_LINEWIDTH);
        long                 nILineWidth      = rILineWidthItem.GetValue ();

        const XLineColorItem &rILineColorItem = (const XLineColorItem &) aInputAttr.Get (XATTR_LINECOLOR);
        const Color          &rIColor         = rILineColorItem.GetValue ();

        const SdrObject* pObj = NULL;
        const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
        if( rMarkList.GetMarkCount() == 1 )
            pObj = rMarkList.GetMark(0)->GetObj();

        SfxItemSet* pNewAttr = new SfxItemSet( pDoc->GetPool() );
        pView->GetAttributes( *pNewAttr );

        //CHINA001 SvxLineTabDialog* pDlg = new SvxLineTabDialog( NULL, pNewAttr, pDoc, pObj, bHasMarked );
        SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
        DBG_ASSERT(pFact, "Dialogdiet Factory fail!");//CHINA001
        SfxAbstractTabDialog * pDlg = pFact->CreateSvxLineTabDialog(NULL,
                    pNewAttr,
                    pDoc,
                ResId(RID_SVXDLG_LINE),
                pObj,
                bHasMarked);
        DBG_ASSERT(pDlg, "Dialogdiet fail!");//CHINA001
        if ( pDlg->Execute() == RET_OK )
        {
            // die ausgabeparameter des dialogs bestimmen
            SfxItemSet           *pOutputAttr     = (SfxItemSet *) pDlg->GetOutputItemSet();

            const XLineStyleItem &rOLineStyleItem = (const XLineStyleItem &) pOutputAttr->Get (XATTR_LINESTYLE);
            XLineStyle           eOLineStyle      = rOLineStyleItem.GetValue ();

            const XLineDashItem  &rOLineDashItem  = (const XLineDashItem &) pOutputAttr->Get (XATTR_LINEDASH);
            const XDash          &rODash          = rOLineDashItem.GetValue ();

            const XLineWidthItem &rOLineWidthItem = (const XLineWidthItem &) pOutputAttr->Get (XATTR_LINEWIDTH);
            long                 nOLineWidth      = rOLineWidthItem.GetValue ();

            const XLineColorItem &rOLineColorItem = (const XLineColorItem &) pOutputAttr->Get (XATTR_LINECOLOR);
            const Color          &rOColor         = rOLineColorItem.GetValue ();

            pView->SetAttributes (*(pDlg->GetOutputItemSet ()));
        }

        // Attribute wurden geaendert, Listboxes in Objectbars muessen aktualisiert werden
        static USHORT SidArray[] = {
                        SID_ATTR_LINE_STYLE,
                        SID_ATTR_LINE_DASH,
                        SID_ATTR_LINE_WIDTH,
                        SID_ATTR_LINE_COLOR,
                        0 };

        pViewShell->GetViewFrame()->GetBindings().Invalidate( SidArray );

        delete pDlg;
        delete pNewAttr;
    }

    rReq.Ignore ();
}

} // end of namespace sd
<|endoftext|>


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

#include "DmaConfigProxy.h"
#include "DmaIndicationWrapper.h"
#include "StdDmaIndication.h"
#include "GeneratedTypes.h"
#include "HdmiDisplayRequestProxy.h"
#include "HdmiDisplayIndicationWrapper.h"
#include "HdmiInternalIndicationWrapper.h"
#include "HdmiInternalRequestProxy.h"
#include "portal.h"
#include <stdio.h>
#include <sys/mman.h>
#include <ctype.h>
#include "i2chdmi.h"
#include "edid.h"

#define FRAME_COUNT 2
#define MAX_PIXEL 256
#define INCREMENT_PIXEL 2

static HdmiInternalRequestProxy *hdmiInternal;
static HdmiDisplayRequestProxy *device;
static DmaConfigProxy *dma;
static PortalAlloc *portalAlloc[FRAME_COUNT];
static unsigned int ref_srcAlloc[FRAME_COUNT];
static int *dataptr[FRAME_COUNT];
static int frame_index;
static int nlines = 1080;
static int npixels = 1920;
static int fbsize = nlines*npixels*4;

void dump(const char *prefix, char *buf, size_t len)
{
    fprintf(stderr, "%s: ", prefix);
    for (int i = 0; i < 16; i++)
	fprintf(stderr, "%02x", (unsigned char)buf[i]);
    fprintf(stderr, "\n");
}

static void *thread_routine(void *data)
{
    fprintf(stderr, "Calling portalExec\n");
    portalExec(0);
    fprintf(stderr, "portalExec returned ???\n");
    return data;
}

static int corner[] = {0, -1, 0xf00f, 0x0fff};
static int corner_index;
static void fill_pixels(int offset)
{
    int *ptr = dataptr[frame_index];
    for (int line = 0; line < nlines; line++)
      for (int pixel = 0; pixel < npixels; pixel++) {
	int v = ((((MAX_PIXEL *  line) /  nlines)+offset) % MAX_PIXEL) << 16
	       | ((((MAX_PIXEL * pixel) / npixels)+offset) % MAX_PIXEL);
        if (!v)
            v = 1;
        if (line < 20 && pixel < 20)
            v = corner[(corner_index+0) % 4];
        if (line < 30 && pixel > npixels - 40)
            v = corner[(corner_index+1) % 4];
        if (line > nlines - 20 && pixel < 20)
            v = corner[(corner_index+2) % 4];
        if (line > nlines - 30 && pixel > npixels - 40)
            v = corner[(corner_index+3) % 4];
        if (line < 20 && pixel % 20 < 2)
            v = corner[(corner_index+0) % 4];
        if (line % 30 < 2 && pixel > npixels - 40)
            v = corner[(corner_index+1) % 4];
	ptr[line * npixels + pixel] = v;
      }
    corner_index = offset/16;
    dma->dCacheFlushInval(portalAlloc[frame_index], dataptr[frame_index]);
    device->startFrameBuffer(ref_srcAlloc[frame_index], fbsize);
    hdmiInternal->setTestPattern(0);
    hdmiInternal->waitForVsync(0);
    frame_index = 1 - frame_index;
}

static int synccount = 0;
static long long totalcount;
static int number;
class HdmiIndication : public HdmiInternalIndicationWrapper {
public:
    HdmiIndication(int id) : HdmiInternalIndicationWrapper(id) {}
  virtual void vsync ( uint64_t v, uint32_t w ) {
      static int base = 0;

totalcount += v;
number += w;
      fill_pixels(base);
base += INCREMENT_PIXEL;
      if (synccount++ >= 20) {
          synccount = 0;
uint32_t zeros = v & 0xffffffff, pix = v >> 32;
          fprintf(stderr, "[%s] v %llx pix=%x:%d. zero=%x:%d. w=%x:%d.\n", __FUNCTION__,v,pix,pix,zeros,zeros,w,w);
      }
    }
};
class DisplayIndication : public HdmiDisplayIndicationWrapper {
public:
    DisplayIndication(int id) : HdmiDisplayIndicationWrapper(id) {}
    virtual void transferStarted ( uint32_t v ) {
      fprintf(stderr, "[%s:%d] v=%d\n", __FUNCTION__, __LINE__, v);
    }
    virtual void transferFinished ( uint32_t v ) {
      fprintf(stderr, "[%s:%d] v=%d\n", __FUNCTION__, __LINE__, v);
    }
    virtual void transferStats ( uint32_t count, uint32_t cycles, uint64_t sumcycles ) {
	fprintf(stderr, "[%s:%d] count=%d cycles=%d sumcycles=%lld avgcycles=%f\n", __FUNCTION__, __LINE__, count, cycles, sumcycles, (double)sumcycles / count);
    }
};

int main(int argc, const char **argv)
{
    PortalPoller *poller = 0;
    DmaIndicationWrapper *dmaIndication;

    poller = new PortalPoller();
    device = new HdmiDisplayRequestProxy(IfcNames_HdmiDisplayRequest, poller);
    dma = new DmaConfigProxy(IfcNames_DmaConfig);
    dmaIndication = new DmaIndication(dma, IfcNames_DmaIndication);
    HdmiInternalIndicationWrapper *hdmiIndication = new HdmiIndication(IfcNames_HdmiInternalIndication);
    HdmiDisplayIndicationWrapper *displayIndication = new DisplayIndication(IfcNames_HdmiDisplayIndication);
    hdmiInternal = new HdmiInternalRequestProxy(IfcNames_HdmiInternalRequest);

    // read out monitor EDID from ADV7511
    struct edid edid;
    init_i2c_hdmi();
    int i2cfd = open("/dev/i2c-0", O_RDWR);
    fprintf(stderr, "Monitor EDID:\n");
    for (int i = 0; i < 256; i++) {
      edid.raw[i] = i2c_read_reg(i2cfd, 0x3f, i);
      fprintf(stderr, " %02x", edid.raw[i]);
      if ((i % 16) == 15) {
	fprintf(stderr, " ");
	for (int j = i-15; j <= i; j++) {
	  unsigned char c = edid.raw[j];
	  fprintf(stderr, "%c", (isprint(c) && isascii(c)) ? c : '.');
	}
	fprintf(stderr, "\n");
      }
    }
    close(i2cfd);
    parseEdid(edid);

    device->stopFrameBuffer();

    pthread_t thread;
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_create(&thread, &attr, thread_routine, 0);

    int status;
    status = poller->setClockFrequency(0, 100000000, 0);

    for (int i = 0; i < 4; i++) {
      int pixclk = (long)edid.timing[i].pixclk * 10000;
      if ((pixclk > 0) && (pixclk < 148000000)) {
	nlines = edid.timing[i].nlines;    // number of visible lines
	npixels = edid.timing[i].npixels;
	int vblank = edid.timing[i].blines; // number of blanking lines
	int hblank = edid.timing[i].bpixels;
	int vsyncoff = edid.timing[i].vsyncoff; // number of lines in FrontPorch (within blanking)
	int hsyncoff = edid.timing[i].hsyncoff;
	int vsyncwidth = edid.timing[i].vsyncwidth; // width of Sync (within blanking)
	int hsyncwidth = edid.timing[i].hsyncwidth;

	fprintf(stderr, "lines %d, pixels %d, vblank %d, hblank %d, vwidth %d, hwidth %d\n",
             nlines, npixels, vblank, hblank, vsyncwidth, hsyncwidth);
	fprintf(stderr, "Using pixclk %d calc_pixclk %d npixels %d nlines %d\n",
		pixclk,
		60l * (long)(hblank + npixels) * (long)(vblank + nlines),
		npixels, nlines);
	status = poller->setClockFrequency(1, pixclk, 0);

	hdmiInternal->setDeLine(vsyncoff,           // End of FrontPorch
                                vsyncoff+vsyncwidth,// End of Sync
                                vblank,             // Start of Visible (start of BackPorch)
                                vblank + nlines, vblank + nlines / 2); // End
        hdmiInternal->setDePixel(hsyncoff,
                                hsyncoff+hsyncwidth, hblank,
                                hblank + npixels, hblank + npixels / 2);
	break;
      }
    }

    fbsize = nlines*npixels*4;

    for (int i = 0; i < FRAME_COUNT; i++) {
        int err = dma->alloc(fbsize, &portalAlloc[i]);
        dataptr[i] = (int*)mmap(0, fbsize, PROT_READ|PROT_WRITE, MAP_SHARED, portalAlloc[i]->header.fd, 0);
        memset(dataptr[i], i ? 0xff : 0, fbsize);
        fprintf(stderr, "calling dma->reference\n");
        ref_srcAlloc[i] = dma->reference(portalAlloc[i]);
    }

    fprintf(stderr, "first mem_stats=%10u\n", dma->show_mem_stats(ChannelType_Read));
    sleep(3);
    fprintf(stderr, "Starting frame buffer ref=%d...", ref_srcAlloc[0]);
    fill_pixels(0);
    fprintf(stderr, "done\n");
    while (1) {
      fprintf(stderr, "mem_stats=%10u\n", dma->show_mem_stats(ChannelType_Read));
      sleep(1);
    }
}
<commit_msg>hdmidisplay now works on both zedboard and zc702<commit_after>/* Copyright (c) 2014 Quanta Research Cambridge, Inc
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include "DmaConfigProxy.h"
#include "DmaIndicationWrapper.h"
#include "StdDmaIndication.h"
#include "GeneratedTypes.h"
#include "HdmiDisplayRequestProxy.h"
#include "HdmiDisplayIndicationWrapper.h"
#include "HdmiInternalIndicationWrapper.h"
#include "HdmiInternalRequestProxy.h"
#include "portal.h"
#include <stdio.h>
#include <sys/mman.h>
#include <ctype.h>
#include "i2chdmi.h"
#include "edid.h"

#define FRAME_COUNT 2
#define MAX_PIXEL 256
#define INCREMENT_PIXEL 2

static HdmiInternalRequestProxy *hdmiInternal;
static HdmiDisplayRequestProxy *device;
static DmaConfigProxy *dma;
static PortalAlloc *portalAlloc[FRAME_COUNT];
static unsigned int ref_srcAlloc[FRAME_COUNT];
static int *dataptr[FRAME_COUNT];
static int frame_index;
static int nlines = 1080;
static int npixels = 1920;
static int fbsize = nlines*npixels*4;

void dump(const char *prefix, char *buf, size_t len)
{
    fprintf(stderr, "%s: ", prefix);
    for (int i = 0; i < 16; i++)
	fprintf(stderr, "%02x", (unsigned char)buf[i]);
    fprintf(stderr, "\n");
}

static void *thread_routine(void *data)
{
    fprintf(stderr, "Calling portalExec\n");
    portalExec(0);
    fprintf(stderr, "portalExec returned ???\n");
    return data;
}

static int corner[] = {0, -1, 0xf00f, 0x0fff};
static int corner_index;
static void fill_pixels(int offset)
{
    int *ptr = dataptr[frame_index];
    for (int line = 0; line < nlines; line++)
      for (int pixel = 0; pixel < npixels; pixel++) {
	int v = ((((MAX_PIXEL *  line) /  nlines)+offset) % MAX_PIXEL) << 16
	       | ((((MAX_PIXEL * pixel) / npixels)+offset) % MAX_PIXEL);
        if (!v)
            v = 1;
        if (line < 20 && pixel < 20)
            v = corner[(corner_index+0) % 4];
        if (line < 30 && pixel > npixels - 40)
            v = corner[(corner_index+1) % 4];
        if (line > nlines - 20 && pixel < 20)
            v = corner[(corner_index+2) % 4];
        if (line > nlines - 30 && pixel > npixels - 40)
            v = corner[(corner_index+3) % 4];
        if (line < 20 && pixel % 20 < 2)
            v = corner[(corner_index+0) % 4];
        if (line % 30 < 2 && pixel > npixels - 40)
            v = corner[(corner_index+1) % 4];
	ptr[line * npixels + pixel] = v;
      }
    corner_index = offset/16;
    dma->dCacheFlushInval(portalAlloc[frame_index], dataptr[frame_index]);
    device->startFrameBuffer(ref_srcAlloc[frame_index], fbsize);
    hdmiInternal->setTestPattern(0);
    hdmiInternal->waitForVsync(0);
    frame_index = 1 - frame_index;
}

static int synccount = 0;
static long long totalcount;
static int number;
class HdmiIndication : public HdmiInternalIndicationWrapper {
public:
    HdmiIndication(int id) : HdmiInternalIndicationWrapper(id) {}
  virtual void vsync ( uint64_t v, uint32_t w ) {
      static int base = 0;

totalcount += v;
number += w;
      fill_pixels(base);
base += INCREMENT_PIXEL;
      if (synccount++ >= 20) {
          synccount = 0;
uint32_t zeros = v & 0xffffffff, pix = v >> 32;
          fprintf(stderr, "[%s] v %llx pix=%x:%d. zero=%x:%d. w=%x:%d.\n", __FUNCTION__,v,pix,pix,zeros,zeros,w,w);
      }
    }
};
class DisplayIndication : public HdmiDisplayIndicationWrapper {
public:
    DisplayIndication(int id) : HdmiDisplayIndicationWrapper(id) {}
    virtual void transferStarted ( uint32_t v ) {
      fprintf(stderr, "[%s:%d] v=%d\n", __FUNCTION__, __LINE__, v);
    }
    virtual void transferFinished ( uint32_t v ) {
      fprintf(stderr, "[%s:%d] v=%d\n", __FUNCTION__, __LINE__, v);
    }
    virtual void transferStats ( uint32_t count, uint32_t cycles, uint64_t sumcycles ) {
	fprintf(stderr, "[%s:%d] count=%d cycles=%d sumcycles=%lld avgcycles=%f\n", __FUNCTION__, __LINE__, count, cycles, sumcycles, (double)sumcycles / count);
    }
};

int main(int argc, const char **argv)
{
    PortalPoller *poller = 0;
    DmaIndicationWrapper *dmaIndication;

    poller = new PortalPoller();
    device = new HdmiDisplayRequestProxy(IfcNames_HdmiDisplayRequest, poller);
    dma = new DmaConfigProxy(IfcNames_DmaConfig);
    dmaIndication = new DmaIndication(dma, IfcNames_DmaIndication);
    HdmiInternalIndicationWrapper *hdmiIndication = new HdmiIndication(IfcNames_HdmiInternalIndication);
    HdmiDisplayIndicationWrapper *displayIndication = new DisplayIndication(IfcNames_HdmiDisplayIndication);
    hdmiInternal = new HdmiInternalRequestProxy(IfcNames_HdmiInternalRequest);

    // read out monitor EDID from ADV7511
    struct edid edid;
    init_i2c_hdmi();
    int i2cfd = open("/dev/i2c-0", O_RDWR);
    fprintf(stderr, "Monitor EDID:\n");
    for (int i = 0; i < 256; i++) {
      edid.raw[i] = i2c_read_reg(i2cfd, 0x3f, i);
      fprintf(stderr, " %02x", edid.raw[i]);
      if ((i % 16) == 15) {
	fprintf(stderr, " ");
	for (int j = i-15; j <= i; j++) {
	  unsigned char c = edid.raw[j];
	  fprintf(stderr, "%c", (isprint(c) && isascii(c)) ? c : '.');
	}
	fprintf(stderr, "\n");
      }
    }
    close(i2cfd);
    parseEdid(edid);

    device->stopFrameBuffer();

    pthread_t thread;
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_create(&thread, &attr, thread_routine, 0);

    int status;
    status = poller->setClockFrequency(0, 100000000, 0);

    for (int i = 0; i < 4; i++) {
      int pixclk = (long)edid.timing[i].pixclk * 10000;
      if ((pixclk > 0) && (pixclk < 170000000)) {
	nlines = edid.timing[i].nlines;    // number of visible lines
	npixels = edid.timing[i].npixels;
	int vblank = edid.timing[i].blines; // number of blanking lines
	int hblank = edid.timing[i].bpixels;
	int vsyncoff = edid.timing[i].vsyncoff; // number of lines in FrontPorch (within blanking)
	int hsyncoff = edid.timing[i].hsyncoff;
	int vsyncwidth = edid.timing[i].vsyncwidth; // width of Sync (within blanking)
	int hsyncwidth = edid.timing[i].hsyncwidth;

	fprintf(stderr, "lines %d, pixels %d, vblank %d, hblank %d, vwidth %d, hwidth %d\n",
             nlines, npixels, vblank, hblank, vsyncwidth, hsyncwidth);
	fprintf(stderr, "Using pixclk %d calc_pixclk %d npixels %d nlines %d\n",
		pixclk,
		60l * (long)(hblank + npixels) * (long)(vblank + nlines),
		npixels, nlines);
	status = poller->setClockFrequency(1, pixclk, 0);
hblank--; // needed on zc702
	hdmiInternal->setDeLine(vsyncoff,           // End of FrontPorch
                                vsyncoff+vsyncwidth,// End of Sync
                                vblank,             // Start of Visible (start of BackPorch)
                                vblank + nlines, vblank + nlines / 2); // End
        hdmiInternal->setDePixel(hsyncoff,
                                hsyncoff+hsyncwidth, hblank,
                                hblank + npixels, hblank + npixels / 2);
	break;
      }
    }

    fbsize = nlines*npixels*4;

    for (int i = 0; i < FRAME_COUNT; i++) {
        int err = dma->alloc(fbsize, &portalAlloc[i]);
        dataptr[i] = (int*)mmap(0, fbsize, PROT_READ|PROT_WRITE, MAP_SHARED, portalAlloc[i]->header.fd, 0);
        memset(dataptr[i], i ? 0xff : 0, fbsize);
        fprintf(stderr, "calling dma->reference\n");
        ref_srcAlloc[i] = dma->reference(portalAlloc[i]);
    }

    fprintf(stderr, "first mem_stats=%10u\n", dma->show_mem_stats(ChannelType_Read));
    sleep(3);
    fprintf(stderr, "Starting frame buffer ref=%d...", ref_srcAlloc[0]);
    fill_pixels(0);
    fprintf(stderr, "done\n");
    while (1) {
      fprintf(stderr, "mem_stats=%10u\n", dma->show_mem_stats(ChannelType_Read));
      sleep(1);
    }
}
<|endoftext|>