Subscribe to this thread
Home - General / All posts - Buffer without rounded corners
ghelobytes
149 post(s)
#06-May-10 03:36

Hi guys!

Is it possible to perform a buffer preserving the corners of a polygon?

And also what is the purpose of the last parameter (epsilon) in this

method of Geom object: Geom.Buffer(BufferType, width, epsilon);

Thanks in advance!


namria, philippines

ghelobytes@yahoo.com

Sloots

678 post(s)
#06-May-10 04:54

How about using Transform | Scale on a copy of the object?


http://www.mppng.nl/manifold/pointlabeler

ghelobytes
149 post(s)
#06-May-10 05:54

hi sloots,

I already tried using Scale but I need the new geom to be of uniform distance from the edges of the original geom.


namria, philippines

ghelobytes@yahoo.com

BCowper


1,275 post(s)
#06-May-10 07:15

Sounds like you want the same functionality as the Offset command in AutoCAD, can't think of a way to replicate this command in Manifold. If you or you have a colleague who has AutoCAD it may better to create the geometry in CAD.

Mike Pelletier

2,122 post(s)
#06-May-10 08:42

Here's a nice query from Tjhb that's modified to include a scale input. Maybe this could be will work for you.

Edit: Ah, I see now that the scale function doesn't work for irregular areas.

--SQL

PARAMETERS [Copies] SINGLE, [Direction] DOUBLE, [Offset] DOUBLE, [Scale] DOUBLE;

INSERT INTO [Drawing] ([Geom (I)])

SELECT Scale(MoveVertically(MoveHorizontally([ID], [N] * [dX]), [N] * [dY]), [Scale])

FROM

[Drawing] AS [D]

INNER JOIN

(SELECT [Digit 4] * 1000 + [Digit 3] * 100 + [Digit 2] * 10

+ [Digit 1] + 1 AS [N]

FROM

(VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9) NAMES ([Digit 4]))

CROSS JOIN

(VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9) NAMES ([Digit 3]))

CROSS JOIN

(VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9) NAMES ([Digit 2]))

CROSS JOIN

(VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9) NAMES ([Digit 1])))

ON [D].[Selection (I)]

AND [N] <= [Copies]

CROSS JOIN

(VALUES

([Offset] * Sin(Deg2Rad([Direction])),

[Offset] * Cos(Deg2Rad([Direction])))

NAMES ([dX], [dY]));

tjhb
10,094 post(s)
#06-May-10 14:57

The epsilon is the location precision that will be used for the operation. Its function is more obvious if you consider say Geom.Normalize(epsilon).

The task here is one that is much easier for the eye than for code.

To "perform a buffer preserving the corners of a polygon" is very easily said and understood. But how it breaks down is less easy.

One way of doing it:

  • Get each side S of the polygon P
  • Get the centroid C of each S
  • Rotate each S by 90° to give the displacement axis A
  • Use P to clip (subtract) each A, leaving just the exterior part
  • Find which end of each A now touches P, and if this is not the start point of A, reverse A
  • Find the point D at distance R (the "buffer" distance) along each A
  • Calculate the distances dX and dY between each pair (C, D)
  • Move each S by the corresponding dX and dY

(Now the hard part, not broken down:)

  • Extend each S, in both directions, far enough to intersect with its neighbouring S
tjhb
10,094 post(s)
#06-May-10 17:31

Here's a more grown-up procedure.

  • Split the area into its vertices, with an index
  • Split the area into its sides
  • For each vertex
    • Find the two sides that touch it
    • Find the bearings B1 and B2 of the two sides
    • From B1 and B2, derive the interior angle θ, and B3, the bearing of the line bisecting θ
    • Given the desired "buffer" distance D, calculate the radius to the displaced vertex, R = D / 0.5 sin θ
    • Move the vertex the distance R in the direction B3
  • Pair each displaced vertex with its neighbour (matching index to index + 1; index to 0 for the last)
  • Draw a line connecting each pair of vertices
  • Group the lines
  • Convert to lines to an area
tjhb
10,094 post(s)
#06-May-10 17:53

[Last line should read "Convert the lines to an area".]

ghelobytes
149 post(s)
#06-May-10 21:44

What I'm actually trying to do is label the corners of parcels. But those labels must be placed inside the parcel. Using InnerBuffer, I was able to accomplish this with a square shaped polygon. But this is difficult to apply to an irregularly-shaped polygon.

To be more clear, this is an example of what I'm trying to achieve:

http://www.mathopenref.com/polygoninteriorangles.html


namria, philippines

ghelobytes@yahoo.com

tosborn

231 post(s)
#06-May-10 22:09

To explore this issue further, attached is a Manifold Map file with an experimental script I threw together. I've read what I can on-line about straight skeletons, but never really found any code that I could incorporate into a script. So this script works along the lines that Tim sketched out above. From the Map or the Drawing select one of the concave area objects and run the script (convex areas don't seem to offer much of a problem). The script will ask for an offset. A positive number will create an outer offset, and a negative number will create an inner offset. The script produces a set of intersecting offset lines that could be used as input to the bounded area transform.

To play around, select the area on the left and enter a value of 20. There will be a little downward indentation at the top of the offset lines. A single bounded area could be made from those lines. Delete those lines and now re-run with a value of 25. Notice that now there is a little upward bump at the top. If we ran bounded areas on these lines 2 areas would be created. But the area created inside the upward bump would not be part of the final offset. Now play around with the area object on the right that will self-intersect itself after a certain point with an outer offset. I wonder what exotic area shapes would cause this approach to fail?

Tim Osborn

Attachments:
offsetpolygon.map

KlausDE

6,410 post(s)
#06-May-10 23:04

Tim, this is another great tool as it is and a perfect design study for a powerfull feature request.

Restriced to area input the sign of the offset is sufficient as input. With an additional mouse interactive input this could be extended to line input where I would need it most. You need another input to determine the side of the line where the offset is created. Functions with this type of 2-parameter input don't fit into the Drawings Transform Toolbar but go into the Edit Toolbar. With a graphically determined offset we could implicitely get the side.

But in this respect I love AutoCADs input mode that takes graphically constructed input by mouse on pair with concurrent numeric input.


Do you really want to ruin economy only to save the planet?

tjhb
10,094 post(s)
#07-May-10 03:47

Very nice Tim—I'm jealous of your knowledge of matrix algebra, which I can't do to save my life. Extremely economical.

ghelobytes
149 post(s)
#07-May-10 04:14

tnx for all of your reply guys...

and nice code Tim... exactly what I needed...

but one more thing... do you happen to know

how to get the interior angles of irregular polygon?

i'm trying to solve my interior labeling problem with

pure mathematics alone... something like what you

can see here: http://www.mathopenref.com/polygoninteriorangles.html


namria, philippines

ghelobytes@yahoo.com

tosborn

231 post(s)
#07-May-10 19:34

Attached below is a script to produce internal angles for a regular or irregular polygon. You select one polygon and run the script. It will produce a set of points...one for each vertex of the polygon. The internal angle of the polygon at each vertex is then recorded in a column called "Internal Angle" in the owned table of the drawing. You could use that to create labels. It seems to be working correctly but double check its results against what you expect.

Attachments:
Internal Polygon Angles.txt

tjhb
10,094 post(s)
#08-May-10 14:57

I've written an SQL version of this function, creating a new area object buffered either in or out, more or less along the lines of the method I sketched above, but using vector arithmetic rather than bearings, and in particular unit vectors.

Manipulating vectors is something I've wanted to learn to do for some time. I'm amazed how simple and powerful a technique it is. Now I can take it into territory that previously has been out of my grasp, like making normal maps for shading terrain and 3D models in Photoshop.

So I want to post all of this because it might help others as well. Because I was learning new stuff the code is quite long and full of comments. I hesitate to post it in this thread, because I don't want to hide it away in an attachment, but I also don't want to get in the way of Tim's excellent scripted code (which is in attachments).

So I thought I'd stick it a new thread, with a link from here. Good idea?

tosborn

231 post(s)
#08-May-10 15:53

Sounds good to me. Looking forward to reading your code and comments!

ghelobytes
149 post(s)
#09-May-10 07:01

will be waiting for your post on that...


namria, philippines

ghelobytes@yahoo.com

tjhb
10,094 post(s)
#15-May-10 03:09

Sorry for the delay.

When I last posted, my code dealt only with single-branched areas.

I had some inspiration and saw how to deal with areas having multiple islands and/or holes, in a way applicable to other methods and projects. Which was useful.

Then it occurred to me that my method failed to account for areas with "redundant" coordinates, i.e. coordinates that do not change the shape of the object. (The scare quotes are because sometimes these coordiates are not redundant, as when an area has been normalized in the presence of a line passing through it.)

That threw up some interesting problems, because of faults in my logic and an idiosyncrasy in Manifold. I'm still working on those but it's almost there.

KlausDE

6,410 post(s)
#15-May-10 03:09

I have generalized Tim's (@tosborn this time) Offset Tool to work with the Active Component in a Map or Drawing window and to work with Lines, too. And I added a JoinLines to keep results simple.

Notice that unlike the Transform Toolbar the input messagebox takes floats of buffer distances with the decimal delimiter of the regional settings of the machine.

Attachments:
OffsetPolygonOrLine.txt


Do you really want to ruin economy only to save the planet?

tosborn

231 post(s)
#15-May-10 12:26

Great additions Klaus!

I've noticed that on a polygon when one creates bounded areas from the offset lines, if multiple areas are created the ones that wind clockwise are the extraneous areas that are not part of the true offset.

geozap
264 post(s)
#11-Oct-14 06:58

I am trying to make 2 modifications to this script:

1. I want it to work for many selected objects

2. The offset distance is not to be given by the user, but taken from a column in the drawing. So it can be different for each object to be offset.

It's the first time I am trying to edit a manifold script and although I have some knowledge of vb and java, I have had no luck with this one and I keep getting Syntax errors.

So, I would like some general help on scripting on:

a)how to take distance value from a column

b)how to loop through selected objects and apply the Offset

Any links to vbscript examples that do something similar to a and b is really appreciated.

Thanks a lot for any help!

oisink
370 post(s)
#11-Oct-14 15:24

to loop through an objectset called objSelectionSet try

For each obj in objSelectionSet

' my code

Next

(Edit - why is my code formatting button not working?)

In terms of getting the distance value from a column, which column, where. If it is an attribute of an object, then object.record.data("column") gets the contents of the column.

See http://www.georeference.org/Forum/t123578.14#123994 or

http://www.georeference.org/Forum/t119153.1#119154 or many other examples on the forum

Does this help...or post an example.

Oisin

geozap
264 post(s)
#11-Oct-14 19:12

Thanks!

I used what you wrote about object.record.data("column") to get distance from a column. I just changed 2 lines of code.

But it seems that looping in the way to get the right results is not that simple and is beyond my totally beginner understanding of vbscript.

oisink
370 post(s)
#12-Oct-14 11:26

Post an example and I'll have a look

Oisin

geozap
264 post(s)
#12-Oct-14 16:49

The script I tried to edit is the one named "OffsetPolygonOrLine.txt" posted by user KlausDE, 6 posts before.

I made it work with distance taken from a column named "distance" by changing the lines the user enters distance from

distance = inputbox("Enter Offset Distance(+ to the right, - to the left)")

to:

distance=selObj.record.data("distance")

So, now it works without the user having to enter the offset distance manually.

But it works for one selected object only. To make it work for many selected objects I tried to make it loop with "for next". But I am not familiar with vbscript and manifold programming as so I don't understand how the code works and I didn't manage to make the code produce correct results.

volker

1,086 post(s)
#21-Oct-14 09:50

I have replied to SPAM so my post is not seen ....

here is a map from my script-archive.

The Script is written by Tim Osborne and modified by Klaus Engelberg.

Attachments:
Buffer_edge.map


http://www.thegisservicesector.de

geozap
264 post(s)
#21-Oct-14 15:07

Your script is the same as the one posted by user KlausDE in 15 May 2010, isn't it?

volker

1,086 post(s)
#22-Oct-14 07:33

could be...

like i wrote "The Script is written by Tim Osborne and modified by Klaus Engelberg."

you could modify

if selectedobjset.count<>1 then

to "<1" but then it don`t work right, some lines are overshoot.

Sorry i am not familiar wit vbscript, too....


http://www.thegisservicesector.de

Manifold User Community Use Agreement Copyright (C) 2007-2021 Manifold Software Limited. All rights reserved.