如何删除不与特定矩形相交的所有SVG元素?

时间:2014-01-16 18:57:31

标签: svg

我有一个SVG图像,我想从中提取几个矩形区域作为独立的SVG图像。因为原始图像相当大,但与感兴趣区域相交的元素很小,我不希望完全位于裁剪的viewBox之外的元素保留在裁剪的SVG图像中。

从概念上讲,我正在寻找的是:

cropping diagram

裁剪的SVG(是的,输出必须是 SVG ,而不是位图)不应包含螺旋或星形的元素,因为它们完全落在感兴趣的区域之外。 (是的,非连接元素确实必须被删除,因为源SVG比裁剪的SVG多几个数量级,因为我打算以不同的方式裁剪数百次。)我希望能够指定由于要生成相当多的裁剪图像,命令行中感兴趣的区域也是如此。

有没有可以做到这一点的工具?

3 个答案:

答案 0 :(得分:0)

可以在svg rect对象内部和/或与rect对象相交的情况下解析SVG元素并将其标记为true / false。 这对你有用吗?

isEnclosed = mySVG.checkEnclosure(myElement, RectObj)
doesIntersect = mySVG.checkIntersection(myElement, RectObj)

答案 1 :(得分:0)

我使用Jordan Curve定理来测试svg多边形内的点。您的多边形将是您的viewBox。如果每个元素都有一个与之关联的目标点(即中心点)以确定是否要显示它,那么这可能对您有用。 以下是我使用的javascript :(警告:我认为多边形应该有逆时针点。在处理多边形时总是一个好主意)

//---Point-in-polygon: Jordan Curve Theorem---
function pointInPolygon(myPolygon,px,py)
{
    var pointsList=myPolygon.points

    var x
    var y
    var x1
    var y1
    var crossings=0
    var verts=pointsList.numberOfItems

//---Iterate through each line ---
    for ( var i = 0; i < verts; i++ )
    {
        var vertx=pointsList.getItem(i).x
        var verty=pointsList.getItem(i).y
        if(i<verts-1)
        {
            var vertxNext=pointsList.getItem(i+1).x
            var vertyNext=pointsList.getItem(i+1).y
        }
        else
        {
            var vertxNext=pointsList.getItem(0).x
            var vertyNext=pointsList.getItem(0).y
        }

    /* This is done to ensure that we get the same result when
       the line goes from left to right and right to left */
        if ( vertx < vertxNext){
            x1 = vertx;
            x2 = vertxNext;
        } else {
            x1 = vertxNext;
            x2 = vertx;
        }

        /* First check if the ray is possible to cross the line */
        if ( px > x1 && px <= x2 && ( py < verty || py <= vertyNext ) ) {
        var eps = 0.000000001;

        /* Calculate the equation of the line */
        var dx = vertxNext - vertx;
        var dy = vertyNext - verty;
        var k;

        if ( Math.abs(dx) < eps ){
            k = Infinity;
        } else {
            k = dy/dx;
        }

            var m = verty - k * vertx;

            /* Find if the ray crosses the line */
            y2 = k * px + m;
            if ( py <= y2 ){
                crossings++;
            }
        }
    }
    //---odd number of crossings: point inside polygon--
    var crossFlag=(crossings/2)+""
    if(crossFlag.indexOf(".")!=-1)
    return true;
    else
    return false;
} 

答案 2 :(得分:0)

由于您的svg元素已转换,您可能需要将它们转换为屏幕点。我已经使用以下javascript为各种svg元素(线,矩形,圆形,椭圆,多边形,折线和路径)

//----build a generic document SVG root to hold svg point---
function screenLine(line,svg)
{
    var sCTM = line.getCTM()
    var x1=parseFloat(line.getAttribute("x1"))
    var y1=parseFloat(line.getAttribute("y1"))
    var x2=parseFloat(line.getAttribute("x2"))
    var y2=parseFloat(line.getAttribute("y2"))

    var mySVGPoint1 = svg.createSVGPoint();
    mySVGPoint1.x = x1
    mySVGPoint1.y = y1
    mySVGPointTrans1 = mySVGPoint1.matrixTransform(sCTM)
    line.setAttribute("x1",mySVGPointTrans1.x)
    line.setAttribute("y1",mySVGPointTrans1.y)

    var mySVGPoint2 = svg.createSVGPoint();
    mySVGPoint2.x = x2
    mySVGPoint2.y = y2
    mySVGPointTrans2= mySVGPoint2.matrixTransform(sCTM)
    line.setAttribute("x2",mySVGPointTrans2.x)
    line.setAttribute("y2",mySVGPointTrans2.y)
    //---force removal of transform--
    line.setAttribute("transform","")
    line.removeAttribute("transform")
}
function screenCircle(circle,svg)
{
    var sCTM = circle.getCTM()
    var scaleX  = sCTM.a;

    var cx=parseFloat(circle.getAttribute("cx"))
    var cy=parseFloat(circle.getAttribute("cy"))

    var r=parseFloat(circle.getAttribute("r"))

    var mySVGPointC = svg.createSVGPoint();
    mySVGPointC.x = cx
    mySVGPointC.y = cy
    mySVGPointTransC = mySVGPointC.matrixTransform(sCTM)
    circle.setAttribute("cx",mySVGPointTransC.x)
    circle.setAttribute("cy",mySVGPointTransC.y)

    circle.setAttribute("r",r*scaleX)
    //---force removal of transform--
    circle.setAttribute("transform","")
    circle.removeAttribute("transform")
}
function screenEllipse(ellipse,svg)
{
    var sCTM = ellipse.getCTM()
    var scaleX  = sCTM.a;
    var scaleY  = sCTM.d;

    var cx=parseFloat(ellipse.getAttribute("cx"))
    var cy=parseFloat(ellipse.getAttribute("cy"))

    var rx=parseFloat(ellipse.getAttribute("rx"))
    var ry=parseFloat(ellipse.getAttribute("ry"))

    var mySVGPointC = svg.createSVGPoint();
    mySVGPointC.x = cx
    mySVGPointC.y = cy
    mySVGPointTransC = mySVGPointC.matrixTransform(sCTM)
    ellipse.setAttribute("cx",mySVGPointTransC.x)
    ellipse.setAttribute("cy",mySVGPointTransC.y)

    ellipse.setAttribute("rx",rx*scaleX)
    ellipse.setAttribute("ry",ry*scaleY)

    //---force removal of transform--
    ellipse.setAttribute("transform","")
    ellipse.removeAttribute("transform")
}
function screenRect(rect,svg)
{
    var sCTM = rect.getCTM()
    var scaleX  = sCTM.a;
    var scaleY  = sCTM.d;

    var x=parseFloat(rect.getAttribute("x"))
    var y=parseFloat(rect.getAttribute("y"))

    var width=parseFloat(rect.getAttribute("width"))
    var height=parseFloat(rect.getAttribute("height"))

    var mySVGPoint = svg.createSVGPoint();
    mySVGPoint.x = x
    mySVGPoint.y = y
    mySVGPointTrans = mySVGPoint.matrixTransform(sCTM)
    rect.setAttribute("x",mySVGPointTrans.x)
    rect.setAttribute("y",mySVGPointTrans.y)

    rect.setAttribute("width",width*scaleX)
    rect.setAttribute("height",height*scaleY)

    //---force removal of transform--
    rect.setAttribute("transform","")
    rect.removeAttribute("transform")
}
function screenPolyline(myPoly,svg)
{
    var sCTM = myPoly.getCTM()
    var pointsList = myPoly.points;
    var n = pointsList.numberOfItems;
    for(var m=0;m<n;m++)
    {
        var mySVGPoint = mySVG.createSVGPoint();
        mySVGPoint.x = pointsList.getItem(m).x
        mySVGPoint.y = pointsList.getItem(m).y
        mySVGPointTrans = mySVGPoint.matrixTransform(sCTM)
        pointsList.getItem(m).x=mySVGPointTrans.x
        pointsList.getItem(m).y=mySVGPointTrans.y
    }
    //---force removal of transform--
    myPoly.setAttribute("transform","")
    myPoly.removeAttribute("transform")
}

function screenPath(path,svg)
{
    var sCTM = path.getCTM()
    var scaleX  = sCTM.a;
    var scaleY  = sCTM.d;

    var segList=path.pathSegList
    var segs=segList.numberOfItems
    //---change segObj values
    for(var k=0;k<segs;k++)
    {
        var segObj=segList.getItem(k)

        if(segObj.x && segObj.y )
        {
            var mySVGPoint = svg.createSVGPoint();
            mySVGPoint.x = segObj.x
            mySVGPoint.y = segObj.y
            mySVGPointTrans = mySVGPoint.matrixTransform(sCTM)
            segObj.x=mySVGPointTrans.x
            segObj.y=mySVGPointTrans.y
        }

        if(segObj.x1 && segObj.y1)
        {
            var mySVGPoint1 = svg.createSVGPoint();
            mySVGPoint1.x = segObj.x1
            mySVGPoint1.y = segObj.y1
            mySVGPointTrans1 = mySVGPoint1.matrixTransform(sCTM)
            segObj.x1=mySVGPointTrans1.x
            segObj.y1=mySVGPointTrans1.y
        }
        if(segObj.x2 && segObj.y2)
        {
            var mySVGPoint2 = svg.createSVGPoint();
            mySVGPoint2.x = segObj.x2
            mySVGPoint2.y = segObj.y2
            mySVGPointTrans2 = mySVGPoint2.matrixTransform(sCTM)
            segObj.x2=mySVGPointTrans2.x
            segObj.y2=mySVGPointTrans2.y
        }

        if(segObj.r1)segObj.r1=segObj.r1*scaleX
        if(segObj.r2)segObj.r2=segObj.r2*scaleX
    }
    //---force removal of transform--
    path.setAttribute("transform","")
    path.removeAttribute("transform")
}

//---changes all transformed points to screen points---
function screenPolygon(myPoly,mySVG)
{
    var sCTM = myPoly.getCTM()
    var pointsList = myPoly.points;
    var n = pointsList.numberOfItems;
    for(var m=0;m<n;m++)
    {
        var mySVGPoint = mySVG.createSVGPoint();
        mySVGPoint.x = pointsList.getItem(m).x
        mySVGPoint.y = pointsList.getItem(m).y
        mySVGPointTrans = mySVGPoint.matrixTransform(sCTM)
        pointsList.getItem(m).x=mySVGPointTrans.x
        pointsList.getItem(m).y=mySVGPointTrans.y
    }
    //---force removal of transform--
    myPoly.setAttribute("transform","")
    myPoly.removeAttribute("transform")
}