如何获取形状/Body的X、Y、Z坐标?含圆角矩形等距坐标需求
Hey there! Let's tackle your questions one by one—starting with the MATLAB specifics for that rounded rectangle, then moving to alternative methods and multi-language approaches.
1. MATLAB: Get Equally Spaced Coordinates for the Rounded Rectangle (Starting from Bottom Midpoint, Counter-Clockwise)
First, let's break down your shape: the rectangle with position=[0 -1 10 2] and Curvature=[1] is a capsule shape—two semicircles (radius 1) on the left/right, connected by a horizontal rectangle (8 units long, 2 units tall). The bottom midpoint is (5, -1).
Here’s code to generate N equally spaced points (we’ll use 200 as an example):
% Shape parameters x0 = 0; y0 = -1; w = 10; h = 2; r = min(w/2, h/2); % Rounded corner radius (1 in this case) start_point = [x0 + w/2, y0]; % Bottom midpoint (5, -1) N = 200; % Number of coordinates % Calculate segment lengths seg1_len = w/2 - r; % Right along bottom to right semicircle start seg2_len = pi*r; % Right semicircle circumference seg3_len = w - 2*r; % Left along top to left semicircle start seg4_len = pi*r; % Left semicircle circumference seg5_len = w/2 - r; % Right along bottom back to start total_len = seg1_len + seg2_len + seg3_len + seg4_len + seg5_len; step_len = total_len / (N-1); % Equal spacing between points % Initialize coordinate array coords = zeros(N, 2); coords(1,:) = start_point; idx = 2; % Segment 1: Move right to (9, -1) remaining = seg1_len; while remaining > 0 && idx <= N move = min(remaining, step_len); coords(idx,:) = coords(idx-1,:) + [move, 0]; remaining -= move; idx += 1; end % Segment 2: Counter-clockwise around right semicircle (center (9, 0)) center = [x0 + w - r, y0 + r]; current_angle = 3*pi/2; % Start at 270 degrees (bottom of the semicircle) remaining = seg2_len; while remaining > 0 && idx <= N move = min(remaining, step_len); angle_delta = move / r; % Arc length = radius * angle (radians) current_angle -= angle_delta; % Counter-clockwise = decrease angle coords(idx,:) = center + r*[cos(current_angle), sin(current_angle)]; remaining -= move; idx += 1; end % Segment 3: Move left to (1, 1) remaining = seg3_len; while remaining > 0 && idx <= N move = min(remaining, step_len); coords(idx,:) = coords(idx-1,:) + [-move, 0]; remaining -= move; idx += 1; end % Segment 4: Counter-clockwise around left semicircle (center (1, 0)) center = [x0 + r, y0 + h - r]; current_angle = pi/2; % Start at 90 degrees (top of the semicircle) remaining = seg4_len; while remaining > 0 && idx <= N move = min(remaining, step_len); angle_delta = move / r; current_angle += angle_delta; % Counter-clockwise = increase angle coords(idx,:) = center + r*[cos(current_angle), sin(current_angle)]; remaining -= move; idx += 1; end % Segment 5: Move right back to start (5, -1) remaining = seg5_len; while remaining > 0 && idx <= N move = min(remaining, step_len); coords(idx,:) = coords(idx-1,:) + [move, 0]; remaining -= move; idx += 1; end % Ensure the last point matches the start (for closure) coords(end,:) = start_point; % Plot to verify figure plot(coords(:,1), coords(:,2), '-o', 'MarkerSize', 2) axis equal grid minor
2. Generating the Shape Without the rectangle Function
The code above already does this! The core idea is to decompose the shape into basic primitives (line segments and arcs) and calculate points for each primitive individually. This approach is far more flexible than relying on MATLAB's built-in functions, especially if you need to tweak the shape later.
For more complex rounded rectangles (non-100% curvature), you’d just adjust the radius to min(w*curvature(1), h*curvature(2)) and add vertical line segments between the arcs.
3. Getting Shape Coordinates in Other Languages
The general workflow applies across all languages: decompose the shape into primitives, calculate total length, generate equally spaced points for each primitive, then stitch them together. Here’s how to implement this in common languages:
Python
Use numpy for calculations, or shapely for high-level shape handling:
import numpy as np # Parameters x0, y0 = 0, -1 w, h = 10, 2 r = min(w/2, h/2) N = 200 start_point = np.array([x0 + w/2, y0]) total_len = (w-2*r)*2 + 2*np.pi*r step_len = total_len / (N-1) coords = [start_point] idx = 1 # Repeat the segment logic from MATLAB, adapted to Python syntax # (Full code would mirror the MATLAB steps with numpy arrays)
JavaScript
Calculate points manually, then render with Canvas if needed:
const x0 = 0, y0 = -1; const w = 10, h = 2; const r = Math.min(w/2, h/2); const N = 200; const startPoint = [x0 + w/2, y0]; const totalLen = (w-2*r)*2 + 2*Math.PI*r; const stepLen = totalLen / (N-1); const coords = [startPoint]; let idx = 1; // Segment logic adapted to JS (similar to MATLAB/Python)
C++
Use std::vector to store points and standard math functions:
#include <vector> #include <cmath> #include <algorithm> struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; int main() { double x0 = 0, y0 = -1; double w = 10, h = 2; double r = std::min(w/2, h/2); int N = 200; std::vector<Point> coords; coords.emplace_back(x0 + w/2, y0); double totalLen = (w-2*r)*2 + 2*M_PI*r; double stepLen = totalLen / (N-1); int idx = 1; // Segment logic adapted to C++ return 0; }
General Tips for Any Shape
- Decompose first: Break complex shapes into lines, arcs, or Bezier curves—these are easy to generate points for.
- Calculate length: For lines, use Euclidean distance; for arcs, use
radius * angle_in_radians; for Bezier curves, use numerical integration to approximate length. - Interpolate points: For lines, linear interpolation works; for arcs, calculate angle increments; for Bezier curves, use parameterized steps or split into small line segments.
- Adjust direction/start: Rearrange points to match your desired starting point and traversal direction.
内容的提问来源于stack exchange,提问作者Aquarium HowTo

