std::string packLineData(LineData lineData) { rapidjson::Document document; document.SetObject(); rapidjson::Value startPt(rapidjson::kObjectType); startPt.AddMember("x", lineData.startPoint.x, document.GetAllocator()); startPt.AddMember("y", lineData.startPoint.y, document.GetAllocator()); rapidjson::Value endPt(rapidjson::kObjectType); endPt.AddMember("x", lineData.endPoint.x, document.GetAllocator()); endPt.AddMember("y", lineData.endPoint.y, document.GetAllocator()); rapidjson::Value lineColor(rapidjson::kObjectType); lineColor.AddMember("r", lineData.color.r, document.GetAllocator()); lineColor.AddMember("g", lineData.color.g, document.GetAllocator()); lineColor.AddMember("b", lineData.color.b, document.GetAllocator()); lineColor.AddMember("a", lineData.color.a, document.GetAllocator()); document.AddMember("startPoint", startPt, document.GetAllocator()); document.AddMember("endPoint", endPt, document.GetAllocator()); document.AddMember("radius", lineData.radius, document.GetAllocator()); document.AddMember("color", lineColor, document.GetAllocator()); rapidjson::StringBuffer buffer; rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); document.Accept(writer); return std::string(buffer.GetString(), buffer.GetSize()); }
//---------------------------------------------------------- void ofxVectorGraphics::endShape(bool bClose){ if(bDraw){ ofEndShape(bClose); } if(bRecord){ //catmull roms - we need at least 4 points to draw if( whichShapeMode == 1 && curvePts.size() > 3){ //we go through and we calculate the bezier of each //catmull rom curve - smart right? :) for (int i = 1; i< curvePts.size()-2; i++) { ofPoint3 prevPt( curvePts[i-1][0], curvePts[i-1][1]); ofPoint3 startPt(curvePts[i][0], curvePts[i][1]); ofPoint3 endPt( curvePts[i+1][0], curvePts[i+1][1]); ofPoint3 nextPt( curvePts[i+2][0], curvePts[i+2][1]); //SUPER WEIRD MAGIC CONSTANT = 1/6 //Someone please explain this!!! //It works and is 100% accurate but wtf! ofPoint3 cp1 = startPt + ( endPt - prevPt ) * (1.0/6); ofPoint3 cp2 = endPt + ( startPt - nextPt ) * (1.0/6); //if this is the first line we are drawing //we have to start the path at a location if( i == 1 ){ creeps.startPath(startPt.x, startPt.y); bShouldClose = true; } creeps.addCurve( cp1.x, cp1.y, cp2.x, cp2.y, endPt.x, endPt.y); } } if(bShouldClose){ //we close the path if requested if(bClose)creeps.closeSubpath(); //render the stroke as either a fill or a stroke. if(bFill){ creeps.endPath(CreEPS::FILL); }else{ creeps.endPath(CreEPS::STROKE); } bShouldClose = false; } //we want to clear all the vertices //otherwise we keep adding points from //the previous file - cool but not what we want! clearAllVertices(); } }
void CXMLExporter::WriteEdge(CComPtr<ISkpEdge> pEdge) { HResult hr; m_Stats.m_nEdges += 1; if (m_pOptions->GetExportLayers()) { CComPtr<ISkpDrawingElement> pDE; hr = pEdge->QueryInterface(IID_ISkpDrawingElement, (void**) &pDE); CComPtr<ISkpLayer> pLayer; hr = pDE->get_Layer(&pLayer); long layerId = GetEntityId(pLayer); Write("<Edge layer=\"%d\">\n", layerId); } else { Write("<Edge>\n"); } IncreaseIndent(); CComPtr<ISkpPoint3d> pStartPoint; hr = pEdge->get_StartPoint(&pStartPoint); CPoint3d startPt(pStartPoint); CPoint3d startPoint = m_InheritanceManager.GetCurrentTransform() * startPt; Write("<Start x=\"%f\" y=\"%f\" z=\"%f\" />\n", startPoint.X(), startPoint.Y(), startPoint.Z()); CComPtr<ISkpPoint3d> pEndPoint; hr = pEdge->get_EndPoint(&pEndPoint); CPoint3d endPt(pEndPoint); CPoint3d endPoint = m_InheritanceManager.GetCurrentTransform() * endPt; Write("<End x=\"%f\" y=\"%f\" z=\"%f\" />\n", endPoint.X(), endPoint.Y(), endPoint.Z()); DecreaseIndent(); Write("</Edge>\n"); }
void WorldMap::restartGame(){ Sound::stopSound(GameSound::GameOver); Static::gameState = GameState::Playing; Point startPt(1280, 2464);//original starting pt player->currentLayer = Layer::OverWorld; player->prevWorldX = player->worldX; player->prevWorldY = player->worldY; player->worldX = 4; player->worldY = 2; float inventoryNewX = player->worldY*Global::roomHeight; float inventoryNewY = player->worldX*Global::roomWidth; player->inventory->setInventoryPosition(Point(inventoryNewX, inventoryNewY)); player->inventory->playerBar->setPlayerBar(Point(inventoryNewX, inventoryNewY)); player->inventory->playerBar->healPlayerToFull(); player->movePlayerToNewVector = true; player->position = startPt; player->updateSprites(); Global::gameView.setCenter(player->worldY*Global::roomWidth + Global::SCREEN_WIDTH / 2, player->worldX*Global::roomHeight + Global::SCREEN_HEIGHT / 2); Sound::playSound(GameSound::OverWorld); }
bool MgArc::_setHandlePoint2(int index, const Point2d& pt, float, int& data) { static float lastSweepAngle; if (index == 1 || index == 2) { // 起点、终点 return setCenterRadius(getCenter(), pt.distanceTo(getCenter()), getStartAngle(), getSweepAngle()); } if (index == 3) { // 弧线中点 return setStartMidEnd(getStartPoint(), pt, getEndPoint()); } if (index == 4) { // 改变起始角度 if (data == 0) { lastSweepAngle = getSweepAngle(); data++; } Point2d startPt(getCenter().polarPoint((pt - getCenter()).angle2(), getRadius())); bool ret = setCSE(getCenter(), startPt, getEndPoint(), lastSweepAngle); lastSweepAngle = getSweepAngle(); return ret; } if (index == 5) { // 改变终止角度 if (data == 0) { lastSweepAngle = getSweepAngle(); data++; } Point2d endPt(getCenter().polarPoint((pt - getCenter()).angle2(), getRadius())); bool ret = setCSE(getCenter(), getStartPoint(), endPt, lastSweepAngle); lastSweepAngle = getSweepAngle(); return ret; } if (index == 6) { return setTanStartEnd(pt - getStartPoint(), getStartPoint(), getEndPoint()); } if (index == 7) { return (setTanStartEnd(getEndPoint() - pt, getEndPoint(), getStartPoint()) && _reverse()); } return offset(pt - getCenter(), -1); }
void ObjectGroup::draw(cv::Mat& image) { if(getContext()->getDrawingFlags()->mDrawBoundingBox) { cv::Rect_<float> r = mModel->getLastBoundingBox(); cv::rectangle(image, r, getColor(), 2); cv::rectangle(image, cv::Rect_<float>(r.x - 5, r.y - 7, 12*getObjectId().size(), 14), cv::Scalar(0,0,0), CV_FILLED); cv::putText(image, getObjectId(), cv::Point(r.x-5, r.y+4), cv::FONT_HERSHEY_DUPLEX, 0.5, cv::Scalar(255,255,255),1,8, false); std::string stateStr = getStateRepresentativeString(getState()); cv::Point startPt(r.x-5, r.height+r.y); cv::rectangle(image, cv::Rect_<float>(startPt.x, startPt.y-12, 12*stateStr.size(), 14), cv::Scalar(0,0,0), CV_FILLED); cv::putText(image, stateStr, startPt, cv::FONT_HERSHEY_DUPLEX, 0.5, cv::Scalar(255,255,255),1,8, false); } //We don't want to show the Centroid of the blob /*if(getContext()->getDrawingFlags()->mDrawCentroid) { const std::map<int, Blob>& blobs = mModel->getBlobs(); if(blobs.size() > 1) { auto it = blobs.begin(); cv::Point2f lastPt = it->second.getCentroid(); ++it; for(; it != blobs.end(); ++it) { cv::Point2f currentPt = it->second.getCentroid(); cv::line(image, lastPt, currentPt, getColor(), 3); lastPt = currentPt; } } }*/ for(auto objectIt = mObjectList.begin(); objectIt != mObjectList.end(); ++objectIt) (*objectIt)->draw(image); }
BOOST_FIXTURE_TEST_CASE(BlockedPaths, WorldFixtureEmpty0P) { MapPoint startPt(10, 10); // Create a circle of stones so the path is completely blocked std::vector<MapPoint> surroundingPts = world.GetPointsInRadius(startPt, 1); BOOST_FOREACH(const MapPoint& pt, surroundingPts) world.SetNO(pt, new noGranite(GT_1, 1)); std::vector<MapPoint> surroundingPts2; for(unsigned i=0; i<12; i++) surroundingPts2.push_back(world.GetNeighbour2(startPt, i)); BOOST_FOREACH(const MapPoint& pt, surroundingPts2) BOOST_REQUIRE_EQUAL(world.FindHumanPath(startPt, pt), INVALID_DIR); // Allow left exit world.DestroyNO(surroundingPts[0]); BOOST_REQUIRE_EQUAL(world.FindHumanPath(startPt, surroundingPts2[0]), 0); BOOST_REQUIRE(checkWalkOnTerrain(world, startPt, surroundingPts2[0], Direction::WEST, TT_WATER, true)); BOOST_REQUIRE(checkWalkOnTerrain(world, startPt, surroundingPts2[0], Direction::WEST, TT_SWAMPLAND, true)); BOOST_REQUIRE(checkWalkOnTerrain(world, startPt, surroundingPts2[0], Direction::WEST, TT_LAVA, false)); BOOST_REQUIRE(checkWalkOnTerrain(world, startPt, surroundingPts2[0], Direction::WEST, TT_SNOW, false)); BOOST_REQUIRE(checkWalkOnPoint(world, startPt, surroundingPts2[0], Direction::WEST, TT_WATER)); BOOST_REQUIRE(checkWalkOnPoint(world, startPt, surroundingPts2[0], Direction::WEST, TT_SWAMPLAND)); }
PointObject* calcPoint(const std::vector<int>& v) { PointObject* pO = nullptr; int start_point = 0; int end_point = 0; auto it = std::find_if(v.begin(), v.end(), [](const int a) { return (a != 0); }); auto it2 = std::find_if(v.rbegin(), v.rend(), [](int a) { return (a != 0); }); if ((it != v.end())) { Point startPt(std::distance(v.begin(), it)); Point endPt(std::distance(it2, v.rend()) - 1); pO = new Point(average(startPt, endPt)); } else { pO = new NullPoint(); } return pO; }
Acad::ErrorStatus AcDbXmlPoly::xmlOut( AcDbObject* pObj, AcDbXmlOutFiler* pFiler) { Acad::ErrorStatus es = eOk; AsdkPoly* pPoly = AsdkPoly::cast(pObj); if (!pPoly) return eInvalidInput; AcUtXMLDOMNode* pNode = NULL; AcUtXMLDOMElement* pElement = NULL; AcUtXMLDOMAttribute* pAttribute = NULL; try { es = pFiler->pushNode(L"asdk:Poly", MY_SCHEMA, pNode); if (es != eOk) throw es; pElement = new AcUtXMLDOMElement(pNode); if (pElement == NULL) throw eOutOfMemory; es = superXmlOut(pObj, pFiler); if (es != eOk) throw es; es = pFiler->appendAttribute(pPoly->numSides(), L"numSides", pElement); if (es != eOk) throw es; AcUtString name=pPoly->name(); es = pFiler->appendAttribute(name, L"name", pElement); if (es != eOk) throw es; AcGePoint2d pt2d = pPoly->center(); AcGePoint3d centerPt(pt2d.x, pt2d.y, pPoly->elevation()); // Convert the point from ECS to WCS acdbEcs2Wcs(asDblArray(centerPt), asDblArray(centerPt), asDblArray(pPoly->normal()), true); es = pFiler->writePoint(L"dxml:CenterPoint", centerPt); if (es != eOk) throw es; pt2d = pPoly->startPoint(); AcGePoint3d startPt(pt2d.x, pt2d.y, pPoly->elevation()); // Convert the point from ECS to WCS acdbEcs2Wcs(asDblArray(startPt), asDblArray(startPt), asDblArray(pPoly->normal()), true); es = pFiler->writePoint(L"dxml:StartPoint", startPt); if (es != eOk) throw es; es = pFiler->writeNormalVector(pPoly->normal()); if (es != eOk) throw es; es = pFiler->writeHardPointerId(L"acdb:TextStyleTableRecordId", pPoly->styleId()); if (es != eOk) throw es; es = pFiler->popNode(); if (es != eOk) throw es; } catch (Acad::ErrorStatus thrownEs) { es = thrownEs; } if (pAttribute) delete pAttribute; if (pElement) delete pElement; if (pNode && pNode != pFiler->getCurrentNode()) delete pNode; return es; }
void ossimQtVceCanvasWidget::contentsMousePressEvent(QMouseEvent * e ) { theMouseButtonState = e->button(); switch(e->button()) { case Qt::LeftButton: { theLeftDownFlag = true; deleteSelectionRect(); theMouseStartPt = QPoint(e->x(), e->y()); theSelectionRect = new ossimQtVceShapeRect(QRect(e->x(), e->y(), 1, 1), canvas()); // make sure that the selection rect is in front of everything // theSelectionRect->setZ(2); if(!intersectsSelection()) { unselectItems(); // initialize mode // QCanvasItemList collisionList = theSelectionRect->collisions(true); ossimQtVceConnectableObject* obj = getObjectWhereConnectableSlotIntersectsPoint(collisionList, theMouseStartPt); if(obj) { QRect rect; if(obj->getConnectionSlotBoundingRect(rect, theMouseStartPt)) { delete theSelectionRect; theSelectionRect = NULL; theLineObject = new QCanvasLine(canvas()); QPoint startPt(rect.x() + rect.width()/2, rect.y() + rect.height()/2); theLineObject->setPoints(startPt.x(), startPt.y(), theMouseStartPt.x(), theMouseStartPt.y()); theLineObject->setPen(QPen(QColor(0,0,0), 2, Qt::DotLine)); theLineObject->show(); } } if(theSelectionRect) { // now set the pen style to dashed // theSelectionRect->hide(); theSelectionRect->setPen(QPen(QColor(0,0,0), 2, Qt::DotLine)); theSelectionRect->show(); } } else { deleteSelectionRect(); } break; } case Qt::RightButton: { thePopupMenu->hide(); QPoint pt = mapToGlobal(pos()); thePopupMenu->popup(e->globalPos()); } default: { break; } } emit canvasWidgetMousePressEvent(e); }
bool ThreadStereo::initializeThread(corresponding_pts& start, tangent_and_score& tan, vector<ThreadPiece_Vision*>& currPieces) { Point3f lastPoint; //set opt params opt_params_vision.length_per_segment = myThread.length_thread_each_piece; opt_params_vision.threadStereo = &myThread; opt_params_vision.transform_back = Matrix4d::Identity(); Vector3d startPt((double)start.pt3d.x, (double)start.pt3d.y, (double)start.pt3d.z); opt_params_vision.transform_back.corner(Eigen::TopRight,3,1) = startPt; opt_params_vision.orig_params_each_piece = new NEWMAT::ColumnVector(4*NUM_THREAD_PIECES_INIT_OPT+6); //initialize x_sol as if we just finished one iteration NEWMAT::ColumnVector x_sol; x_sol.ReSize(2*NUM_THREAD_PIECES_FIRST_OPT+3); for (int i=0; i < NUM_THREAD_PIECES_FIRST_OPT; i++) { x_sol.element(2*i) = OPTIMIZATION_INIT_CURVATURE; x_sol.element(2*i+1) = OPTIMIZATION_INIT_TORSION; } x_sol.element(2*NUM_THREAD_PIECES_FIRST_OPT ) = tan.rot1; x_sol.element(2*NUM_THREAD_PIECES_FIRST_OPT + 1) = tan.rot2; x_sol.element(2*NUM_THREAD_PIECES_FIRST_OPT + 2) = 0.0; //initialize thread as if we just finished one iteration Matrix4d transform_at_start; transformFromEulerAngles(transform_at_start, x_sol(x_sol.nrows()-2), x_sol(x_sol.nrows()-1), x_sol(x_sol.nrows()), startPt); currPieces.resize(0); currPieces.push_back(new ThreadPiece_Vision(x_sol(1), x_sol(2), myThread.length_thread_each_piece)); currPieces.back()->setPrevTransform(transform_at_start); currPieces.back()->_numPieces = 1; for (int i=1; i < NUM_THREAD_PIECES_FIRST_OPT; i++) { currPieces.push_back(new ThreadPiece_Vision(x_sol.element(2*i), x_sol.element(2*i+1), myThread.length_thread_each_piece, currPieces[i-1])); } for (int numPiecesThisOpt = NUM_THREAD_PIECES_FIRST_OPT; numPiecesThisOpt <= NUM_THREAD_PIECES_INIT_OPT; numPiecesThisOpt++) { opt_params_vision.num_segments = numPiecesThisOpt; for (int i=0; i < numPiecesThisOpt; i++) { if (i < (x_sol.nrows()-3)/2) { opt_params_vision.orig_params_each_piece->element(2*i) = x_sol.element(2*i); opt_params_vision.orig_params_each_piece->element(2*i+1) = x_sol.element(2*i+1); } else { opt_params_vision.orig_params_each_piece->element(2*i) = x_sol.element(2*(numPiecesThisOpt-1)); opt_params_vision.orig_params_each_piece->element(2*i+1) = x_sol.element(2*(numPiecesThisOpt)-1); } } opt_params_vision.orig_params_each_piece->element(2*numPiecesThisOpt ) = x_sol(x_sol.nrows()-2); opt_params_vision.orig_params_each_piece->element(2*numPiecesThisOpt + 1) = x_sol(x_sol.nrows()-1); opt_params_vision.orig_params_each_piece->element(2*numPiecesThisOpt + 2) = x_sol(x_sol.nrows()); //optimize #ifdef PDS if (numPiecesThisOpt == NUM_THREAD_PIECES_INIT_OPT) optimize_PDS(2*opt_params_vision.num_segments+3, energyEvalFunctionVisionFirst, energyEvalFunctionVision_init, x_sol, OPTIMIZATION_TOLERANCE_INIT); else optimize_PDS(2*opt_params_vision.num_segments+3, energyEvalFunctionVisionFirst, energyEvalFunctionVision_init, x_sol, OPTIMIZATION_TOLERANCE_NORMAL); #else if (numPiecesThisOpt == NUM_THREAD_PIECES_INIT_OPT) optimize_GSS(2*opt_params_vision.num_segments+3, energyEvalFunctionVisionFirst, energyEvalFunctionVision_init, x_sol, OPTIMIZATION_TOLERANCE_INIT); else optimize_GSS(2*opt_params_vision.num_segments+3, energyEvalFunctionVisionFirst, energyEvalFunctionVision_init, x_sol, OPTIMIZATION_TOLERANCE_NORMAL); #endif //reset thread params, see if we are done transformFromEulerAngles(transform_at_start, x_sol(x_sol.nrows()-2), x_sol(x_sol.nrows()-1), x_sol(x_sol.nrows()), startPt); currPieces[0]->setParams(x_sol(1), x_sol(2), myThread.length_thread_each_piece); currPieces[0]->setPrevTransform(transform_at_start); for (int i=1; i < numPiecesThisOpt; i++) { if (i < currPieces.size()) currPieces[i]->setParams(x_sol.element(2*i), x_sol.element(2*i+1), myThread.length_thread_each_piece); else currPieces.push_back(new ThreadPiece_Vision(x_sol.element(2*i), x_sol.element(2*i+1), myThread.length_thread_each_piece, currPieces.back())); } currPieces.back()->getLastPoint(lastPoint); if (myThread.isEndPiece(lastPoint)) { //return false; } } return true; }
/** * 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; }
int testPoint() { int numErr = 0; logMessage(_T("TESTING - class GM_3dPoint ...\n\n")); // Default constructor, point must be invalid GM_3dPoint pt; if (pt.isValid()) { logMessage(_T("\tERROR - Default constructor creates valid points\n")); numErr++; } else { logMessage(_T("\tOK - Default constructor creates invalid points\n")); } // Get/Set points coordinates double x = getRandomDouble(); double y = getRandomDouble(); double z = getRandomDouble(); pt.x(x); pt.y(y); pt.z(z); if (pt.x() != x || pt.y() != y || pt.z() != z) { logMessage(_T("\tERROR - Get/Set not working\n")); numErr++; } else { logMessage(_T("\tOK - Get/Set working\n")); } // Copy constructor GM_3dPoint pt1(pt); if (pt.isValid() != pt1.isValid() || pt1.x() != pt.x() || pt1.y() != pt.y() || pt1.z() != pt.z()) { logMessage(_T("\tERROR - Copy constructor not working\n")); numErr++; } else { logMessage(_T("\tOK - Copy constructor working\n")); } // Constructor (coordinates) x = getRandomDouble(); y = getRandomDouble(); z = getRandomDouble(); GM_3dPoint pt2(x, y, z); if (!pt2.isValid() || pt2.x() != x || pt2.y() != y || pt2.z() != z) { logMessage(_T("\tERROR - Coordinate constructor not working\n")); numErr++; } else { logMessage(_T("\tOK - Coordinate constructor working\n")); } // Constructor (angle) double ang = getRandomAngle(); GM_3dPoint pt3(ang); if (!pt2.isValid() || pt3.x() != cos(ang) || pt3.y() != sin(ang) || pt3.z() != 0.0) { logMessage(_T("\tERROR - XY angle constructor not working\n")); numErr++; } else { logMessage(_T("\tOK - XY angle constructor working\n")); } // Invalidation pt.invalidate(); if (pt.isValid()) { logMessage(_T("\tERROR - Invalidation not working\n")); numErr++; } else { logMessage(_T("\tOK - Invalidation working\n")); } // Inversion GM_3dPoint invPt(pt2); invPt.xyInvert(); if (invPt.isValid() != pt2.isValid() || invPt.x() != -pt2.x() || invPt.y() != -pt2.y() || invPt.z() != pt2.z()) { logMessage(_T("\tERROR - Inversion not working\n")); numErr++; } else { logMessage(_T("\tOK - Inversion working\n")); } // Origin check GM_3dPoint origPt(GM_NULL_TOLERANCE / 2.0, -GM_NULL_TOLERANCE / 2.0, 0.0); if (pt2.isOrigin() || !origPt.isOrigin()) { logMessage(_T("\tERROR - Origin check not working\n")); numErr++; } else { logMessage(_T("\tOK - Origin check working\n")); } // Distance GM_3dPoint startPt(getRandomDouble(), getRandomDouble(), getRandomDouble()); GM_3dPoint endPt(getRandomDouble(), getRandomDouble(), getRandomDouble()); double dx = startPt.x() - endPt.x(); double dy = startPt.y() - endPt.y(); double dz = startPt.z() - endPt.z(); double dist = sqrt(dx*dx + dy*dy + dz*dz); if (!startPt.isValid() || !endPt.isValid() || startPt.distFrom(endPt) != dist) { logMessage(_T("\tERROR - Distance computation not working\n")); numErr++; } else { logMessage(_T("\tOK - Distance computation working\n")); } // Equality GM_3dPoint ptEq1(getRandomDouble(), getRandomDouble(), getRandomDouble()); GM_3dPoint ptEq2(ptEq1); GM_3dPoint ptEq3(ptEq1.x() + getRandomDouble(), ptEq1.y() + getRandomDouble(), ptEq1.z() + getRandomDouble()); if (ptEq1 != ptEq2 || ptEq1 == ptEq3) { logMessage(_T("\tERROR - Equality check not working\n")); numErr++; } else { logMessage(_T("\tOK - Equality check working\n")); } return numErr; }
int testLine() { int numErr = 0; logMessage(_T("TESTING - class GM_3dLine ...\n\n")); // Default constructor, line must be invalid GM_3dLine ln; if (ln.isValid()) { logMessage(_T("\tERROR - Default constructor creates valid line\n")); numErr++; } else { logMessage(_T("\tOK - Default constructor creates invalid line\n")); } // Get/Set line coordinates double xStart = getRandomDouble(); double yStart = getRandomDouble(); double zStart = getRandomDouble(); double xEnd = getRandomDouble(); double yEnd = getRandomDouble(); double zEnd = getRandomDouble(); ln.begin().x(xStart); ln.begin().y(yStart); ln.begin().z(zStart); ln.end().x(xEnd); ln.end().y(yEnd); ln.end().z(zEnd); if (!ln.isValid() || ln.begin().x() != xStart || ln.begin().y() != yStart || ln.begin().z() != zStart || ln.end().x() != xEnd || ln.end().y() != yEnd || ln.end().z() != zEnd) { logMessage(_T("\tERROR - Get/Set not working\n")); numErr++; } else { logMessage(_T("\tOK - Get/Set working\n")); } // Copy constructor GM_3dLine ln1(ln); if (ln1.isValid() != ln.isValid() || ln1.begin().x() != ln.begin().x() || ln1.begin().y() != ln.begin().y() || ln1.begin().z() != ln.begin().z() || ln1.end().x() != ln.end().x() || ln1.end().y() != ln.end().y() || ln1.end().z() != ln.end().z()) { logMessage(_T("\tERROR - Copy constructor not working\n")); numErr++; } else { logMessage(_T("\tOK - Copy constructor working\n")); } // Constructor (points) GM_3dPoint startPt(getRandomDouble(), getRandomDouble(), getRandomDouble()); GM_3dPoint endPt(getRandomDouble(), getRandomDouble(), getRandomDouble()); GM_3dLine ln2(startPt, endPt); if (!ln2.isValid() || ln2.begin().x() != startPt.x() || ln2.begin().y() != startPt.y() || ln2.begin().z() != startPt.z() || ln2.end().x() != endPt.x() || ln2.end().y() != endPt.y() || ln2.end().z() != endPt.z()) { logMessage(_T("\tERROR - Points constructor not working\n")); numErr++; } else { logMessage(_T("\tOK - Points constructor working\n")); } // Constructor (coordinates) xStart = getRandomDouble(); yStart = getRandomDouble(); zStart = getRandomDouble(); xEnd = getRandomDouble(); yEnd = getRandomDouble(); zEnd = getRandomDouble(); GM_3dLine ln3(xStart, yStart, zStart, xEnd, yEnd, zEnd); if (!ln3.isValid() || ln3.begin().x() != xStart || ln3.begin().y() != yStart || ln3.begin().z() != zStart || ln3.end().x() != xEnd || ln3.end().y() != yEnd || ln3.end().z() != zEnd) { logMessage(_T("\tERROR - Coordinate constructor not working\n")); numErr++; } else { logMessage(_T("\tOK - Coordinate constructor working\n")); } // dx, dy, dz double dx = ln2.dx(); double dy = ln2.dy(); double dz = ln2.dz(); if (dx != ln2.end().x()-ln2.begin().x() || dy != ln2.end().y()-ln2.begin().y() || dz != ln2.end().z()-ln2.begin().z()) { logMessage(_T("\tERROR - dx, dy or dz not working\n")); numErr++; } else { logMessage(_T("\tOK - dx, dy or dz working\n")); } // Dot product double dotProduct = ln2 * ln3; double dxLn2 = ln2.dx(); double dyLn2 = ln2.dy(); double dzLn2 = ln2.dz(); double dxLn3 = ln3.dx(); double dyLn3 = ln3.dy(); double dzLn3 = ln3.dz(); double checkDotProduct = dxLn2*dxLn3 + dyLn2*dyLn3 + dzLn2*dzLn3; if (dotProduct != checkDotProduct) { logMessage(_T("\tERROR - Dot product not working\n")); numErr++; } else { logMessage(_T("\tOK - Dot product working\n")); } // Cross product GM_3dLine crossProdLn = ln2 ^ ln3; double checkCrossProdX = ln2.begin().x() + (dyLn2*dzLn3 - dzLn2*dyLn3); double checkCrossProdY = ln2.begin().y() + (dzLn2*dxLn3 - dxLn2*dzLn3); double checkCrossProdZ = ln2.begin().z() + (dxLn2*dyLn3 - dyLn2*dxLn3); if (!crossProdLn.isValid() || crossProdLn.end().x() != checkCrossProdX || crossProdLn.end().y() != checkCrossProdY || crossProdLn.end().z() != checkCrossProdZ) { logMessage(_T("\tERROR - Cross product not working\n")); numErr++; } else { logMessage(_T("\tOK - Cross product working\n")); } // Center GM_3dPoint ln2Center = ln2.center(); if (!ln2Center.isValid() || ln2Center.x() != ln2.begin().x() + (ln2.end().x()-ln2.begin().x())/2.0 || ln2Center.y() != ln2.begin().y() + (ln2.end().y()-ln2.begin().y())/2.0 || ln2Center.z() != ln2.begin().z() + (ln2.end().z()-ln2.begin().z())/2.0) { logMessage(_T("\tERROR - Center point computation not working\n")); numErr++; } else { logMessage(_T("\tOK - Center point computation working\n")); } // Invert GM_3dLine ln2Copy(ln2); ln2.invert(); if (!ln2Copy.isValid() || ln2Copy.begin().x() != ln2.end().x() || ln2Copy.begin().y() != ln2.end().y() || ln2Copy.begin().z() != ln2.end().z() || ln2Copy.end().x() != ln2.begin().x() || ln2Copy.end().y() != ln2.begin().y() || ln2Copy.end().z() != ln2.begin().z()) { logMessage(_T("\tERROR - Inversion not working\n")); numErr++; } else { logMessage(_T("\tOK - Inversion working\n")); } // Length double checkLen = sqrt(ln2.dx()*ln2.dx() + ln2.dy()*ln2.dy() + ln2.dz()*ln2.dz()); if (ln2.length() != checkLen) { logMessage(_T("\tERROR - Length computation not working\n")); numErr++; } else { logMessage(_T("\tOK - Length computation working\n")); } // Null check GM_3dLine nullLn(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); bool checkNull1 = nullLn.isNull(); nullLn.begin().x(10.0); bool checkNull2 = nullLn.isNull(); if (!nullLn.isValid() || !checkNull1 || checkNull2) { logMessage(_T("\tERROR - Null line check not working\n")); numErr++; } else { logMessage(_T("\tOK - Null line check working\n")); } // Vertical line check double xCoord = getRandomDouble(); double yCoord = getRandomDouble(); GM_3dLine vertLn(xCoord, yCoord, getRandomDouble(), xCoord, yCoord, getRandomDouble()); bool checkVert1 = vertLn.isVertical(); vertLn.begin().x(vertLn.begin().x() + 10.0); bool checkVert2 = vertLn.isVertical(); if (!vertLn.isValid() || !checkVert1 || checkVert2) { logMessage(_T("\tERROR - Vertical line check not working\n")); numErr++; } else { logMessage(_T("\tOK - Vertical line check working\n")); } // Horizontal line check double zCoord = getRandomDouble(); GM_3dLine horLn(getRandomDouble(), getRandomDouble(), zCoord, getRandomDouble(), getRandomDouble(), zCoord); bool checkHor1 = horLn.isHorizontal(); horLn.begin().z(horLn.begin().z() + 10.0); bool checkHor2 = horLn.isHorizontal(); if (!horLn.isValid() || !checkHor1 || checkVert2) { logMessage(_T("\tERROR - Horizontal line check not working\n")); numErr++; } else { logMessage(_T("\tOK - Horizontal line check working\n")); } // Z min/max double minZ = ln2.minZ(); double maxZ = ln2.maxZ(); double checkMin = ln2.begin().z() < ln2.end().z() ? ln2.begin().z() : ln2.end().z(); double checkMax = ln2.begin().z() > ln2.end().z() ? ln2.begin().z() : ln2.end().z(); if (minZ != checkMin || maxZ != checkMax) { logMessage(_T("\tERROR - min/max Z not working\n")); numErr++; } else { logMessage(_T("\tOK - min/max Z working\n")); } // Point on line at Z double sec = getRandom01Double(); double dX = ln2.dx(); double dY = ln2.dy(); double dZ = ln2.dz(); double xCheck = ln2.begin().x() + (sec * dX); double yCheck = ln2.begin().y() + (sec * dY); double zCheck = ln2.begin().z() + (sec * dZ); GM_3dPoint pointAtZ = ln2.pointAtZ(zCheck); if (!pointAtZ.isValid() || fabs(pointAtZ.x()-xCheck) > GM_NULL_TOLERANCE || fabs(pointAtZ.y()-yCheck) > GM_NULL_TOLERANCE) { logMessage(_T("\tERROR - Point on line at Z not working\n")); numErr++; } else { logMessage(_T("\tOK - Point on line at Z working\n")); } // Nomal vector on XY GM_3dVector normalVectorR = ln2.normalXYVector(true); GM_3dVector normalVectorL = ln2.normalXYVector(false); GM_3dVector ln2Dir(ln2); double dotPR = normalVectorR * ln2Dir; double dotPL = normalVectorL * ln2Dir; bool RSide = ln2Dir.isAtLeftOnXY(normalVectorR); bool LSide = ln2Dir.isAtLeftOnXY(normalVectorL); if (!normalVectorR.isValid() || !normalVectorL.isValid() || fabs(dotPR) > GM_NULL_TOLERANCE || fabs(dotPL) > GM_NULL_TOLERANCE || !RSide || LSide) { logMessage(_T("\tERROR - XY normal vector computation not working\n")); numErr++; } else { logMessage(_T("\tOK - XY normal vector computation working\n")); } // Point from section double section = getRandom01Double(); GM_3dPoint sectionPoint = ln2.pointFromSection(section); double ln2Len = ln2.length(); double pointSectionLen = ln2.begin().distFrom(sectionPoint); if (fabs((pointSectionLen / ln2Len) - section) > GM_NULL_TOLERANCE) { logMessage(_T("\tERROR - Point from section not working\n")); numErr++; } else { logMessage(_T("\tOK - Point from section working\n")); } // Section from point double checkSection = ln2.sectionFromPoint(sectionPoint); if (fabs(checkSection - section) > GM_NULL_TOLERANCE) { logMessage(_T("\tERROR - Section from point not working\n")); numErr++; } else { logMessage(_T("\tOK - Section from point working\n")); } // Point distance ln2Dir.normalize(); GM_3dVector ln2NormDir(ln2Dir); section = getRandom01Double(); sectionPoint = ln2.pointFromSection(section); if (fabs(ln2Dir.x()) > GM_NULL_TOLERANCE) { ln2NormDir.x(getRandomDouble()); ln2NormDir.y(getRandomDouble()); ln2NormDir.z(getRandomDouble()); ln2NormDir.normalize(); ln2NormDir.x(-(ln2Dir.y()*ln2NormDir.y() + ln2Dir.z()*ln2NormDir.z()) / ln2Dir.x()); } else if (fabs(ln2Dir.y()) > GM_NULL_TOLERANCE) { ln2NormDir.x(getRandomDouble()); ln2NormDir.y(getRandomDouble()); ln2NormDir.z(getRandomDouble()); ln2NormDir.normalize(); ln2NormDir.y(-(ln2Dir.x()*ln2NormDir.x() + ln2Dir.z()*ln2NormDir.z()) / ln2Dir.y()); } else if (fabs(ln2Dir.z()) > GM_NULL_TOLERANCE) { ln2NormDir.x(getRandomDouble()); ln2NormDir.y(getRandomDouble()); ln2NormDir.z(getRandomDouble()); ln2NormDir.normalize(); ln2NormDir.z(-(ln2Dir.x()*ln2NormDir.x() + ln2Dir.y()*ln2NormDir.y()) / ln2Dir.z()); } else { ln2NormDir.invalidate(); } double dist = 0.0; double checkDist = 0.0; GM_3dPoint pointOnLine; if (ln2NormDir.isValid()) { ln2NormDir.normalize(); double dotProd = ln2NormDir * ln2Dir; dist = fabs(getRandomDouble()); GM_3dPoint externPoint(sectionPoint); externPoint = (GM_3dVector)externPoint + (ln2NormDir * dist); checkDist = ln2.pointDistance(externPoint, pointOnLine); } if (!pointOnLine.isValid() || fabs(dist - checkDist) > GM_NULL_TOLERANCE) { logMessage(_T("\tERROR - Point distance not working\n")); numErr++; } else { logMessage(_T("\tOK - Point distance working\n")); } return numErr; }