Exemplo n.º 1
0
Vector<Vector<Point2> > Geometry::_polypath_offset(const Vector<Point2> &p_polypath, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) {

	using namespace ClipperLib;

	JoinType jt = jtSquare;

	switch (p_join_type) {
		case JOIN_SQUARE: jt = jtSquare; break;
		case JOIN_ROUND: jt = jtRound; break;
		case JOIN_MITER: jt = jtMiter; break;
	}

	EndType et = etClosedPolygon;

	switch (p_end_type) {
		case END_POLYGON: et = etClosedPolygon; break;
		case END_JOINED: et = etClosedLine; break;
		case END_BUTT: et = etOpenButt; break;
		case END_SQUARE: et = etOpenSquare; break;
		case END_ROUND: et = etOpenRound; break;
	}
	ClipperOffset co;
	Path path;

	// Need to scale points (Clipper's requirement for robust computation)
	for (int i = 0; i != p_polypath.size(); ++i) {
		path << IntPoint(p_polypath[i].x * SCALE_FACTOR, p_polypath[i].y * SCALE_FACTOR);
	}
	co.AddPath(path, jt, et);

	Paths paths;
	co.Execute(paths, p_delta * SCALE_FACTOR); // inflate/deflate

	// Have to scale points down now
	Vector<Vector<Point2> > polypaths;

	for (Paths::size_type i = 0; i < paths.size(); ++i) {
		Vector<Vector2> polypath;

		const Path &scaled_path = paths[i];

		for (Paths::size_type j = 0; j < scaled_path.size(); ++j) {
			polypath.push_back(Point2(
					static_cast<real_t>(scaled_path[j].X) / SCALE_FACTOR,
					static_cast<real_t>(scaled_path[j].Y) / SCALE_FACTOR));
		}
		polypaths.push_back(polypath);
	}
	return polypaths;
}
Exemplo n.º 2
0
bool ComputeOffset(const Paths &paths, double amount, Paths *result) {
  // Previous operations can leave small artifacts (e.g. self-intersecting
  // polygons) which ClipperOffset cannot handle. CleanPolygons fixes at least
  // some of these cases.
  Paths cleaned(paths.size());  // CleanPolygons does not resize 'cleaned'.
  CleanPolygons(paths, cleaned);
  Paths tmp_paths;
  if (!CopyAndForceOrientation(cleaned, true, &tmp_paths))
    return false;

  ClipperOffset co;
  co.ArcTolerance = kQuantaPerInch / 1000;
  co.AddPaths(tmp_paths, jtRound, etClosedPolygon);
  co.Execute(*result, InchesToQuanta(amount));
  return true;
}
void SHAPE_POLY_SET::Inflate( int aFactor, int aCircleSegmentsCount )
{
    ClipperOffset c;

    BOOST_FOREACH( const POLYGON& poly, m_polys )
    {
        for( unsigned int i = 0; i < poly.size(); i++ )
            c.AddPath( convertToClipper( poly[i], i > 0 ? false : true ), jtRound, etClosedPolygon );
    }

    PolyTree solution;

    c.ArcTolerance = fabs( (double) aFactor ) / M_PI / aCircleSegmentsCount;

    c.Execute( solution, aFactor );

    importTree( &solution );
}
void SHAPE_POLY_SET::Inflate( int aFactor, int aCircleSegmentsCount )
{
    // A static table to avoid repetitive calculations of the coefficient
    // 1.0 - cos( M_PI/aCircleSegmentsCount)
    // aCircleSegmentsCount is most of time <= 64 and usually 8, 12, 16, 32
    #define SEG_CNT_MAX 64
    static double arc_tolerance_factor[SEG_CNT_MAX+1];

    ClipperOffset c;

    for( const POLYGON& poly : m_polys )
    {
        for( unsigned int i = 0; i < poly.size(); i++ )
            c.AddPath( convertToClipper( poly[i], i > 0 ? false : true ), jtRound, etClosedPolygon );
    }

    PolyTree solution;

    // Calculate the arc tolerance (arc error) from the seg count by circle.
    // the seg count is nn = M_PI / acos(1.0 - c.ArcTolerance / abs(aFactor))
    // see:
    // www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/ClipperOffset/Properties/ArcTolerance.htm

    if( aCircleSegmentsCount < 6 )  // avoid incorrect aCircleSegmentsCount values
        aCircleSegmentsCount = 6;

    double coeff;

    if( aCircleSegmentsCount > SEG_CNT_MAX || arc_tolerance_factor[aCircleSegmentsCount] == 0 )
    {
        coeff = 1.0 - cos( M_PI/aCircleSegmentsCount);

        if( aCircleSegmentsCount <= SEG_CNT_MAX )
            arc_tolerance_factor[aCircleSegmentsCount] = coeff;
    }
    else
        coeff = arc_tolerance_factor[aCircleSegmentsCount];

    c.ArcTolerance = std::abs( aFactor ) * coeff;

    c.Execute( solution, aFactor );

    importTree( &solution );
}
Exemplo n.º 5
0
vector<ofVec3f> ofApp::offsetCell(list<int> & crv, float amt) {
	float scaling = 10;
	ClipperOffset co;
	Path P;
	Paths offsetP;
	float offset = amt;

	for (auto index : crv) {
		ofVec3f v = linesMesh.getVertex(index);
		P.push_back(IntPoint(v.x*scaling, v.y*scaling));
	}
	co.AddPath(P, jtRound, etClosedPolygon);
	co.Execute(offsetP, -offset*scaling);

	vector<ofVec3f> offsetPts;
	if (offsetP.size() > 0) {
		//visual offset for etching
		CleanPolygons(offsetP);

		if (doEtchOffset) {
			co.Clear();
			co.AddPaths(offsetP, jtRound, etClosedPolygon);
			co.Execute(offsetP, -etchOffset*scaling);
		}

		Path & oP = offsetP[0];
		for (int i = 0; i < oP.size(); i++) {
			ofVec3f pt3D(oP[i].X / scaling, oP[i].Y / scaling);
			offsetPts.push_back(pt3D);
		}
	}
	return offsetPts;
}
Exemplo n.º 6
0
vector<ofVec3f> ofApp::offsetCell(list<int> & crv, AnisoPoint2f & pt) {
	float scaling = 1000;
	ClipperOffset co;
	co.ArcTolerance = 1;
	Path P;
	Paths offsetP;
	float offset = ofClamp(offsetPercent / sqrt(pt.jacobian->determinant()), minThick*0.5, maxThick*0.5);

	if (doSmooth) {
		
		for (auto index : crv) {
			ofVec3f v = linesMesh.getVertex(index);
			IntPoint iPt(v.x * scaling, v.y * scaling);
			P.push_back(iPt);
		}
		co.AddPath(P, jtRound, etClosedPolygon);
		co.Execute(offsetP, -offset*scaling);
		if(offsetP.size() == 0) return vector<ofVec3f>();
		P.clear();
		ofVec2f center;
		for (auto & v : offsetP[0]) {
			//ofVec3f v = linesMesh.getVertex(index);
			Vector2f p(v.X, v.Y);
			p = (*pt.jacobian)*p;
			IntPoint iPt(p.coeff(0), p.coeff(1));
			P.push_back(iPt);
			center += ofVec2f(iPt.X, iPt.Y);
		}
		center /= crv.size();
		CleanPolygon(P);
		
		co.Clear();
		co.AddPath(P, jtRound, etClosedPolygon);
		float radius = 9e20;

		//get exact radius from straight skeleton
		Polygon_2 poly;
		for (auto & pt : P) {
			poly.push_back(Point_2(pt.X, pt.Y));
		}
		boost::shared_ptr<Ss> iss = CGAL::create_interior_straight_skeleton_2(poly.vertices_begin(), poly.vertices_end());
		radius = 0;
		for (Ss::Vertex_handle vh = iss->vertices_begin(); vh != iss->vertices_end(); vh++) {
			if (!vh->has_infinite_time()) {
				radius = max(radius, (float)vh->time());
			}
		}

		//estimate radius
		//for (auto & iPt : P) {
		//	radius = min(radius, (iPt.X - center.x)*(iPt.X - center.x) + (iPt.Y - center.y)*(iPt.Y - center.y));
		//}
		//radius = sqrt(radius);
		//co.Execute(offsetP, -radius);
		//int tries = 0;
		//while (offsetP.size() == 0 && tries < 50) {
		//	radius *= .95;
		//	co.Execute(offsetP, -radius);
		//	tries++;
		//}
		//cout << tries << endl;
		radius *= filletPercent;
		co.Execute(offsetP, -radius);
		//radius = min(radius,(radius - offset*scaling)*filletPercent + offset*scaling);
		
		//co.Execute(offsetP, -offset*scaling);
		vector<ofVec3f> offsetPts;
		if (offsetP.size() > 0) {
			//visual offset for etching
			co.Clear();
			CleanPolygons(offsetP);
			co.AddPaths(offsetP, jtRound, etClosedPolygon);
			co.Execute(offsetP, radius);
			CleanPolygons(offsetP);
			Path longestP;
			int pLen = 0;
			for (auto & oP : offsetP) {
				if (oP.size() > pLen) {
					pLen = oP.size();
					longestP = oP;
				}
			}
			Matrix2f inverse = pt.jacobian->inverse();
			if (doEtchOffset) {
				co.Clear();
				for (auto & lPt : longestP) {
					Vector2f anisoPt(lPt.X, lPt.Y);
					anisoPt = inverse*anisoPt;
					lPt.X = anisoPt[0];
					lPt.Y = anisoPt[1];
				}
				co.AddPath(longestP, jtRound, etClosedPolygon);
				co.Execute(offsetP, etchOffset*scaling);
				longestP = offsetP[0];
			}
			for (int i = 0; i < longestP.size(); i++) {
				//ofVec3f pt3D(oP[i].X / scaling, oP[i].Y/ scaling);
				Vector2f anisoPt(longestP[i].X / scaling, longestP[i].Y / scaling);
				if(!doEtchOffset)anisoPt = inverse*anisoPt;
				offsetPts.push_back(ofVec3f(anisoPt.coeff(0), anisoPt.coeff(1)));
			}
		}
		return offsetPts;
	}
	else {
		for (auto index : crv) {
			ofVec3f v = linesMesh.getVertex(index);
			IntPoint iPt(v.x * scaling, v.y * scaling);
			P.push_back(iPt);
		}
		CleanPolygon(P);
		//Paths simplerP;
		//SimplifyPolygon(P, simplerP);
		//CleanPolygons(simplerP);
		//P = simplerP[0];
		//CleanPolygon(P);
		//Polygon_2 poly;
		//for (auto & pt : P) {
		//	poly.push_back(Point_2(pt.X, pt.Y));
		//}
		//boost::shared_ptr<Ss> iss = CGAL::create_interior_straight_skeleton_2(poly.vertices_begin(), poly.vertices_end());
		//float radius = 0;
		//for (Ss::Vertex_handle vh = iss->vertices_begin(); vh != iss->vertices_end(); vh++) {
		//	if (!vh->has_infinite_time()) {
		//		radius = max(radius, (float)vh->time());
		//	}
		//}
		
		//Paths simplerP;
		//SimplifyPolygon(P, simplerP);
		//co.AddPaths(simplerP, jtRound, etClosedPolygon);
		//radius = ofClamp(radius*offsetPercent, minThick*0.5*scaling, maxThick*0.5*scaling);
		co.AddPath(P, jtRound, etClosedPolygon);
		co.Execute(offsetP, -offset*scaling);
		vector<ofVec3f> offsetPts;
		if (offsetP.size() > 0) {
			CleanPolygons(offsetP);
			if (doEtchOffset) {
				co.Clear();
				co.AddPaths(offsetP, jtRound, etClosedPolygon);
				co.Execute(offsetP, etchOffset*scaling);
			}
			else {
				co.Clear();
				co.AddPaths(offsetP, jtRound, etClosedPolygon);
				co.Execute(offsetP, 1);
			}
			Path longestP;
			int pLen = 0;
			for (auto & oP : offsetP) {
				if (oP.size() > pLen) {
					pLen = oP.size();
					longestP = oP;
				}
			}
			Path & oP = longestP;
			for (int i = 0; i < oP.size(); i++) {
				ofVec3f pt3D(oP[i].X / scaling, oP[i].Y/ scaling);
				offsetPts.push_back(pt3D);
			}
		}
		return offsetPts;
	}

}
Exemplo n.º 7
0
void Boundary::Draw( ODDC& dc, PlugIn_ViewPort &piVP )
{
    //ODPath::Draw( dc, piVP );
    if ( m_bVisible && m_pODPointList->GetCount() > 2) {
        int l_iBoundaryPointCount = 0;
        m_bpts = new wxPoint[ m_pODPointList->GetCount() ];
        wxPoint r;
        for(wxODPointListNode *node = m_pODPointList->GetFirst(); node; node = node->GetNext()) {
            ODPoint *pOp = node->GetData();
            GetCanvasPixLL( &piVP, &r, pOp->m_lat, pOp->m_lon );
            m_bpts[ l_iBoundaryPointCount++ ] = r;
        }
        
        if( m_bExclusionBoundary && !m_bInclusionBoundary ) {
            // fill boundary with hatching
            wxGraphicsContext *wxGC = NULL;
            wxMemoryDC *pmdc = wxDynamicCast(dc.GetDC(), wxMemoryDC);
            if( pmdc ) wxGC = wxGraphicsContext::Create( *pmdc );
            else {
                wxClientDC *pcdc = wxDynamicCast(dc.GetDC(), wxClientDC);
                if( pcdc ) wxGC = wxGraphicsContext::Create( *pcdc );
            }
            
            wxGC->SetPen(*wxTRANSPARENT_PEN);
            wxColour tCol;
            tCol.Set(m_fillcol.Red(), m_fillcol.Green(), m_fillcol.Blue(), m_uiFillTransparency);
            wxGC->SetBrush( *wxTheBrushList->FindOrCreateBrush( tCol, wxBRUSHSTYLE_CROSSDIAG_HATCH ) );
            wxGraphicsPath path = wxGC->CreatePath();
            path.MoveToPoint(m_bpts[0].x, m_bpts[0].y);
            for( size_t i = 1; i < m_pODPointList->GetCount(); i++ )
            {
                path.AddLineToPoint(m_bpts[i].x, m_bpts[i].y);
            }
            path.CloseSubpath();
            wxGC->StrokePath(path);
            wxGC->FillPath( path );
            delete wxGC;
        } else if( !m_bExclusionBoundary && m_bInclusionBoundary && m_pODPointList->GetCount() > 3 ) {
            // surround boundary with hatching if there is more than 10 pixels different between points
            int l_imaxpointdiffX = 0;
            int l_imaxpointdiffY = 0;
            for( size_t i = 1; i < m_pODPointList->GetCount(); i++ ) {
                int l_ipointdiffX = abs(m_bpts[0].x - m_bpts[i].x);
                int l_ipointdiffY = abs(m_bpts[0].y - m_bpts[i].y);
                if(l_ipointdiffX > l_imaxpointdiffX) l_imaxpointdiffX = l_ipointdiffX;
                if(l_ipointdiffY > l_imaxpointdiffY) l_imaxpointdiffY = l_ipointdiffY;
            }
            if(l_imaxpointdiffX < 10 && l_imaxpointdiffY < 10 ) return;

            // Use ClipperLib to manage Polygon 
            // If needed simplify polygons to make shading stay outside
            Paths poly(1);
            for( size_t i = 0; i < m_pODPointList->GetCount(); i++ ) {
                poly[0] << IntPoint( m_bpts[i].x, m_bpts[i].y );
            }
            Paths polys;
            SimplifyPolygons( poly, polys );
            ClipperOffset co;
            Paths ExpandedBoundaries;
            co.AddPaths( polys, jtSquare, etClosedPolygon );
            co.Execute( ExpandedBoundaries, m_iInclusionBoundarySize );
            
            wxPoint *l_InclusionBoundary = new wxPoint[ ExpandedBoundaries[0].size() + 1 ];
            for( size_t i = 0; i < ExpandedBoundaries[0].size(); i++ )
            {
                l_InclusionBoundary[i].x = ExpandedBoundaries[0][i].X;
                l_InclusionBoundary[i].y = ExpandedBoundaries[0][i].Y;
            }
            // need to add first point to end to ensure the polygon is closed
            l_InclusionBoundary[ ExpandedBoundaries[0].size()].x = ExpandedBoundaries[0][0].X;
            l_InclusionBoundary[ ExpandedBoundaries[0].size()].y = ExpandedBoundaries[0][0].Y;

            int *l_iPolygonPointCount = new int[2];
            l_iPolygonPointCount[0] = m_pODPointList->GetCount();
            l_iPolygonPointCount[1] = ExpandedBoundaries[0].size() + 1;
            
            wxGraphicsContext *wxGC = NULL;
            wxMemoryDC *pmdc = wxDynamicCast(dc.GetDC(), wxMemoryDC);
            if( pmdc ) wxGC = wxGraphicsContext::Create( *pmdc );
            else {
                wxClientDC *pcdc = wxDynamicCast(dc.GetDC(), wxClientDC);
                if( pcdc ) wxGC = wxGraphicsContext::Create( *pcdc );
            }
            
            wxGC->SetPen(*wxTRANSPARENT_PEN);
            wxColour tCol;
            tCol.Set(m_fillcol.Red(), m_fillcol.Green(), m_fillcol.Blue(), m_uiFillTransparency);
            wxGC->SetBrush( *wxTheBrushList->FindOrCreateBrush( tCol, wxBRUSHSTYLE_CROSSDIAG_HATCH ) );
            wxGraphicsPath path = wxGC->CreatePath();
            path.MoveToPoint(m_bpts[0].x, m_bpts[0].y);
            for( int i = 0; i < l_iPolygonPointCount[0]; i++ ) {
                path.AddLineToPoint(m_bpts[i].x, m_bpts[i].y);
            }
            path.MoveToPoint(l_InclusionBoundary[0].x, l_InclusionBoundary[0].y);
            for( int i = 1; i < l_iPolygonPointCount[1]; i++ ) {
                path.AddLineToPoint(l_InclusionBoundary[i].x, l_InclusionBoundary[i].y);
            }
            path.CloseSubpath();
            wxGC->StrokePath(path);
            wxGC->FillPath( path );
            delete wxGC;
            ExpandedBoundaries.clear();
            polys.clear();
            poly.clear();
            co.Clear();
        }
        wxDELETEA( m_bpts );
    }

    
    ODPath::Draw( dc, piVP );
}
Exemplo n.º 8
0
void Boundary::DrawGL( PlugIn_ViewPort &piVP )
{
#ifdef ocpnUSE_GL
    if ( !m_bVisible ) return;
    
    ODDC dc;
    
    if(m_pODPointList->GetCount() > 2 ) {
        if( m_bExclusionBoundary || m_bInclusionBoundary ) {
            wxPoint *l_AllPoints;
            int     l_iAllPointsSizes[2];
            wxPoint *l_InclusionBoundary;
            int l_iBoundaryPointCount = 0;
            m_bpts = new wxPoint[ m_pODPointList->GetCount() ];
            wxPoint r;
            for(wxODPointListNode *node = m_pODPointList->GetFirst(); node; node = node->GetNext()) {
                ODPoint *pOp = node->GetData();
                GetCanvasPixLL( &piVP, &r, pOp->m_lat, pOp->m_lon );
                m_bpts[ l_iBoundaryPointCount++ ] = r;
            }
            
            if( !m_bExclusionBoundary && m_bInclusionBoundary ) {
                // surround boundary with hatching if there is more than 10 pixels different between points
                int l_imaxpointdiffX = 0;
                int l_imaxpointdiffY = 0;
                for( size_t i = 1; i < m_pODPointList->GetCount(); i++ ) {
                    int l_ipointdiffX = abs(m_bpts[0].x - m_bpts[i].x);
                    int l_ipointdiffY = abs(m_bpts[0].y - m_bpts[i].y);
                    if(l_ipointdiffX > l_imaxpointdiffX) l_imaxpointdiffX = l_ipointdiffX;
                    if(l_ipointdiffY > l_imaxpointdiffY) l_imaxpointdiffY = l_ipointdiffY;
                }

                if(l_imaxpointdiffX < 10 && l_imaxpointdiffY < 10 ) return;
                // Use ClipperLib to manage Polygon 
                // If needed simplify polygons to make shading stay outside
                Paths poly(1);
                for( int i = 0; i < l_iBoundaryPointCount; i++ ) {
                    poly[0] << IntPoint( m_bpts[i].x, m_bpts[i].y );
                }
                Paths simplePolys;
                SimplifyPolygons( poly, simplePolys );
                ClipperOffset co;
                Paths ExpandedBoundaries;
                co.AddPaths( simplePolys, jtSquare, etClosedPolygon );
                co.Execute( ExpandedBoundaries, m_iInclusionBoundarySize );
                
                int l_iInclusionBoundarySize = ExpandedBoundaries[0].size();
                l_InclusionBoundary = new wxPoint[ l_iInclusionBoundarySize + 1 ];
                for( int i = 0; i < l_iInclusionBoundarySize; i++ )
                {
                    l_InclusionBoundary[i].x = ExpandedBoundaries[0][i].X;
                    l_InclusionBoundary[i].y = ExpandedBoundaries[0][i].Y;
                }
                // need to add first point to end to ensure the polygon is closed
                l_InclusionBoundary[ l_iInclusionBoundarySize ].x = ExpandedBoundaries[0][0].X;
                l_InclusionBoundary[ l_iInclusionBoundarySize ].y = ExpandedBoundaries[0][0].Y;

                // Create one array containing the original polygon joined to the expanded polygon to allow filling
                l_iAllPointsSizes[0] = l_iBoundaryPointCount;
                l_iAllPointsSizes[1] = l_iInclusionBoundarySize;
                l_AllPoints = new wxPoint[ l_iBoundaryPointCount + l_iInclusionBoundarySize + 1 ];
                for( int i = 0; i < l_iBoundaryPointCount; i++ ) {
                    l_AllPoints[i] = m_bpts[ i ];
                }
                for( int i = 0; i < l_iInclusionBoundarySize; i++ ) {
                    l_AllPoints[ i + l_iBoundaryPointCount ] = l_InclusionBoundary[i];
                }
                ExpandedBoundaries.clear();
            }
            
            // Each byte represents a single pixel for Alpha. This provides a cross hatch in a 16x16 pixel square
            GLubyte slope_cross_hatch[] = {
                0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
                0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00,
                0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00,
                0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00,
                0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 
                0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
                0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00,
                0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00,
                0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00,
                0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF
            };        

            GLuint textureID;
            glGenTextures(1, &textureID);
            glBindTexture( GL_TEXTURE_2D, textureID );
            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
            glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, 16, 16, 0, GL_ALPHA, GL_UNSIGNED_BYTE, slope_cross_hatch );
            dc.SetTextureSize( 16, 16 );
            glEnable( GL_TEXTURE_2D );
            glEnable( GL_BLEND );
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
            glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
            wxColour tCol;
            tCol.Set(m_fillcol.Red(), m_fillcol.Green(), m_fillcol.Blue(), m_uiFillTransparency);
            dc.SetBrush( *wxTheBrushList->FindOrCreateBrush( tCol, wxPENSTYLE_SOLID ) );

            if( m_bExclusionBoundary ) {
                if(m_bIsBeingCreated) dc.DrawPolygonTessellated( m_pODPointList->GetCount(), m_bpts, 0, 0);
                else dc.DrawPolygonTessellated( m_pODPointList->GetCount() - 1, m_bpts, 0, 0);
            } else if( m_bInclusionBoundary ) {
                dc.DrawPolygonsTessellated( 2, l_iAllPointsSizes, l_AllPoints, 0, 0);
            }

            glDisable( GL_BLEND );
            glDisable( GL_TEXTURE_2D );
            glDeleteTextures(1, &textureID);

            wxDELETEA( m_bpts );
            
        } 
        
    }
    
    ODPath::DrawGL( piVP );
    
#endif
}
Exemplo n.º 9
0
float Polygon3D::computeInset(std::vector<float> &offsetDistances, Loop3D &pgonInset, bool computeArea)
{
	Loop3D cleanPgon; 
	double tol = 0.01f;

	cleanPgon = this->contour;

	int prev, next;
	int cSz = cleanPgon.size();

	if(cSz < 3){
		return 0.0f;
	}

	if(reorientFace(cleanPgon)){				
		std::reverse(offsetDistances.begin(), offsetDistances.end() - 1);
	}

	//if offsets are zero, add a small epsilon just to avoid division by zero
	for(size_t i=0; i<offsetDistances.size(); ++i){
		if(fabs(offsetDistances[i]) < tol){
			offsetDistances[i] = tol;
		}
	}

	//pgonInset.resize(cSz);

	QVector3D intPt;


	/*
	// GEN CODE--> It leads to self-intersection very often with non-convex polygons
	for(int cur=0; cur<cSz; ++cur){
		//Some geometry and trigonometry

		//point p1 is the point with index cur
		prev = (cur-1+cSz)%cSz; //point p0
		next = (cur+1)%cSz;	  //point p2

		if (Util::diffAngle(cleanPgon[prev] - cleanPgon[cur], cleanPgon[next] - cleanPgon[cur]) < 0.1f) {
			// For deanend edge
			QVector3D vec = cleanPgon[cur] - cleanPgon[prev];
			QVector3D vec2(-vec.y(), vec.x(), 0);

			float angle = atan2f(vec2.y(), vec2.x());
			for (int i = 0; i <= 10; ++i) {
				float a = angle - (float)i * M_PI / 10.0f;
				intPt = QVector3D(cleanPgon[cur].x() + cosf(a) * offsetDistances[cur], cleanPgon[cur].y() + sinf(a) * offsetDistances[cur], cleanPgon[cur].z());
				pgonInset.push_back(intPt);
			}
		} else {
			Util::getIrregularBisector(cleanPgon[prev], cleanPgon[cur], cleanPgon[next], offsetDistances[prev], offsetDistances[cur], intPt);
			
			// For acute angle
			if (pgonInset.size() >= 2) {
				if (Util::diffAngle(pgonInset[pgonInset.size() - 2] - pgonInset[pgonInset.size() - 1], intPt - pgonInset[pgonInset.size() - 1]) < 0.1f) {
					pgonInset.erase(pgonInset.begin() + pgonInset.size() - 1);
				}
			}

			pgonInset.push_back(intPt);
		}
	}*/
	
	// Old Code
	pgonInset.resize(cSz);
	for(int cur=0; cur<cSz; ++cur){
		//Some geometry and trigonometry

		//point p1 is the point with index cur
		prev = (cur-1+cSz)%cSz; //point p0
		next = (cur+1)%cSz;	  //point p2

		getIrregularBisector(cleanPgon[prev], cleanPgon[cur], cleanPgon[next],
			offsetDistances[prev], offsetDistances[cur], intPt);

		pgonInset[cur] = intPt;
	}



	//temp
	

	//Compute inset area
	if(computeArea){

		boost::geometry::ring_type<Polygon3D>::type bg_contour;
		boost::geometry::ring_type<Polygon3D>::type bg_contour_inset;
		float contArea;
		float contInsetArea;

		if(pgonInset.size()>0){
			boost::geometry::assign(bg_contour_inset, pgonInset);
			boost::geometry::correct(bg_contour_inset);

			if(boost::geometry::intersects(bg_contour_inset)){
				//printf("INSET: intersects\n");
				pgonInset.clear();
				//return 0.0f;
			} else {

				boost::geometry::assign(bg_contour, cleanPgon);
				boost::geometry::correct(bg_contour);
				//if inset is not within polygon
				if( !is2DRingWithin2DRing(bg_contour_inset, bg_contour) ){
					pgonInset.clear();
					//printf("INSET: ringWithRing\n");
					//return 0.0f;
				} else {
					contArea = fabs(boost::geometry::area(bg_contour));
					contInsetArea = fabs(boost::geometry::area(bg_contour_inset));

					if(contInsetArea < contArea){// OK EXIT
						//return boost::geometry::area(bg_contour_inset);
						return contInsetArea;
					} else {
						//printf("INSET: contInsetArea < contArea\n");
						pgonInset.clear();
						//return 0.0f;
					}
				}
			}
		} else {
			//printf("INSET: sides <0\n");
			pgonInset.clear();
			//return 0.0f;
		}
		// IT FAILED TRY SECOND METHOD
		{
			Path subj;
			Paths solution;
			for(int cur=0; cur<cSz; ++cur){
				subj << IntPoint(cleanPgon[cur].x()*1000,cleanPgon[cur].y()*1000);
			}
			/*subj << 
				ClipperLib::IntPoint(348,257) << IntPoint(364,148) << IntPoint(362,148) << 
				IntPoint(326,241) << IntPoint(295,219) << IntPoint(258,88) << 
				IntPoint(440,129) << IntPoint(370,196) << IntPoint(372,275);*/
			ClipperOffset co;
			co.AddPath(subj, jtSquare, etClosedPolygon);
			co.Execute(solution, -1000*7.5);
			pgonInset.resize(solution[0].size());
			for(int sN=0;sN<solution[0].size();sN++){
				pgonInset[sN]=QVector3D(solution[0][sN].X/1000.0f,solution[0][sN].Y/1000.0f,0);
			}
			//printf("Solutions %d\n",solution.size());
			return Area(solution[0]);
		}

	}
	return 0.0f;

}