OffsetContour function

There’s a question on SO:

And a forum topic:

With some changes of the ProfiledContourGeometry, there is a function which offsets points of a contour - OffsetContour :

OffsetContour

  function OffsetContour(offset, contour) {
  	
    let result = [];
    
    offset = new THREE.BufferAttribute(new Float32Array([offset, 0, 0]), 3);
    
    for (let i = 0; i < contour.length; i++) {
      let v1 = new THREE.Vector2().subVectors(contour[i - 1 < 0 ? contour.length - 1 : i - 1], contour[i]);
      let v2 = new THREE.Vector2().subVectors(contour[i + 1 == contour.length ? 0 : i + 1], contour[i]);
      let angle = v2.angle() - v1.angle();
      let halfAngle = angle * 0.5;
			
      let hA = halfAngle;
      let tA = v2.angle() + Math.PI * 0.5;
      
      let shift = Math.tan(hA - Math.PI * 0.5);
      let shiftMatrix = new THREE.Matrix4().set(
             1, 0, 0, 0, 
        -shift, 1, 0, 0,
             0, 0, 1, 0,
             0, 0, 0, 1
      );
			
      
      let tempAngle = tA;
      let rotationMatrix = new THREE.Matrix4().set(
        Math.cos(tempAngle), -Math.sin(tempAngle), 0, 0,
        Math.sin(tempAngle),  Math.cos(tempAngle), 0, 0,
                          0,                    0, 1, 0,
                          0,                    0, 0, 1
      );

      let translationMatrix = new THREE.Matrix4().set(
        1, 0, 0, contour[i].x,
        0, 1, 0, contour[i].y,
        0, 0, 1, 0,
        0, 0, 0, 1,
      );

      let cloneOffset = offset.clone();

      shiftMatrix.applyToBufferAttribute(cloneOffset);
      rotationMatrix.applyToBufferAttribute(cloneOffset);
      translationMatrix.applyToBufferAttribute(cloneOffset);

      result.push(new THREE.Vector2(cloneOffset.getX(0), cloneOffset.getY(0)));
    }
    

    return result;
  }

Of course, it is a simple and imperfect concept. For example, it doesn’t check for self-intersection of a result contour. But, at least, it works with not so complex contours :slight_smile:

8 Likes

Hello this is an awesome algorithm for my small polygon is it working fine but when i am trying with the larger polygon it fails please can you help me in this even in your fiddle i tried so i am not getting the exact polygon shape that i have in the picture attachedoffset
http://jsfiddle.net/hzgrp8nt/ fiddle with my points

@Alex


That’s what I see in the provided jsfiddle.

@prisoner849, old topic but would like to note a special case where the shape is not fully symmetric.

One complication I faced was the disappearance of some edges that I had to handle in a while loop. In my application I added a debug mode that helps see the points and lines

correct_retraction

retraction_discard

Here a link to the function in action

This example is not integrated with three.js but as you mentioned this is more a math geometry related issue and I believe integration in three.js shouldn’t be difficult in comparison.

here even a link to a live demo if needed to the voronoi cells retraction in action. Hint it’s the slider without name that is used for debug second below “min cell edge”
https://websvg.github.io/voronoi/

2 Likes

That’s what I did, making a custom addon for AutoCAD years ago :slight_smile: :beers:

1 Like

@prisoner849 please check the fiddle here due to the offset value the offsetCounter is giving me some wrong points especially the last one is really big can you tell me the reason and also i want to learn each part of this algorithm please suggest some links to go through it
http://jsfiddle.net/stb5kxag/8/

@Alex
Why do you have three consequent points of the same coordinates?

  new THREE.Vector2(-0.36216475270688875,0.09509806858932279),
  new THREE.Vector2(-0.36216475270688875,0.09509806858932279),
  new THREE.Vector2(-0.36216475270688875,0.09509806858932279)

Leave just one.

no actually its due to the polygon i imported from the dxf as i shared the image also to you and i figure out some thing with the offset is going on because if i am providing offset as 1 to your offset counter function it is not giving me the proper result but if we turn it into i*0.1 it work fine @prisoner849 i really appreciate if you share some link along with the solution that contain all the concepts theory used into your algo

This topic based on another one: ProfiledContourGeometry, so you can find some explanation there.
I wouldn’t recommend to have consequent duplicates of points in a contour.

@prisoner849 your suggestion really help me but here one thing i notices in my project if i provide the -offset so the offset polygon come inside the polygon and if i provide + offset than it come outside generally but in this polyon case it is not coming inside as i am providing the -offset please @prisoner849 can you suggest me on this or help.

That’s what I have:


in range -0.1…0.1 with step 0.1, and without duplicates of vertices.

@prisoner849 i am new to three js so please dont be bother i am glad for your attentions
here my question is
OffsetContour(0.1, contour1)
in this method if i pass the negative value of offset so the offset polygon will be drawn inside the main polygon if so than i am unable to get it inside the main polygon always it is coming out

@prisoner849 any thoughts on this

Use this approach: Wall building in a level-editor

1 Like

@prisoner849 see this fiddle we have two polygon red and green here the red should come inside but it is not why?
http://jsfiddle.net/42q7pst1/8/

Maybe because of the order of vertices? CW or CCW.

@prisoner849 i checked to make the points in ccw way and it is working fine but according to requirement the points can be any combination how we can make it work for any combination without converting CW to CCW or vise versa

I read your post @prisoner849 i see you created this for vector2. Can you guide me what changes this algorithm need for vector3 points

@Alex Do you mean that you’ve got a flat shape, that is not on XY plane?

Yes i got flat shape that is on x,z plane. @prisoner849 you inputs are really valuable at this stage.
Your algorithm is really helping me but some times i get wrong offset also i think its only because i am dealing in the x,z plane.

Here for an example

[
{
“x”: 0.2587492907388422,
“y”: 0.4153157504699383
},
{
“x”: 0.25980117624347054,
“y”: 0.40617683058502696
},
{
“x”: 0.26564295222986334,
“y”: 0.4084280404592947
},
{
“x”: 0.2798622383099108,
“y”: 0.4017477866234108
},
{
“x”: 0.27779138030333667,
“y”: 0.41049061888718047
},
{
“x”: 0.2587492907388422,
“y”: 0.4153157504699383
}
]

These are my point at the moment so after using the offset function i am getting
this shape pic

But i am expecting an offset means a border outside with same structure as i have in red. When i reverse the above point i am getting the proper shape but what is the root cause when i need to reverse the point and when no i dont understand that or is there any way to make this algorithm stable for my requirement please let me know