You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在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:

  1. The z-loop condition uses x < nz instead of z < nz
  2. The sphere center coordinates dx, dy, dz aren't defined (we'll set them to the matrix center for a centered sphere)
  3. You didn't allocate memory for the pos matrix (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=2 means 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 the den value 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: Increasing k will make the new matrix smaller, and the sphere will appear even more reduced. For example, k=3 would produce a 3×3×3 matrix (since 10/3 uses integer division). If your matrix dimensions aren't divisible by k, you can add padding or truncate the edges as needed.
  • Sphere Tightness Threshold: The count > (k*k*k)/2 condition 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

火山引擎 最新活动