Is masking available for vector shapes, outside of PImage.mask()?

Can I mask a vector shape using another vector shape, and have the end result be a vector? (e.g., for exporting to vector PDF / SVG) Or is masking available only for pixels, meaning both that the mask itself needs to be a raster image, and the thing getting masked needs to be a raster image as well?

Is there some workaround hack that would allow for masking vectors with vectors?

not an expert in this area, but afaik you can load svgs into a shape and svg has some masking ability.

I would think that (lets talk about polygons, not bezier contours) it will something you have to do yourself. might be tedious, but finding intersection points of two lines is not the most horrible task I can imagine.

some time ago I made this method: maybe it’s helpful…

//--------------------------------------------------
PVector calculateIntersection (PVector P1, PVector v1, PVector P3, PVector v2) {
  float parallel;
  parallel = v1.x*v2.y-v2.x*v1.y;
  if (parallel == 0) return P3;
  PVector P2 = new PVector(0, 0);
  PVector P4 = new PVector(0, 0);
  PVector S = new PVector(0, 0);
  P2.set(P1);
  P2.add(v1);
  P4.set(P3);
  P4.add(v2);
  //---------------
  S.x = ((P4.x-P3.x)*(P2.x*P1.y-P1.x*P2.y)-(P2.x-P1.x)*(P4.x*P3.y-P3.x*P4.y))/((P4.y-P3.y)*(P2.x-P1.x)-(P2.y-P1.y)*(P4.x-P3.x));
  S.y = ((P1.y-P2.y)*(P4.x*P3.y-P3.x*P4.y)-(P3.y-P4.y)*(P2.x*P1.y-P1.x*P2.y))/((P4.y-P3.y)*(P2.x-P1.x)-(P2.y-P1.y)*(P4.x-P3.x));
  return S;
}
3 Likes

That’s a great question!

You could install from the IDE the Geomerative library that can do SVG and “RShape” clipping and intersections. (RShape is a vector object for the lib).

import geomerative.*;

RShape shp1;
RShape shp2;
RShape shp3;
RShape cursorShape;

void setup()
{
  size(400, 400);
  smooth();

  RG.init(this);

  shp1 = RG.loadShape("Toucan.svg");
  shp2 = RShape.createStar(0, 0, 100.0, 80.0, 20);

  shp1.centerIn(g);
}

void draw()
{
  background(255);    
  translate(width/2,height/2);

  cursorShape = new RShape(shp2);
  cursorShape.translate(mouseX - width/2, mouseY - height/2);
  
  // Only intersection() does not work for shapes with more than one path
  shp3 = RG.intersection( shp1, cursorShape );
  
  strokeWeight( 3 );

  if(mousePressed){
    fill( 0 , 220 , 0 , 30 );
    stroke( 0 , 120 , 0 );
    RG.shape(shp1);

    fill( 220 , 0 , 0 , 30 );
    stroke( 120 , 0 , 0 );
    RG.shape(cursorShape);
  }
  else{
    fill( 220 );
    stroke( 120 );
    RG.shape(shp3);
  }
}

I really wish there would be a simpler way. I have found some poly clipping libraries I thought I could adapt, but they are horribly broken :frowning: (watch me crash here Boolean operation in polygons)

2 Likes

Thanks for the answers, guys. The Geomerative library is interesting. I tested out a simple intersection op and saved to PDF. The resulting boolean’d geometry is kinda dense, but I can clean it up in Adobe Illustrator using a Path > Simplify op, and the results are decent. I’ll explore both things more, and learn more about PVector objects.

1 Like

I’m glad you have some promissing results!

Oh, I’m afraid PVector is not what you are looking for, it is a simple [x, y, z] data structure with methods for vector maths only. :frowning:

A PShape can be a vector-graphics container, but it lacks the “boolean” (union, difference, intersection) methods of RShape.

1 Like