Ejemplo n.º 1
0
// covert the number to decimal double
double Base2Decimal(const char* src, unsigned int src_base, unsigned int percision){
	unsigned int numSize = strlen(src);
	double digitPower = 0;
	double newNum = 0;
	int startNum = 0;
	int i = 0;
	unsigned int fracPointIndex = findPoint(src);

	// case of negative number
	(src[0] == '-') ? startNum = 1 : startNum = 0;

	// case there is no fraction point
	if (fracPointIndex == numSize)
		return (double)atoi(src);

	// create left side of fraction point
	for (i = fracPointIndex - 1; i >= startNum; --i)
		newNum += (pow(src_base, digitPower++))*(char2num(src[i]));

	digitPower = -1;
	// create right side of fraction point
	for (i = (int)fracPointIndex + 1; i < (int)numSize; ++i)
		newNum += (pow(src_base, digitPower--))*(char2num(src[i]));

	// case of negative number
	if (src[0] == '-')
		newNum = -(newNum);

	return newNum;
}
Ejemplo n.º 2
0
// calibration function to be run at the beginning only
vector<double> calibrate(){
	
	cvSmooth(frame, imageFiltree, CV_BLUR,seuilFiltre,seuilFiltre,0.0,0.0);
	cvCvtColor(imageFiltree, imageHSV,CV_BGR2HSV);
	cvInRangeS(imageHSV,cvScalar(hmin, smin, vmin, 0.0),cvScalar(hmax, smax, vmax, 0.0),imageBinaire);
	cvErode(imageBinaire, imageErodee, NULL, nbErosions);
	cvDilate(imageErodee, imageDilatee, NULL, nbDilatations);
	
	imageObjectRGB = multBinColor(imageDilatee, frame);
	imageObjectHSV = multBinColor(imageDilatee, imageHSV);
	
	vector<vector<CvPoint3D32f> > vecDistinctPoints = findPoint();
	
	// find the centroid of the object and trace it
	vector<CvPoint> centroid = centroiding(vecDistinctPoints);
	sort(centroid);
	
	vector<double> tanAlphaT = vector<double>(centroid.size(),0);
	double p;
	
	for (int i=0; i<centroid.size(); i++){
		p = abs(centroid[i].x - (frame->width / 2));
		tanAlphaT[i] = atan(d/D-p*ratioPixelSizeF);
	}
	return tanAlphaT;
}
Ejemplo n.º 3
0
bool TlevelsPage::TwidgetCurves::setCursor(void)
{
    POINT cp;
    GetCursorPos(&cp);
    ScreenToClient(h,&cp);
    std::pair<int,int> pt=findPoint(cp.x,cp.y);
    return pt.first>40?(curpoint=-1,false):(curpoint=pt.second,true);
}
Ejemplo n.º 4
0
void callback(int i)
{
	float time;
	clock_t t1, t2;
	
	// Start timer
	t1 = clock();
	
	// Filtering, HSV to Binary Image, Erosions and Dilations
	cvSmooth(frame, imageFiltree, CV_BLUR,seuilFiltre,seuilFiltre,0.0,0.0);
	cvCvtColor(imageFiltree, imageHSV,CV_BGR2HSV);
	cvInRangeS(imageHSV,cvScalar(hmin, smin, vmin, 0.0),cvScalar(hmax, smax, vmax, 0.0),imageBinaire);
	cvErode(imageBinaire, imageErodee, NULL, nbErosions);
	cvDilate(imageErodee, imageDilatee, NULL, nbDilatations);
	
	//imageDilateeFiltree =  lowPassFilter(imageDilatee); FILTER
	
	// multiplication between the original image in RGB and HSV and the binary image
	imageObjectRGB = multBinColor(imageDilatee, frame);
	imageObjectHSV = multBinColor(imageDilatee, imageHSV);
	
	// find the points and separate them (rows correspond to each point and the columns to the pixels belonging to the points)
	vector<vector<CvPoint3D32f> > vecDistinctPoints = findPoint();
	
	// find the centroid of the point and trace it
	vector<CvPoint> centroid = centroiding(vecDistinctPoints);
	// sort the centroids
	centroid = sort(centroid);
	
	// compute the distance with and without lens distortion
	vector<double> distance = findDistance(imageObjectHSV, centroid, tanAlphaT);
	
	// Contours
	/*cvFindContours( imageDilatee, storage, &contours, sizeof(CvContour),
	 CV_RETR_LIST, CV_CHAIN_APPROX_NONE, cvPoint(0,0) );*/
	
	/*cvDrawContours( frame, contours,
	 CV_RGB(255,255,0), CV_RGB(0,255,0),
	 1, 2, 8, cvPoint(0,0));*/
	
	
	cvNamedWindow(myWindow, CV_WINDOW_AUTOSIZE);
	cvNamedWindow(myWindowObjectHSV, CV_WINDOW_AUTOSIZE);
	cvNamedWindow(myWindowObjectRGB, CV_WINDOW_AUTOSIZE);
	cvShowImage(myWindow, frame);
	cvShowImage(myWindowObjectHSV, imageObjectHSV);
	cvShowImage(myWindowObjectRGB, imageObjectRGB);
	//cvSaveImage("NoisyGridCentroiding.png", imageObjectRGB,0);
	
	// End timer
	t2 = clock();
	
	// Compute execution time
	time = (float)(t2 - t1) / CLOCKS_PER_SEC;
	
	cout << "execution time = " << time << " s" << endl;
	
}
Ejemplo n.º 5
0
void AngleVariation::initialise()
{
    // Calculate points positions
    QPointF tempPoint = QPointF();
    tempPoint.setX(branchLine.p2().x() - branchLine.p1().x());
    tempPoint.setY(branchLine.p2().y() - branchLine.p1().y());
    branchAngle = atan2(tempPoint.y(), tempPoint.x());
    origPoint = findPoint(branchAngle - variationAngle);
    variationPoint = calculateOpposingPoint(origPoint);
}
Ejemplo n.º 6
0
// remove trailing zeros
void removeTrailingZeros(char** strNew){
	char* str = *strNew;
	unsigned int fracPointIndex = findPoint(str);
	unsigned int index = strlen(str) - 1;
	char clearZero = 1;

	// while need to clear zeros or reached the fraction point
	while (clearZero == 1 && index > fracPointIndex){
		// replace 0 with NULL
		if (str[index] == '0')
			str[index--] = '\0';
		else
			clearZero = 0;
	}
}
Ejemplo n.º 7
0
bool Line::find(DRAWDEBUG_PARAM_N){
    LinePoint lp;
    LinePoint::LinePointParam lParam = m_LineParam;
    lParam.sobelThreshold = 50;
    bool found = findPoint(lp,lParam DRAWDEBUG_ARG);
    m_points.clear();
    //std::cout<<"found::::: "<<found<<" "<<lParam.edge<<std::endl;

    if(!found){
        return false;
    }
    m_points.push_front(lp);
    //found receptor point -> try to extend the line
    extend(true DRAWDEBUG_ARG);
    extend(false DRAWDEBUG_ARG);
    return true;
}
Ejemplo n.º 8
0
void LaserSystem::addBeams(Laser& laser, TilePosition& tilePos)
{
    // Setup everything
    currentPosition = ng::vec::cast<int>(tilePos.pos);
    currentDirection = laser.direction;

    // Current layer is the starting layer of the beam
    currentLayer = (tilePos.layer && !getLayer());

    // Simulate the laser until it hits something
    laser.beamCount = 0;
    sf::Vector2f startPoint = tileMap.getCenterPoint<float>(tilePos.pos);
    PointInfo endPoint;
    do
    {
        // Find next point that collides
        endPoint = findPoint();

        Laser::Beam* beam;
        if (laser.beamCount < laser.beams.size())
        {
            // Use an existing sprite
            beam = &(laser.beams[laser.beamCount]);
        }
        else
        {
            // Setup a new sprite with the beam texture
            laser.beams.emplace_back();
            beam = &laser.beams.back();
            ng::SpriteLoader::load(beam->sprite, textureFilename, true);
        }
        ++laser.beamCount;

        beam->sprite.setOrigin(beamWidth / 2, 0);

        // Calculate and set the beam length
        float beamLength = ng::vec::distance(startPoint, endPoint.position);
        beam->sprite.setScale(1, beamLength);

        // Set the beam's position and rotation
        beam->sprite.setPosition(startPoint);
        beam->sprite.setRotation(ng::vec::rotateAngle(laser.getAngle(currentDirection), 180.0));

        // Set the beam's layer
        beam->layer = currentLayer;

        if (endPoint.state == PointInfo::State::Redirect)
        {
            // Change the direction based on the angle of the mirror
            bool mirrorState = tileMapData(endPoint.tileId).state;
            changeDirection(mirrorState, currentDirection);
        }
        else if (endPoint.state == PointInfo::State::Activate)
        {
            // Enable the laser sensor
            es::Events::send(SwitchEvent{endPoint.tileId, SwitchEvent::On});
            laserSensorsToDisable.erase(endPoint.tileId);
        }

        startPoint = endPoint.position;
    }
    while (endPoint.state == PointInfo::State::Redirect);
}
Ejemplo n.º 9
0
int main(int argc, char **argv)
{
  google::SetUsageMessage("dense --help");
  google::SetVersionString("1.0.0");
  google::ParseCommandLineFlags(&argc, &argv, true);
  
  int maxCorners = 10000;
  double qualityLevel = 0.03;
  double minDistance = 2;
  std::vector<cv::Mat> all_images;
  std::vector<cv::Mat> all_gray_images;
  std::vector<camera_frame_wo_image> camera_frame_wo_images;

  nvm_file input(FLAGS_nvm_file);
  all_images.resize(input.kf_data.size());
  all_gray_images.resize(input.kf_data.size());
  camera_frame_wo_images.resize(input.kf_data.size());
  // TODO: Add distortion parameters
  for (int i=0; i<all_images.size(); i++) {
    std::cerr << FLAGS_data_dir + "/" + input.kf_data[i].filename << "\n";
    all_images[i] = cv::imread(FLAGS_data_dir + "/" + input.kf_data[i].filename);
    cv::cvtColor(all_images[i], all_gray_images[i], CV_RGBA2GRAY);
    camera_frame_wo_images[i] = camera_frame_wo_image(
      input.kf_data[i].focal, 
      input.kf_data[i].rotation, 
      input.kf_data[i].translation,
      all_images[i].cols/2, all_images[i].rows/2);
  }
  // input.corr_data.clear();
  cv::Point2f center(all_images[0].cols/2, all_images[0].rows/2);
  
  // for (int i=0; i<input.kf_data.size()-FLAGS_windows; i++) {
  for (int i=0; i<1; i++) {
    // Get good points in img i
    std::vector<cv::Point2f> corners;
    cv::goodFeaturesToTrack(all_gray_images[i], corners, maxCorners, qualityLevel, minDistance);
    std::cout << "Found " << corners.size() << "\n"; 
    int c1= 0; 
    for (auto pt: corners) {
      std::cout << c1 << "\n";
      c1++;
      std::vector<triangulation_bundle> to_triangulate;
      // Get correspondances in img i+1 and i+2 ...
      to_triangulate.push_back(triangulation_bundle(camera_frame_wo_images[i], 
          makeCenterSubtracted(pt, center)));
      cv::Point2f location; 
      for (int j=i+1; j<i + FLAGS_windows; j++) {
        if (findPoint(pt, all_images[i], all_images[j], camera_frame_wo_images[i], camera_frame_wo_images[j], location)) {
          to_triangulate.push_back(triangulation_bundle(camera_frame_wo_images[j],
            makeCenterSubtracted(location, center)));
        }
      }
      // Triangulate
      if (to_triangulate.size()>2) {
        cv::Point3f final3d = Triangulate(to_triangulate);

        // Add to input 3D cloud
        input.corr_data.push_back(Corr3D(final3d, findColor(all_images[i], pt)));  
      }
    }
  }

  input.save_to_disk(FLAGS_output_file);
  input.save_ply_file(FLAGS_output_ply);
  return 0;
}
void MainWindow::refindmatch()
{
    if (dm->scanSN == 0)
        dm->firstFind = true;
    findPoint();
}
void MainWindow::pointmatch()
{
    dm->blocksize = ui->binarySlider->value();
    findPoint();
}
Ejemplo n.º 12
0
/**
  * TODO es kommt auf die suchrichtung an, was direction==true oder false tut, ab dem winkel > 90 dreht sich die suchrichtung im Bild um. Veranschaulicht wird das durch einen Kreis wobei man in den beiden oberen Quadranten sucht.
  */
void Line::extend(bool direction DRAWDEBUG){
    lms::math::vertex2i pixel;

    //std::cout<<"EXXXXXXXXXXXXTEND"<<std::endl;
    float searchStepX;
    float searchStepY;
    float currentLength = 0;
    float currentStepLength = m_LineParam.stepLengthMax;

    bool found = false;
    //search as long as the searchLength isn't reached
    while(currentLength < m_LineParam.maxLength){
        found = false;
        //Create new point using the last data
        LinePoint searchPoint;
        if(direction){
            searchPoint = m_points[m_points.size()-1];
        }else{
            searchPoint = m_points[0];
        }

        //get needed stuff
        //float lineWidth = searchPoint.distance();

        pixel.x = searchPoint.low_high.x;
        pixel.y = searchPoint.low_high.y;
        float oldSearchAngle = m_LineParam.searchAngle;
        float oldSearchAngleOrth;
        if(m_points.size() > 1){
            //get angle between last two points
            EdgePoint *top;
            EdgePoint *bot;
            if(!m_LineParam.fixedSearchAngle){
                if(direction){
                    top = &m_points[m_points.size()-1].low_high;
                    bot = &m_points[m_points.size()-2].low_high;
                }else{
                    top = &m_points[1].low_high;
                    bot = &m_points[0].low_high;
                }
                oldSearchAngle = atan2(top->y - bot->y,top->x-bot->x);
                oldSearchAngle -= M_PI_2;
            }
        }

        if(direction){
            oldSearchAngleOrth = oldSearchAngle+M_PI_2;
        }else{
            oldSearchAngleOrth = oldSearchAngle-M_PI_2;
        }
        //move the point along the tangent of the line and afterwards move it from the line so the point isn't already on the line
        searchStepX = cos(oldSearchAngleOrth)*currentStepLength-m_LineParam.lineWidthTransMultiplier*currentStepLength*cos(oldSearchAngle);
        searchStepY = sin(oldSearchAngleOrth)*currentStepLength-m_LineParam.lineWidthTransMultiplier*currentStepLength*sin(oldSearchAngle);
        //try to find a new point
        //calculate new searchPoint
        if(m_LineParam.target->inside(pixel.x+searchStepX,pixel.y+searchStepY)){
            //move pixel
            pixel += lms::math::vertex2i(searchStepX,searchStepY);
            //TODO that could be made more efficient
            LinePoint::LinePointParam param = m_LineParam;
            param.x = pixel.x;
            param.y = pixel.y;
            param.searchLength = 2*m_LineParam.lineWidthTransMultiplier*currentStepLength;
            param.searchAngle = oldSearchAngle;

            if(findPoint(searchPoint,param DRAWDEBUG_ARG)){
                found = true;
                if(direction){
                    currentLength += searchPoint.low_high.distance(m_points[m_points.size()-1].low_high);
                    m_points.push_back(searchPoint);
                }else{
                    currentLength += searchPoint.low_high.distance(m_points[0].low_high);
                    m_points.push_front(searchPoint);
                }


            }
        }
        //std::cout<<"FOUND "<<found<<" "<<currentLength<<std::endl;
        if(!found){
            //found no point, decrease length
            //TODO add some better algo.
            currentStepLength *= 0.5;
            if(currentStepLength < m_LineParam.stepLengthMin){
                //stop searching, no more points can be found on this line
                //TODO return
                //std::cout<<"BREAK "<<currentLength<<std::endl;
                break;
            }
        }
    }
    //std::cout<<"ENDE "<< currentLength<<" max: "<<m_LineParam.maxLength<<std::endl;
}
/**
 * Function ConvertOutlineToPolygon
 * build a polygon (with holes) from a DRAWSEGMENT list, which is expected to be
 * a outline, therefore a closed main outline with perhaps closed inner outlines.
 * These closed inner outlines are considered as holes in the main outline
 * @param aSegList the initial list of drawsegments (only lines, circles and arcs).
 * @param aPolygons will contain the complex polygon.
 * @param aTolerance is the max distance between points that is still accepted as connected (internal units)
 * @param aErrorText is a wxString to return error message.
 * @param aErrorLocation is the optional position of the error in the outline
 */
bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SET& aPolygons,
                              wxString* aErrorText, unsigned int aTolerance, wxPoint* aErrorLocation )
{
    if( aSegList.size() == 0 )
        return true;

    wxString msg;

    // Make a working copy of aSegList, because the list is modified during calculations
    std::vector< DRAWSEGMENT* > segList = aSegList;

    DRAWSEGMENT* graphic;
    wxPoint prevPt;

    // Find edge point with minimum x, this should be in the outer polygon
    // which will define the perimeter Edge.Cuts polygon.
    wxPoint xmin    = wxPoint( INT_MAX, 0 );
    int     xmini   = 0;

    for( size_t i = 0; i < segList.size(); i++ )
    {
        graphic = (DRAWSEGMENT*) segList[i];

        switch( graphic->GetShape() )
        {
        case S_SEGMENT:
            {
                if( graphic->GetStart().x < xmin.x )
                {
                    xmin    = graphic->GetStart();
                    xmini   = i;
                }

                if( graphic->GetEnd().x < xmin.x )
                {
                    xmin    = graphic->GetEnd();
                    xmini   = i;
                }
            }
            break;

        case S_ARC:
            // Freerouter does not yet understand arcs, so approximate
            // an arc with a series of short lines and put those
            // line segments into the !same! PATH.
            {
                wxPoint  pstart = graphic->GetArcStart();
                wxPoint  center = graphic->GetCenter();
                double   angle  = -graphic->GetAngle();
                double   radius = graphic->GetRadius();
                int      steps  = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 );
                wxPoint  pt;

                for( int step = 1; step<=steps; ++step )
                {
                    double rotation = ( angle * step ) / steps;

                    pt = pstart;

                    RotatePoint( &pt, center, rotation );

                    if( pt.x < xmin.x )
                    {
                        xmin  = pt;
                        xmini = i;
                    }
                }
            }
            break;

        case S_CIRCLE:
            {
                wxPoint pt = graphic->GetCenter();

                // pt has minimum x point
                pt.x -= graphic->GetRadius();

                // when the radius <= 0, this is a mal-formed circle. Skip it
                if( graphic->GetRadius() > 0 && pt.x < xmin.x )
                {
                    xmin  = pt;
                    xmini = i;
                }
            }
            break;

        case S_CURVE:
            {
                graphic->RebuildBezierToSegmentsPointsList( graphic->GetWidth() );

                for( unsigned int jj = 0; jj < graphic->GetBezierPoints().size(); jj++ )
                {
                    wxPoint pt = graphic->GetBezierPoints()[jj];

                    if( pt.x < xmin.x )
                    {
                        xmin  = pt;
                        xmini = i;
                    }
                }
            }
            break;

        case S_POLYGON:
            {
                const auto poly = graphic->GetPolyShape();
                MODULE* module = aSegList[0]->GetParentModule();
                double orientation = module ? module->GetOrientation() : 0.0;
                VECTOR2I offset = module ? module->GetPosition() : VECTOR2I( 0, 0 );

                for( auto iter = poly.CIterate(); iter; iter++ )
                {
                    auto pt = *iter;
                    RotatePoint( pt, orientation );
                    pt += offset;

                    if( pt.x < xmin.x )
                    {
                        xmin.x = pt.x;
                        xmin.y = pt.y;
                        xmini = i;
                    }
                }
            }
            break;
        default:
            break;
        }
    }

    // Grab the left most point, assume its on the board's perimeter, and see if we
    // can put enough graphics together by matching endpoints to formulate a cohesive
    // polygon.

    graphic = (DRAWSEGMENT*) segList[xmini];

    // The first DRAWSEGMENT is in 'graphic', ok to remove it from 'items'
    segList.erase( segList.begin() + xmini );

    // Output the Edge.Cuts perimeter as circle or polygon.
    if( graphic->GetShape() == S_CIRCLE )
    {
        int steps = GetArcToSegmentCount( graphic->GetRadius(), ARC_LOW_DEF, 360.0 );
        TransformCircleToPolygon( aPolygons, graphic->GetCenter(), graphic->GetRadius(), steps );
    }
    else if( graphic->GetShape() == S_POLYGON )
    {
        MODULE* module = graphic->GetParentModule();     // NULL for items not in footprints
        double orientation = module ? module->GetOrientation() : 0.0;
        VECTOR2I offset = module ? module->GetPosition() : VECTOR2I( 0, 0 );

        aPolygons.NewOutline();

        for( auto it = graphic->GetPolyShape().CIterate( 0 ); it; it++ )
        {
            auto pt = *it;
            RotatePoint( pt, orientation );
            pt += offset;
            aPolygons.Append( pt );
        }
    }
    else
    {
        // Polygon start point. Arbitrarily chosen end of the
        // segment and build the poly from here.

        wxPoint startPt = wxPoint( graphic->GetEnd() );
        prevPt = graphic->GetEnd();
        aPolygons.NewOutline();
        aPolygons.Append( prevPt );

        // Do not append the other end point yet of this 'graphic', this first
        // 'graphic' might be an arc or a curve.

        for(;;)
        {
            switch( graphic->GetShape() )
            {
            case S_SEGMENT:
                {
                    wxPoint  nextPt;

                    // Use the line segment end point furthest away from
                    // prevPt as we assume the other end to be ON prevPt or
                    // very close to it.

                    if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
                        nextPt = graphic->GetEnd();
                    else
                        nextPt = graphic->GetStart();

                    aPolygons.Append( nextPt );
                    prevPt = nextPt;
                }
                break;

            case S_ARC:
                // We do not support arcs in polygons, so approximate
                // an arc with a series of short lines and put those
                // line segments into the !same! PATH.
                {
                    wxPoint pstart  = graphic->GetArcStart();
                    wxPoint pend    = graphic->GetArcEnd();
                    wxPoint pcenter = graphic->GetCenter();
                    double  angle   = -graphic->GetAngle();
                    double  radius  = graphic->GetRadius();
                    int     steps   = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 );

                    if( !close_enough( prevPt, pstart, aTolerance ) )
                    {
                        wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), aTolerance ) );

                        angle = -angle;
                        std::swap( pstart, pend );
                    }

                    wxPoint nextPt;

                    for( int step = 1; step<=steps; ++step )
                    {
                        double rotation = ( angle * step ) / steps;
                        nextPt = pstart;
                        RotatePoint( &nextPt, pcenter, rotation );

                        aPolygons.Append( nextPt );
                    }

                    prevPt = nextPt;
                }
                break;

            case S_CURVE:
                // We do not support Bezier curves in polygons, so approximate
                // with a series of short lines and put those
                // line segments into the !same! PATH.
                {
                    wxPoint  nextPt;
                    bool reverse = false;

                    // Use the end point furthest away from
                    // prevPt as we assume the other end to be ON prevPt or
                    // very close to it.

                    if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
                        nextPt = graphic->GetEnd();
                    else
                    {
                        nextPt = graphic->GetStart();
                        reverse = true;
                    }

                    if( reverse )
                    {
                        for( int jj = graphic->GetBezierPoints().size()-1; jj >= 0; jj-- )
                            aPolygons.Append( graphic->GetBezierPoints()[jj] );
                    }
                    else
                    {
                        for( size_t jj = 0; jj < graphic->GetBezierPoints().size(); jj++ )
                            aPolygons.Append( graphic->GetBezierPoints()[jj] );
                    }

                    prevPt = nextPt;
                }
                break;

            default:
                if( aErrorText )
                {
                    msg.Printf( "Unsupported DRAWSEGMENT type %s.",
                                BOARD_ITEM::ShowShape( graphic->GetShape() ) );

                    *aErrorText << msg << "\n";
                }

                if( aErrorLocation )
                    *aErrorLocation = graphic->GetPosition();

                return false;
            }

            // Get next closest segment.

            graphic = findPoint( prevPt, segList, aTolerance );

            // If there are no more close segments, check if the board
            // outline polygon can be closed.

            if( !graphic )
            {
                if( close_enough( startPt, prevPt, aTolerance ) )
                {
                    // Close the polygon back to start point
                    // aPolygons.Append( startPt ); // not needed
                }
                else
                {
                    if( aErrorText )
                    {
                        msg.Printf( _( "Unable to find segment with an endpoint of (%s, %s)." ),
                                    StringFromValue( MILLIMETRES, prevPt.x, true ),
                                    StringFromValue( MILLIMETRES, prevPt.y, true ) );

                        *aErrorText << msg << "\n";
                    }

                    if( aErrorLocation )
                        *aErrorLocation = prevPt;

                    return false;
                }
                break;
            }
        }
    }

    while( segList.size() )
    {
        // emit a signal layers keepout for every interior polygon left...
        int hole = aPolygons.NewHole();

        graphic = (DRAWSEGMENT*) segList[0];
        segList.erase( segList.begin() );

        // Both circles and polygons on the edge cuts layer are closed items that
        // do not connect to other elements, so we process them independently
        if( graphic->GetShape() == S_POLYGON )
        {
            MODULE* module = graphic->GetParentModule();     // NULL for items not in footprints
            double orientation = module ? module->GetOrientation() : 0.0;
            VECTOR2I offset = module ? module->GetPosition() : VECTOR2I( 0, 0 );

            for( auto it = graphic->GetPolyShape().CIterate(); it; it++ )
            {
                auto val = *it;
                RotatePoint( val, orientation );
                val += offset;

                aPolygons.Append( val, -1, hole );
            }
        }
        else if( graphic->GetShape() == S_CIRCLE )
        {
            // make a circle by segments;
            wxPoint  center  = graphic->GetCenter();
            double   angle   = 3600.0;
            wxPoint  start   = center;
            int      radius  = graphic->GetRadius();
            int      steps   = GetArcToSegmentCount( radius, ARC_LOW_DEF, 360.0 );
            wxPoint  nextPt;

            start.x += radius;

            for( int step = 0; step < steps; ++step )
            {
                double rotation = ( angle * step ) / steps;
                nextPt = start;
                RotatePoint( &nextPt.x, &nextPt.y, center.x, center.y, rotation );
                aPolygons.Append( nextPt, -1, hole );
            }
        }
        else
        {
            // Polygon start point. Arbitrarily chosen end of the
            // segment and build the poly from here.

            wxPoint startPt( graphic->GetEnd() );
            prevPt = graphic->GetEnd();
            aPolygons.Append( prevPt, -1, hole );

            // do not append the other end point yet, this first 'graphic' might be an arc
            for(;;)
            {
                switch( graphic->GetShape() )
                {
                case S_SEGMENT:
                    {
                        wxPoint nextPt;

                        // Use the line segment end point furthest away from
                        // prevPt as we assume the other end to be ON prevPt or
                        // very close to it.

                        if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
                        {
                            nextPt = graphic->GetEnd();
                        }
                        else
                        {
                            nextPt = graphic->GetStart();
                        }

                        prevPt = nextPt;
                        aPolygons.Append( prevPt, -1, hole );
                    }
                    break;

                case S_ARC:
                    // Freerouter does not yet understand arcs, so approximate
                    // an arc with a series of short lines and put those
                    // line segments into the !same! PATH.
                    {
                        wxPoint pstart  = graphic->GetArcStart();
                        wxPoint pend    = graphic->GetArcEnd();
                        wxPoint pcenter = graphic->GetCenter();
                        double  angle   = -graphic->GetAngle();
                        int     radius  = graphic->GetRadius();
                        int     steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 );

                        if( !close_enough( prevPt, pstart, aTolerance ) )
                        {
                            wxASSERT( close_enough( prevPt, graphic->GetArcEnd(), aTolerance ) );

                            angle = -angle;
                            std::swap( pstart, pend );
                        }

                        wxPoint nextPt;

                        for( int step = 1; step <= steps; ++step )
                        {
                            double rotation = ( angle * step ) / steps;

                            nextPt = pstart;
                            RotatePoint( &nextPt, pcenter, rotation );

                            aPolygons.Append( nextPt, -1, hole );
                        }

                        prevPt = nextPt;
                    }
                    break;

                case S_CURVE:
                    // We do not support Bezier curves in polygons, so approximate
                    // with a series of short lines and put those
                    // line segments into the !same! PATH.
                    {
                        wxPoint  nextPt;
                        bool reverse = false;

                        // Use the end point furthest away from
                        // prevPt as we assume the other end to be ON prevPt or
                        // very close to it.

                        if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
                            nextPt = graphic->GetEnd();
                        else
                        {
                            nextPt = graphic->GetStart();
                            reverse = true;
                        }

                        if( reverse )
                        {
                            for( int jj = graphic->GetBezierPoints().size()-1; jj >= 0; jj-- )
                                aPolygons.Append( graphic->GetBezierPoints()[jj], -1, hole );
                        }
                        else
                        {
                            for( size_t jj = 0; jj < graphic->GetBezierPoints().size(); jj++ )
                                aPolygons.Append( graphic->GetBezierPoints()[jj], -1, hole );
                        }

                        prevPt = nextPt;
                    }
                    break;

                default:
                    if( aErrorText )
                    {
                        msg.Printf( "Unsupported DRAWSEGMENT type %s.",
                                    BOARD_ITEM::ShowShape( graphic->GetShape() ) );

                        *aErrorText << msg << "\n";
                    }

                    if( aErrorLocation )
                        *aErrorLocation = graphic->GetPosition();

                    return false;
                }

                // Get next closest segment.

                graphic = findPoint( prevPt, segList, aTolerance );

                // If there are no more close segments, check if polygon
                // can be closed.

                if( !graphic )
                {
                    if( close_enough( startPt, prevPt, aTolerance ) )
                    {
                        // Close the polygon back to start point
                        // aPolygons.Append( startPt, -1, hole );   // not needed
                    }
                    else
                    {
                        if( aErrorText )
                        {
                            msg.Printf( _( "Unable to find segment with an endpoint of (%s, %s)." ),
                                        StringFromValue( MILLIMETRES, prevPt.x, true ),
                                        StringFromValue( MILLIMETRES, prevPt.y, true ) );

                            *aErrorText << msg << "\n";
                        }

                        if( aErrorLocation )
                            *aErrorLocation = prevPt;

                        return false;
                    }
                    break;
                }
            }
        }
    }

    return true;
}