Exemplo n.º 1
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.º 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;
}
Exemplo n.º 3
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.º 4
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.º 5
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
}