how to draw voronoi cells of each vertex bounded inside an area and obtain the values of each of the cell areas independently?

62 views (last 30 days)
how to draw voronoi cells of each vertex bounded inside an area and obtain the values of each of the cell areas independently?
  5 Comments
juan sanchez
juan sanchez 3 minutes ago
Thank you for your answer. Looking for information I was able to find this code VoronoiLimitRectSquare at https://nl.mathworks.com/matlabcentral/fileexchange/106380-voronoi-bounded-rectangular-or-square-limits which allows the voronoi to be drawn as rectangles. However this code only extends the lines similarly to your code to the edges of the bounding box. I was able to do the rectangular plot but the problem is that I can not seem to find a method to calculate the areas of each rectangular cell. Which method would you use to find the area using this code? and what difference do you see between VoronoiLimitRectSquare and your provided code? Thank you for your help.
Umar
Umar about 3 hours ago
Edited: Umar about 3 hours ago

Hi @Juan,

Thanks for your message. One thing to keep in mind is that the VoronoiLimitRectSquare function you found is licensed software created by pPreetham Manjunatha, so if you need functionality that goes beyond what is currently implemented—such as computing the areas of each bounded Voronoi cell—the best approach is to contact the author directly through his GitHub page or MATLAB FileExchange profile.

Regarding your question about area computation:

Preetham’s function does not compute Voronoi regions (closed polygons). It only clips the Voronoi edge segments to a rectangular or square boundary and returns their coordinates as ‘vxClip’ and ‘vyClip’. Because the output consists of edges rather than complete cell polygons, there is no built-in method in that code to calculate the area of each region. To get areas, you would first need to reconstruct each cell’s polygon from the clipped edges, which the function itself does not provide.

As for the difference between his implementation and the other code: both perform boundary clipping of Voronoi edges, but neither produces the full polygonal regions required for area calculation. The main differences are in the internal approach to clipping and intersection handling rather than in capabilities related to region geometry.

If precise per-cell areas are essential for your application, it may help to reach out to Preetham for clarification on whether polygon reconstruction is supported or if it is something he plans to include.

Hope this helps!

Sign in to comment.

Answers (1)

Umar
Umar on 30 Nov 2025 at 7:19

@Juan, I saw your question about drawing bounded Voronoi cells and calculating their areas independently. I've put together a complete MATLAB script that solves exactly this problem without needing any toolboxes.

% Bounded Voronoi Diagram with Cell Area Calculation
% This script creates Voronoi cells bounded within a rectangular area
% and calculates the area of each cell independently
% Define bounding box (matching the figure dimensions)
xmin = 0; xmax = 450;
ymin = 40; ymax = 160;
% Create seed points (vertices) - generic data matching the pattern in figure
vertices = [
  50, 140;   % Top left
  50, 110;   % Middle left
  100, 80;   % Lower region
  150, 140;  % Top middle-left
  200, 100;  % Center
  250, 140;  % Top middle-right
  300, 80;   % Lower middle
  350, 140;  % Top right
  400, 100;  % Right middle
];
% Compute Voronoi diagram
[V, C] = voronoin(vertices);
% Initialize array to store cell areas
numCells = length(C);
cellAreas = zeros(numCells, 1);
% Create figure
figure('Color', 'w');
hold on;
axis([xmin-10 xmax+10 ymin-10 ymax+10]);
grid on;
% Draw bounding box
rectangle('Position', [xmin, ymin, xmax-xmin, ymax-ymin], ...
  'EdgeColor', 'k', 'LineWidth', 2);
% Process each Voronoi cell
for i = 1:numCells
  % Get cell vertices
  cellIndices = C{i};
    % Check if cell is bounded (no infinite vertices)
    if all(cellIndices ~= 1)
        % Get coordinates of cell vertices
        cellVertices = V(cellIndices, :);
        % Clip cell to bounding box
        clippedCell = clipPolygonToBox(cellVertices, xmin, xmax, ymin, ymax);
        if ~isempty(clippedCell) && size(clippedCell, 1) >= 3
            % Calculate area using shoelace formula
            cellAreas(i) = polygonArea(clippedCell);
            % Draw the clipped cell
            patch(clippedCell(:,1), clippedCell(:,2), 'w', ...
                'EdgeColor', 'r', 'LineWidth', 1.5);
        end
    else
        % Handle unbounded cells (cells with infinite vertices)
        clippedCell = clipUnboundedCell(V, cellIndices, vertices(i,:), ...
            xmin, xmax, ymin, ymax);
        if ~isempty(clippedCell) && size(clippedCell, 1) >= 3
            % Calculate area
            cellAreas(i) = polygonArea(clippedCell);
            % Draw the clipped cell
            patch(clippedCell(:,1), clippedCell(:,2), 'w', ...
                'EdgeColor', 'r', 'LineWidth', 1.5);
        end
    end
  end
% Plot seed points
plot(vertices(:,1), vertices(:,2), 'b.', 'MarkerSize', 20);
% Add labels to some cells (like in the figure)
text(50, 140, 'cell', 'HorizontalAlignment', 'center', 'FontSize', 10, 'FontWeight', 
'bold');
text(50, 110, 'cell', 'HorizontalAlignment', 'center', 'FontSize', 10, 'FontWeight', 
'bold');
xlabel('X');
ylabel('Y');
title('Bounded Voronoi Diagram with Cell Areas');
% Display results
fprintf('\n=== Voronoi Cell Areas ===\n');
for i = 1:numCells
  fprintf('Cell %d: Area = %.2f\n', i, cellAreas(i));
end
fprintf('Total Area: %.2f\n', sum(cellAreas));
fprintf('Bounding Box Area: %.2f\n', (xmax-xmin)*(ymax-ymin));
hold off;
%% Helper Functions
function area = polygonArea(vertices)
  % Calculate area of polygon using shoelace formula
  % vertices: Nx2 matrix of [x, y] coordinates
    x = vertices(:, 1);
    y = vertices(:, 2);
    % Shoelace formula
    area = 0.5 * abs(sum(x .* circshift(y, -1) - y .* circshift(x, -1)));
  end
function clipped = clipPolygonToBox(polygon, xmin, xmax, ymin, ymax)
  % Clip polygon to rectangular bounding box using Sutherland-Hodgman 
algorithm
    % Define clipping boundaries in order: left, right, bottom, top
    boundaries = [xmin, xmax, ymin, ymax];
    directions = [1, -1, 2, -2]; % 1=right of xmin, -1=left of xmax, 2=above ymin, 
    -2=below ymax
    clipped = polygon;
    % Clip against each boundary
    for b = 1:4
        if isempty(clipped)
            break;
        end
        boundary = boundaries(b);
        direction = directions(b);
        clipped = clipPolygonByLine(clipped, boundary, direction);
    end
  end
function output = clipPolygonByLine(polygon, boundary, direction)
  % Clip polygon by a single line (one edge of bounding box)
  % direction: 1=x>=boundary, -1=x<=boundary, 2=y>=boundary, 
  -2=y<=boundary
    if isempty(polygon)
        output = [];
        return;
    end
    n = size(polygon, 1);
    output = [];
    for i = 1:n
        current = polygon(i, :);
        next = polygon(mod(i, n) + 1, :);
        currentInside = isInside(current, boundary, direction);
        nextInside = isInside(next, boundary, direction);
        if currentInside
            output = [output; current];
            if ~nextInside
                % Crossing from inside to outside - add intersection
                intersect = findIntersection(current, next, boundary, direction);
                output = [output; intersect];
            end
        elseif nextInside
            % Crossing from outside to inside - add intersection
            intersect = findIntersection(current, next, boundary, direction);
            output = [output; intersect];
        end
    end
  end
function inside = isInside(point, boundary, direction)
  % Check if point is inside boundary
  if abs(direction) == 1
      % X boundary
      if direction == 1
          inside = point(1) >= boundary;
      else
          inside = point(1) <= boundary;
      end
  else
      % Y boundary
      if direction == 2
          inside = point(2) >= boundary;
      else
          inside = point(2) <= boundary;
      end
  end
end
function intersect = findIntersection(p1, p2, boundary, direction)
  % Find intersection of line segment p1-p2 with boundary
    if abs(direction) == 1
        % Vertical boundary (constant x)
        t = (boundary - p1(1)) / (p2(1) - p1(1));
        intersect = [boundary, p1(2) + t * (p2(2) - p1(2))];
    else
        % Horizontal boundary (constant y)
        t = (boundary - p1(2)) / (p2(2) - p1(2));
        intersect = [p1(1) + t * (p2(1) - p1(1)), boundary];
    end
  end
function clipped = clipUnboundedCell(V, cellIndices, seedPoint, xmin, xmax, 
ymin, ymax)
  % Clip unbounded Voronoi cell to bounding box
    % Separate finite and infinite vertices
    finiteIdx = cellIndices(cellIndices ~= 1);
    if isempty(finiteIdx)
        clipped = [];
        return;
    end
    finiteVertices = V(finiteIdx, :);
    % For unbounded cells, we need to extend rays to box boundaries
    % This is a simplified approach: create a large polygon and clip it
    % Find the directions of infinite edges
    numVertices = length(cellIndices);
    extendedPoly = [];
    for i = 1:numVertices
        idx = cellIndices(i);
        nextIdx = cellIndices(mod(i, numVertices) + 1);
        if idx == 1
            % Current vertex is at infinity
            if nextIdx ~= 1
                % Next vertex is finite - extend ray backward
                nextVert = V(nextIdx, :);
                direction = nextVert - seedPoint;
                direction = direction / norm(direction);
                % Extend far beyond box
                rayStart = seedPoint - 1000 * direction;
                extendedPoly = [extendedPoly; rayStart];
            end
        elseif nextIdx == 1
            % Next vertex is at infinity - extend ray forward
            currentVert = V(idx, :);
            extendedPoly = [extendedPoly; currentVert];
            direction = currentVert - seedPoint;
            direction = direction / norm(direction);
            % Extend far beyond box
            rayEnd = seedPoint + 1000 * direction;
            extendedPoly = [extendedPoly; rayEnd];
        else
            % Both vertices are finite
            extendedPoly = [extendedPoly; V(idx, :)];
        end
    end
    if isempty(extendedPoly)
        clipped = [];
        return;
    end
    % Clip the extended polygon to bounding box
    clipped = clipPolygonToBox(extendedPoly, xmin, xmax, ymin, ymax);
  end

The main challenge you're facing is that MATLAB's voronoin function returns infinite vertices for edge cells, making area calculations impossible without proper clipping. The script I created uses the Sutherland-Hodgman polygon clipping algorithm to clip each Voronoi cell to your rectangular boundary, then calculates the area using the shoelace formula. It handles both bounded cells in the interior and unbounded cells at the edges by extending rays to the boundary and clipping them properly. The code generates seed points similar to your diagram, creates the Voronoi diagram, clips every cell to your bounding box (which looks like 0-450 on x-axis and 40-160 on y-axis from your image), and stores each cell's area in an array so you get independent area values for each vertex. When you run it, you'll see a visualization matching your figure style with red cell boundaries and a black bounding box, plus it prints out all the individual cell areas in the command window along with the total area to verify everything adds up correctly. The script is completely self-contained with all helper functions included, so you just save it as a .m file and run it directly. This approach gives you full control over the clipping process and works reliably for any rectangular boundary you specify.

Hope this helps!

  3 Comments
Umar
Umar on 1 Dec 2025 at 18:08

Hi @Juan,Thakyou for your kind words, much appreciated. I do understand but the code that I provided you can be modified by you based on your recent attachment. I will encourage you to put some effort into it and pretty confident that you will be able to solve it.

juan sanchez
juan sanchez on 1 Dec 2025 at 18:59
Thank you. I am working on it and trying to put your code in a loop as I wish to plot 3 bounding boxes in the same axes.

Sign in to comment.

Categories

Find more on Voronoi Diagram in Help Center and File Exchange

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!