supposing that your polynom is given with 2 dimensional points in counter-clockwise ordering. For example:
points = {{4, 0}, {1, 2}, {0, 4}, {-3, 0}, {0, -1}};
Lets define a "test area" in which the polynom is embeded:
{minX, maxX} = {Min@#, Max@#} &@points〚All, 1〛;
{minY, maxY} = {Min@#, Max@#} &@points〚All, 2〛;
The edges of the polynom are lines which are defined with 2 corner points:
lines = Partition[points, 2, 1, 1];
The following will calculate the intersection points with the horizontal lines, based on basical analysis (y = M x + B)
intersectionPointsX = {};
For[y = minY + 1, y < maxY, y++,
crossingLines = Select[lines, #[[1, 2]] =!= #[[2, 2]] &];
For[j = 1, j <= Length[crossingLines], j++,
{ux, uy} = crossingLines〚j, 1〛;
{vx, vy} = crossingLines〚j, 2〛;
If[Min[uy, vy] <= y <= Max[uy, vy],
If[ux == vx,
AppendTo[intersectionPointsX, {ux, y}],
M = -((-uy + vy)/(ux - vx)); B = -((uy vx - ux vy)/(ux - vx));
AppendTo[intersectionPointsX, {(y - B)/M, y}]
]
]
]
]
Lets do the same with the vertical lines:
intersectionPointsY = {};
For[x = minX + 1, x < maxX, x++,
crossingLines = Select[lines, #[[1, 1]] =!= #[[2, 1]] &];
For[j = 1, j <= Length[crossingLines], j++,
{ux, uy} = crossingLines〚j, 1〛;
{vx, vy} = crossingLines〚j, 2〛;
If[Min[ux, vx] <= x <= Max[ux, vx],
If[ux == vx,
AppendTo[intersectionPointsY, {x, (uy+vy)/2}]
,
M = -((-uy + vy)/(ux - vx)); B = -((uy vx - ux vy)/(ux - vx));
AppendTo[intersectionPointsY, {x, M x + B}]
]
]
]
]
Now we Gather these intersection points with respect to their intersecting line. We also delete possible dublicates.
intersectionPointsX =
DeleteDuplicates /@ GatherBy[intersectionPointsX, Last];
intersectionPointsY =
DeleteDuplicates /@ GatherBy[intersectionPointsY, First];
Edit:
The following transformations will include more special cases, if there are more than 2 intersections for one line:
intersectionPointsX =
If[Length[#] > 2,
Sort[Select[Partition[#, 2, 1], ! MemberQ[lines, #] &],
Abs[#1[[1, 1]] - #1[[2, 1]]] < Abs[#2[[1, 1]] - #2[[2, 1]]] &][[
1]], #] & /@ intersectionPointsX
intersectionPointsY =
If[Length[#] > 2,
Sort[Select[Partition[#, 2, 1], ! MemberQ[lines, #] &],
Abs[#1[[1, 1]] - #1[[2, 1]]] <
Abs[#2[[1, 1]] - #2[[2, 1]]] &][[1]], #] & /@
intersectionPointsY;
Lets calculate the total segmentslenth in x- and y direction:
ΔX =
Total[Abs[Subtract @@@ intersectionPointsX〚All, All, 1〛]] // N;
ΔY =
Total[Abs[Subtract @@@ intersectionPointsY〚All, All, 2〛]] // N;
so the total lenth of line segments is:
totalSegmentsLenth = ΔX + ΔY;
In this example it is:
31
Visualization
ListPlot[{points, Flatten[intersectionPointsX, 1],
Flatten[intersectionPointsY, 1]},
PlotStyle -> {Directive[Red, PointSize[0.02], Opacity[.5]],
Directive[Blue, PointSize[0.02], Opacity[.5]],
Directive[Green, PointSize[0.02]]},
Prolog -> {Line[points~Join~{points〚1〛}], Opacity[.1],
Polygon[points]},
Epilog -> {Text[#1, Offset[{10, 10}, #2]] & @@@
Transpose[{FromCharacterCode /@
Range[65, 65 + Length[points] - 1], points}],
Thickness[0.005],
Blue, Line /@ intersectionPointsX, Green,
Line /@ intersectionPointsY},
PlotRangePadding -> Scaled[.2],
Frame -> True,
GridLinesStyle -> GrayLevel[.8],
GridLines -> {Table[x, {x, minX, maxX}],
Table[y, {y, minY,maxY}]},
Axes -> False,
PlotLabel -> Column[{
Style["ΔX = "<>ToString@ΔX, Blue],
Style["ΔY = "<>ToString@ΔY,Darker@Green],
"ΔTotal = "<>ToString[totalSegmentsLenth]}]
]
Out:

Another example calculated with the same code:
points = {{1, 2}, {-1, 2}, {-1, -2}, {1, -2}};

One can see that horizontal and vertical edges are not counted as they where inside the polygon. You can include these edges by using For[y = minY, y <= maxY
, ...] instead of For[y = minY + 1, y < maxY, ...]
and the same with x.
Here is an example that produced errors (division by zero, see comments) with the previous version of this code:
points = {{0, 0}, {0, 2}, {-2, 2}, {-4, 4}, {-4, 1}, {-5, -1}, {-3,
0}};

non convex polygons may not work properly:
points = {{0, 0}, {0, 4}, {-2, 2}, {-4, 4}, {-4, 1}, {-4, 0}, {-3, 0}};

You could cut a non convex polygon into pieces of convex polygons.
xy
is not the same asy*x
, which is equivalent toy x
. $\endgroup$