示例#1
0
bool MaskPolygon::clipPolygon(const FDiff2D center,const double radius)
{
    if(radius<=0 || m_polygon.size()<3)
    {
        return false;
    };
    FDiff2D s=m_polygon[m_polygon.size()-1];
    bool s_inside=clip_insideCircle(s,center,radius);
    FDiff2D p;
    VectorPolygon newPolygon;
    bool needsFinalArc=false;
    double angleCovered=0;
    double angleCoveredOffset=0;
    for(unsigned int i=0;i<m_polygon.size();i++)
    {
        p=m_polygon[i];
        bool p_inside=clip_insideCircle(p,center,radius);
        if(p_inside)
        {
            if(s_inside)
            {
                //both points inside
                newPolygon.push_back(p);
            }
            else
            {
                //line crosses circles from outside
                std::vector<FDiff2D> points=clip_getIntersectionCircle(p,s,center,radius);
                DEBUG_ASSERT(points.size()==1);
                angleCovered+=angle_between(s-center,points[0]-center);
                if(newPolygon.size()==0)
                {
                    needsFinalArc=true;
                    angleCoveredOffset=angleCovered;
                }
                else
                {
                    generateArc(newPolygon,points[0],center,radius,angleCovered<0);
                };
                newPolygon.push_back(points[0]);
                newPolygon.push_back(p);
            };
        }
        else
        {
            if(!s_inside)
            {
                //both points outside of circle
                std::vector<FDiff2D> points=clip_getIntersectionCircle(s,p,center,radius);
                //intersection can only be zero points or 2 points
                if(points.size()>1)
                {
                    angleCovered+=angle_between(s-center,points[0]-center);
                    if(newPolygon.size()==0)
                    {
                        needsFinalArc=true;
                        angleCoveredOffset=angleCovered;
                    }
                    else
                    {
                        generateArc(newPolygon,points[0],center,radius,angleCovered<0);
                    };
                    newPolygon.push_back(points[0]);
                    newPolygon.push_back(points[1]);
                    angleCovered=angle_between(points[1]-center,p-center);
                }
                else
                {
                    angleCovered+=angle_between(s-center,p-center);
                };
            }
            else
            {
                //line segment intersects circle from inside
                std::vector<FDiff2D> points=clip_getIntersectionCircle(s,p,center,radius);
                angleCovered=0;
                DEBUG_ASSERT(points.size()==1);
                newPolygon.push_back(points[0]);
            };
        };
        s=p;
        s_inside=p_inside;
    };
    if(needsFinalArc && newPolygon.size()>1)
    {
        generateArc(newPolygon,newPolygon[0],center,radius,(angleCovered+angleCoveredOffset)<0);
    };        
    m_polygon=newPolygon;
    return (m_polygon.size()>2);
};
示例#2
0
文件: vplStroke.cpp 项目: msahlen/vpl
    // Make one closed path by adding the points of the inner path
    void Stroker::endStroke()
    {
        switch(endType_)
        {
            // Simplest case, just add the inner points
            case cButtEnd:
            {
                for(vplUint i = innerPoints_.getItemCount(); i > 0;i-=2)
                {
                    outerPoints_.add(innerPoints_[i - 2]);
                    outerPoints_.add(innerPoints_[i - 1]);
                }

                // Close the path
                outerPoints_.add(outerPoints_[0]);
                outerPoints_.add(outerPoints_[1]);
            }
                break;

            // End outer path with an arc, then add the inner points.
            // Finalize with a closing arc to the first point
            case cRoundEnd:
            {
                Winding winding = determineWinding(normal_,invert(normal_));

                generateArc(currentPoint_,normal_,invert(normal_),
                             winding,&outerPoints_);

                for(vplUint i = innerPoints_.getItemCount(); i > 0;i-=2)
                {
                    outerPoints_.add(innerPoints_[i - 2]);
                    outerPoints_.add(innerPoints_[i - 1]);
                }

                winding = determineWinding(invert(firstNormal_),firstNormal_);

                generateArc(firstPoint_,invert(firstNormal_),firstNormal_,
                            winding,&outerPoints_);

                // Close the path
                outerPoints_.add(outerPoints_[0]);
                outerPoints_.add(outerPoints_[1]);
            }
                break;

            // Add a rectangle with sides stroke width/2 x stroke width
            case cSquareEnd:
            {
                // Use the normals for calculation of the ends
                Vector dir(-normal_.y_,normal_.x_);
                Vector firstDir(-firstNormal_.y_,firstNormal_.x_);

                dir.normalize();
                firstDir.normalize();

                scale_.transform(dir);
                scale_.transform(firstDir);

                dir *= size_ / 2;
                firstDir *= size_ / 2;

                Vector v1 = currentPoint_ + normal_ + dir;
                Vector v2 = currentPoint_ - normal_ + dir;

                addPoint(&outerPoints_,v1);
                addPoint(&outerPoints_,v2);

                for(vplUint i = innerPoints_.getItemCount(); i > 0;i-=2)
                {
                    outerPoints_.add(innerPoints_[i - 2]);
                    outerPoints_.add(innerPoints_[i - 1]);
                }

                v1 = firstPoint_ - firstNormal_ - firstDir;
                v2 = firstPoint_ + firstNormal_ - firstDir;

                addPoint(&outerPoints_,v1);
                addPoint(&outerPoints_,v2);

                // Close the path
                outerPoints_.add(outerPoints_[0]);
                outerPoints_.add(outerPoints_[1]);
            }
                break;
        }

        innerPoints_.clear();
    }