如何在C语言中通过矩阵约简实现球体体积缩减(非直接改半径)
通过矩阵约简(降采样)缩减三维球体矩阵体积的实现方案
Hey there! Let's tackle your problem step by step. First, I noticed a couple of tiny bugs in your original sphere-generating code (easy fixes!) before we dive into matrix reduction for shrinking the sphere's volume without touching the radius variable.
先修正原代码的小问题
Your original code has two easy-to-miss issues:
- The z-loop condition uses
x < nzinstead ofz < nz - The sphere center coordinates
dx,dy,dzaren't defined (we'll set them to the matrix center for a centered sphere) - You didn't allocate memory for the
posmatrix (critical to avoid crashes!)
核心思路:用降采样实现矩阵约简
Instead of modifying the radius, we can downsample the 3D matrix—essentially merging groups of adjacent voxels into a single voxel in a smaller matrix. This reduces the overall matrix size, and since we only keep voxels that represent the original sphere's core, the effective "volume" of the sphere in the new matrix will shrink naturally.
Here's how it works:
- Pick a reduction factor
k: This determines how many original voxels are merged into one. For example,k=2means every 2×2×2 block of original voxels becomes 1 voxel in the new matrix. - For each block in the original matrix, count how many voxels are set to your sphere value
den. If enough voxels in the block belong to the sphere, we keep thedenvalue in the new matrix; otherwise, we set it to 0. This preserves the sphere's shape while shrinking its footprint.
完整实现代码
#include <stdio.h> #include <stdlib.h> int main() { // Original matrix parameters int nx = 10; int ny = 10; int nz = 10; double radius = 4; double den = 3; double dx = nx / 2.0; // Sphere center (x-axis) double dy = ny / 2.0; // Sphere center (y-axis) double dz = nz / 2.0; // Sphere center (z-axis) // Step 1: Allocate and populate original 3D matrix with sphere double ***pos = (double ***)malloc(nx * sizeof(double **)); for (int x = 0; x < nx; x++) { pos[x] = (double **)malloc(ny * sizeof(double *)); for (int y = 0; y < ny; y++) { pos[x][y] = (double *)malloc(nz * sizeof(double)); for (int z = 0; z < nz; z++) { // Fixed loop condition here! double dis = (dx - x)*(dx - x) + (dy - y)*(dy - y) + (dz - z)*(dz - z); if (radius*radius > dis) { pos[x][y][z] = den; } else { pos[x][y][z] = 0; } } } } // Step 2: Matrix reduction (downsampling) to shrink sphere volume int k = 2; // Reduction factor: merge k×k×k voxels into 1 int new_nx = nx / k; int new_ny = ny / k; int new_nz = nz / k; // Allocate new reduced matrix double ***reduced_pos = (double ***)malloc(new_nx * sizeof(double **)); for (int x = 0; x < new_nx; x++) { reduced_pos[x] = (double **)malloc(new_ny * sizeof(double *)); for (int y = 0; y < new_ny; y++) { reduced_pos[x][y] = (double *)malloc(new_nz * sizeof(double)); for (int z = 0; z < new_nz; z++) { // Count how many voxels in the k×k×k block are part of the sphere int count = 0; for (int bx = x*k; bx < x*k + k; bx++) { for (int by = y*k; by < y*k + k; by++) { for (int bz = z*k; bz < z*k + k; bz++) { if (pos[bx][by][bz] == den) { count++; } } } } // If more than half the block is sphere, keep den; else 0 // Adjust this threshold to control how "tight" the reduced sphere is if (count > (k*k*k)/2) { reduced_pos[x][y][z] = den; } else { reduced_pos[x][y][z] = 0; } } } } // Optional: Print size info to verify printf("Original matrix size: %dx%dx%d\n", nx, ny, nz); printf("Reduced matrix size: %dx%dx%d\n", new_nx, new_ny, new_nz); // Step 3: Free allocated memory (critical to avoid leaks!) for (int x = 0; x < nx; x++) { for (int y = 0; y < ny; y++) { free(pos[x][y]); } free(pos[x]); } free(pos); for (int x = 0; x < new_nx; x++) { for (int y = 0; y < new_ny; y++) { free(reduced_pos[x][y]); } free(reduced_pos[x]); } free(reduced_pos); return 0; }
关键细节调整
- Reduction Factor
k: Increasingkwill make the new matrix smaller, and the sphere will appear even more reduced. For example,k=3would produce a 3×3×3 matrix (since 10/3 uses integer division). If your matrix dimensions aren't divisible byk, you can add padding or truncate the edges as needed. - Sphere Tightness Threshold: The
count > (k*k*k)/2condition keeps a voxel only if more than half the original block was part of the sphere. Raise this threshold (e.g.,count > k*k*k*0.75) to get a smaller, tighter sphere; lower it to preserve more of the original shape. - Memory Management: Always free allocated memory in C to avoid memory leaks, especially for large 3D matrices.
内容的提问来源于stack exchange,提问作者GuGim




