2017-07-01 20 views
13

में आयताकार, मंडल या मनमाने ढंग से बहुभुज बनाएं, मैं दो आयामों में वस्तुओं के चारों ओर प्रवाह अनुकरण करना चाहता हूं। इसलिए मैंने सी में एक कार्यक्रम लिखा जो तरल पदार्थ की गति का वर्णन करने के लिए नेवियर-स्टोक्स समीकरणों का उपयोग करता है। अब मैं उस बिंदु पर आया जहां मैं वास्तव में सिमुलेशन डोमेन में एक आयताकार रखने से ज्यादा चाहता हूं। मैं एक अच्छा आयत मिलएम एक्स एन मैट्रिक्स

for(int i=start_x; i<end_x; i++) 
    for(int j=start_y; j<end_y; j++) 
     M[i][j] = 1; // barrier cell = 1 

ऐसा करने से: इस तरह के एक आयत बनाने के लिए मैं बस की तरह कुछ है। कोई आश्चर्य नहीं। लेकिन अगर मैं एक सर्कल, एक क्रॉस, त्रिकोण, विंग प्रोफाइल या किसी अन्य मनमानी बहुभुज के प्रवाह को अनुकरण करना चाहता हूं तो एक दृष्टिकोण क्या होगा? m x n आकार के मैट्रिक्स M में ऐसी 2 डी ऑब्जेक्ट्स को आकर्षित करने का कोई आसान तरीका है?


मुझे बस लगभग किसी भी आकार को आकर्षित करने का एक आसान तरीका मिला। @ नाममात्र पशु के जवाब ने मुझे इस समाधान को खोजने के लिए प्रेरित किया। मैं बस .png फ़ाइल का उपयोग करता हूं और (लिनक्स का उपयोग कर) का उपयोग कर इसे .pgm फ़ाइल में परिवर्तित करता हूं। मेरे कोड में मुझे केवल कुछ और लाइनों की आवश्यकता है:

FILE *pgmFile; 
pgmFile = fopen("picture.pgm", "r"); 
for(int i=0; i<1024; i++){ 
    for(int j=0; j<1024; j++){ 
     int d = fgetc(pgmFile); 
     if(d < 255){ 
      M[i][j] = 1; // barrier cell = 1 
     } 
    } 
} 
fclose(pgmFile); 

यहां मैं 1024 x 1024 पिक्सेल की एक तस्वीर का उपयोग करता हूं। enter image description here

: यदि पिक्सेल का मूल्य 255 (नहीं सफेद) की तुलना में मैं 1. यहाँ के M[i][j] के पिक्सेल सेट से छोटी है एक परिणाम मैं स्टैक ओवरफ़्लो लोगो के साथ बनाया (प्रवाह बाएं से आ रही है) है वेग प्लॉट, रे = 20000 (रेनॉल्ड्स संख्या)

+1

वाह यह वास्तव में बहुत अच्छी – frozen

+0

आंतरिक अंक के लिए एक चक्र कार्य करने के लिए लग रहा है अमूर्त आकृतियों के लिए अपने मौजूदा तकनीक का विस्तार एक समारोह, जो यह सत्यापित बनाने यदि पिक्सेल आकार के भीतरी इलाकों में है की आवश्यकता होती है और 1. उदाहरण के लिए करने के लिए यह सेट हो जाएगा, अगर 1 (x-x0)^2 + (y-y0)^2 <त्रिज्या वापस आ जाएगा। इस तरह के एक समारोह के अंदर आप फ़ाइलों से पढ़ने सहित विभिन्न प्रकार की तकनीकों का उपयोग कर सकते हैं। – RIBH

उत्तर

3

हाथ में समस्या rasterisation (विकिपीडिया) करने के लिए नीचे फोड़े, और विशेष रूप से scan line conversion (siggraph.org) पर।

siggraph.org लेख कैसे straight lines, circles and ellipses, और convex और concave बहुभुज आकर्षित करने के लिए पर विस्तृत व्याख्या में शामिल है।

हालांकि, यह एक समस्या है जिसे पहले से ही बड़ी संख्या में हल किया जा चुका है।जबकि ओपी निश्चित रूप से आवश्यक प्राइमेटिव (लाइन, इलिप्स, त्रिकोण, बहुभुज) को लागू कर सकता है, वहां एक बहुत ही सरल दृष्टिकोण है।

मेरा सुझाव है कि ओ पी पी 5 के लिए एक सरल NetPBM format पाठक (बाइनरी ग्रेस्केल पिक्समैप) प्रारूप, और netpbm tools (लिनक्स वितरण और BSD वेरिएंट में netpbm से पैकेज; अन्य प्रणालियों के लिए Netpbm home page देखें) लागू करता है एक आसान करने के लिए किसी भी छवि परिवर्तित करने के लिए पीजीएम (पी 5) फ़ाइल को पढ़ने के लिए, जहां प्रत्येक पिक्सेल ओपी के मैट्रिक्स में एक तत्व से मेल खाता है।

इस तरह, कोई भी उदाहरण का उपयोग कर सकता है वेक्टर ग्राफिक्स का उपयोग करके सिस्टम को आकर्षित करने के लिए इंकस्केप, इसे किसी भी आकार (जैसे पीएनजी छवि के रूप में निर्यात करके) पर रास्टराइज करें, नेटपीबीएम टूल्स (pngtopnm या anytopnm का उपयोग करके पीजीएम (पी 5) प्रारूप में कनवर्ट करें, उसके बाद ppmtopgm), और फ़ाइल पढ़ें। दरअसल, POSIX.1 सिस्टम में (विंडोज़ को छोड़कर बस हर जगह), पीजीएम (पी 5) प्रारूप में किसी भी पिक्समैप छवि को पढ़ने के लिए popen("anytopnm path-to-file | pnmtopng", "r") (या थोड़ा अधिक जटिल दो -fork() पाइप समाधान) का उपयोग कर सकते हैं।

वैकल्पिक रूप से, कोई उदाहरण का उपयोग करने पर विचार कर सकता है ImageMagick लाइब्रेरी को किसी भी प्रारूप पिक्समैप छवियों (जेपीईजी, जीआईएफ, पीएनजी इत्यादि) के बारे में पढ़ने के लिए।


व्यक्तिगत रूप से, दोनों एक डेवलपर और उपयोगकर्ता (हालांकि ध्यान दें कि मैं स्पष्ट रूप से एक गैर Windows उपयोगकर्ता हूँ, एक दशक से अधिक में Microsoft उत्पादों का उपयोग नहीं किया) के रूप में, मैं netpbm दृष्टिकोण पसंद करेंगे। कार्यक्रम, mysim कहें, उदाहरण के लिए उपयोग करेंगे /usr/lib/mysim/read-image शैल स्क्रिप्ट (या विंडोज़ में प्रोग्राम, शायद मैक; या, यदि परिभाषित किया गया है, तो MYSIM_READ_IMAGE पर्यावरण चर द्वारा परिभाषित स्क्रिप्ट या प्रोग्राम), कमांड लाइन पर निर्दिष्ट छवि को पढ़ने के लिए, इसे पीजीएम (पी 5) प्रारूप में उत्सर्जित करने के लिए। मुख्य कार्यक्रम केवल सहायक के आउटपुट को पढ़ेगा।

इस तरह, यदि किसी उपयोगकर्ता को इनपुट फ़ाइलों के लिए विशेष हैंडलिंग की आवश्यकता होती है, तो वे मौजूदा स्क्रिप्ट की प्रतिलिपि बना सकते हैं, अपनी आवश्यकताओं के अनुसार इसे संशोधित कर सकते हैं, और कहीं भी अपनी होम निर्देशिका (या वैश्विक रूप से, या यहां तक ​​कि मौजूदा को भी बदल सकते हैं) एक, अगर यह सभी उपयोगकर्ताओं द्वारा वैसे भी उपयोग किया जाता है)।

कार्यक्रम या तो popen() या fork() + execv() एक कमांड लाइन पैरामीटर के रूप में इनपुट फ़ाइल नाम के साथ, स्क्रिप्ट को निष्पादित करने के लिए उपयोग, और प्रारंभिक मैट्रिक्स के निर्माण के लिए माता-पिता की प्रक्रिया में उत्पादन पढ़ सकते हैं।

मैं कई कारणों से छवि लाइब्रेरी दृष्टिकोण पर इस दृष्टिकोण को प्राथमिकता देता हूं। सबसे पहले, यह अधिक मॉड्यूलर है, जिससे उपयोगकर्ता छवि पढ़ने की प्रक्रिया को ओवरराइड कर सकता है और यदि आवश्यक हो तो उसे कुशल बना सकता है। (मेरे अनुभव में, इस तरह के ओवरराइड की अक्सर आवश्यकता नहीं होती है, लेकिन जब वे होते हैं, तो वे बेहद उपयोगी होते हैं, और निश्चित रूप से इसके लायक होते हैं।) दूसरा, छवि प्रसंस्करण (जो कई मामलों में काफी जटिल है) एक अलग प्रक्रिया में किया जाता है , जिसका मतलब है कि छवि को पूरी तरह से पढ़ा जाने पर छवि को पढ़ने और समझने के लिए आवश्यक सभी स्मृति (कोड और डेटा के लिए) जारी की जाती है। तीसरा, यह दृष्टिकोण Unix philosophy और KISS principle का पालन करता है, जिसमें मजबूत और उपयोगी टूल के विकास के मार्गदर्शन का एक सिद्ध ट्रैक रिकॉर्ड है।


यहाँ एक उदाहरण कार्यक्रम है कि एक द्विआधारी PBM, PGM, या पीपीएम फ़ाइल (netpbm पी 4, पी 5, और पी 6 प्रारूपों, क्रमशः) मानक इनपुट से पढ़ता है, एक मैट्रिक्स संरचना में, 0 साथ मैट्रिक्स भरने है या 1 (छवि से पढ़ने वाले रंग या ग्रेस्केल मानों के आधार पर)। परीक्षण की आसानी के लिए, कार्यक्रम पीजीएम (पी 5) प्रारूप में मानक आउटपुट के लिए मैट्रिक्स आउटपुट करता है।

कार्यक्रम नेटपीबीएम मैनुअल पृष्ठों (PBM (P4), PGM (P5), और PPM (P6) प्रारूपों के क्रमशः क्रमशः प्रारूप विनिर्देश का पालन करता है)।NetPBM formats पर विकिपीडिया लेख वर्तमान में अमान्य टिप्पणियों (शीर्षलेख और डेटा के बीच) के उदाहरण दिखाता है। नेटपीबीएम मैनुअल पेज बताते हैं कि अंतिम हेडर वैल्यू एक सिंगल व्हाइटस्पेस कैरेक्टर के बाद होता है, और कोई टिप्पणी नहीं है। (यदि कोई टिप्पणी अंतिम शीर्षलेख मान का पालन कर सकती है, तो यह जानना असंभव है कि बाइनरी डेटा में # (बाइनरी 0x23 = 35) कोई टिप्पणी शुरू करता है या वास्तविक डेटा मान है।)

यह स्पष्ट रूप से है सार्वजनिक डोमेन, या समकक्ष, Creative Commons CC0 लाइसेंस के तहत लाइसेंस प्राप्त है। इसका मतलब यह है कि आप वाणिज्यिक परियोजनाओं में भी किसी भी तरह और कहीं भी नीचे दिए गए कोड का उपयोग करने के लिए पूरी तरह से स्वतंत्र हैं, लेकिन इसकी कोई गारंटी नहीं है: यदि यह टूट जाता है, या कुछ तोड़ता है, या आपके बालों को आग लगा देता है, तो आप सभी को रखना टुकड़े और केवल खुद को दोषी ठहराते हैं।

उसने कहा, यह केवल हल्के ढंग से परीक्षण किया गया है, इसलिए यदि आपको इसमें कोई बग मिलती है, तो मुझे टिप्पणियों में बताएं ताकि मैं सत्यापित और ठीक कर सकूं।

#include <stdlib.h> 
#include <string.h> 
#include <stdio.h> 
#include <errno.h> 

/* Matrix to read data into */ 
typedef struct { 
    int   rows; 
    int   cols; 
    long   rowstride; 
    long   colstride; 
    unsigned char *data;  /* data[row*rowstride + col*colstride] */ 
} matrix; 
#define MATRIX_INIT { 0, 0, 0, 0, NULL } 

/* NetPBM (binary) formats supported */ 
#define PNM_PBM 4 
#define PNM_PGM 5 
#define PNM_PPM 6 

/* Error codes from pnm_*() functions */ 
#define PNM_EOF  -1 
#define PNM_INVALID -2 
#define PNM_OVERFLOW -3 


/* This helper function returns the NetPBM file identifier; 
    PNM_PBM, PNM_PGM, PNM_PPM, or PNM_INVALID if unsupported. 
*/ 
static int pnm_type(FILE *in) 
{ 
    /* First character must be 'P'. */ 
    if (getc(in) != 'P') 
     return PNM_INVALID; 

    /* Second character determines the type. */ 
    switch (getc(in)) { 
    case '4': return PNM_PBM; 
    case '5': return PNM_PGM; 
    case '6': return PNM_PPM; 
    default: return PNM_INVALID; 
    } 
} 

/* This helper function reads a number from a NetPBM header, 
    correctly handling comments. Since all numbers in NetPBM 
    headers are nonnegative, this function returns negative 
    when an error occurs: 
    -1: Premature end of input 
    -2: Value is too large (int overflow) 
    -3: Invalid input (not a NetPBM format file) 
*/ 
static int pnm_value(FILE *in) 
{ 
    int c; 

    /* Skip leading whitespace and comments. */ 
    c = getc(in); 
    while (c == '\t' || c == '\n' || c == '\v' || 
      c == '\f' || c == '\r' || c == ' ' || c == '#') 
     if (c == '#') { 
      while (c != EOF && c != '\n') 
       c = getc(in); 
     } else 
      c = getc(in); 

    if (c == EOF) 
     return PNM_EOF; 

    if (c >= '0' && c <= '9') { 
     int value = 0; 

     while (c >= '0' && c <= '9') { 
      const int oldvalue = value; 
      value = 10*value + (c - '0'); 
      if ((int)(value/10) != oldvalue) 
       return PNM_OVERFLOW; 
      c = getc(in); 
     } 

     /* Do not consume the separator. */ 
     if (c != EOF) 
      ungetc(c, in); 

     /* Success. */ 
     return value; 
    } 

    return PNM_INVALID; 
} 

/* This helper function consumes the single newline 
    following the final value in the header. 
    Returns 0 if success, PNM_INVALID otherwise. 
*/ 
static int pnm_newline(FILE *in) 
{ 
    int c; 

    c = getc(in); 
    if (c == '\r') 
     c = getc(in); 
    if (c == '\n') 
     return 0; 

    return PNM_INVALID; 
} 

static void pnm_matrix_free(matrix *to) 
{ 
    if (to) { 
     free(to->data); 
     to->rows = 0; 
     to->cols = 0; 
     to->rowstride = 0; 
     to->colstride = 0; 
     to->data = NULL; 
    } 
} 

static int pnm_matrix_init(matrix *to, int rows, int cols) 
{ 
    size_t cells, bytes; 

    if (rows < 1 || cols < 1) 
     return PNM_INVALID; 

    cells = (size_t)rows * (size_t)cols; 
    if ((size_t)(cells/(size_t)rows) != (size_t)cols || 
     (size_t)(cells/(size_t)cols) != (size_t)rows) 
     return PNM_OVERFLOW; 

    bytes = cells * sizeof to->data[0]; 
    if ((size_t)(bytes/sizeof to->data[0]) != cells) 
     return PNM_OVERFLOW; 

    to->data = malloc(bytes); 
    if (!to->data) 
     return PNM_OVERFLOW; 

    to->rows = rows; 
    to->cols = cols; 

    /* Default to a row-major data order. */ 
    to->colstride = 1L; 
    to->rowstride = cols; 

    return 0; 
} 

static int pnm_p4_matrix(FILE *in, matrix *to) 
{ 
    int rows, cols, result, r, c, byte = 0; 

    cols = pnm_value(in); 
    if (cols < 1) 
     return PNM_INVALID; 

    rows = pnm_value(in); 
    if (rows < 1) 
     return PNM_INVALID; 

    if (pnm_newline(in)) 
     return PNM_INVALID; 

    result = pnm_matrix_init(to, rows, cols); 
    if (result) 
     return result; 

    for (r = 0; r < rows; r++) { 
     const long ri = r * to->rowstride; 
     for (c = 0; c < cols; c++) { 
      const long i = ri + c * to->colstride; 

      switch (c & 7) { 
      case 0: 
       byte = getc(in); 
       if (byte == EOF) { 
        pnm_matrix_free(to); 
        return PNM_INVALID; 
       } 
       to->data[i] = !!(byte & 128); 
       break; 
      case 1: 
       to->data[i] = !!(byte & 64); 
       break; 
      case 2: 
       to->data[i] = !!(byte & 32); 
       break; 
      case 3: 
       to->data[i] = !!(byte & 16); 
       break; 
      case 4: 
       to->data[i] = !!(byte & 8); 
       break; 
      case 5: 
       to->data[i] = !!(byte & 4); 
       break; 
      case 6: 
       to->data[i] = !!(byte & 2); 
       break; 
      case 7: 
       to->data[i] = !!(byte & 1); 
       break; 
      } 
     } 
    } 

    return 0; 
} 

static int pnm_p5_matrix(FILE *in, matrix *to) 
{ 
    int rows, cols, max, r, c, result; 

    cols = pnm_value(in); 
    if (cols < 1) 
     return PNM_INVALID; 

    rows = pnm_value(in); 
    if (rows < 1) 
     return PNM_INVALID; 

    max = pnm_value(in); 
    if (max < 1 || max > 65535) 
     return PNM_INVALID; 

    if (pnm_newline(in)) 
     return PNM_INVALID; 

    result = pnm_matrix_init(to, rows, cols); 
    if (result) 
     return result; 

    if (max < 256) { 
     const int limit = (max + 1)/2; 
     int val; 
     for (r = 0; r < rows; r++) { 
      const long ri = r * to->rowstride; 
      for (c = 0; c < cols; c++) { 
       const long i = ri + c * to->colstride; 

       val = getc(in); 
       if (val == EOF) { 
        pnm_matrix_free(to); 
        return PNM_INVALID; 
       } 

       to->data[i] = (val < limit); 
      } 
     } 
    } else { 
     const int limit = (max + 1)/2; 
     int val, low; 
     for (r = 0; r < rows; r++) { 
      const long ri = r * to->rowstride; 
      for (c = 0; c < cols; c++) { 
       const long i = ri + c * to->colstride; 

       val = getc(in); 
       low = getc(in); 
       if (val == EOF || low == EOF) { 
        pnm_matrix_free(to); 
        return PNM_INVALID; 
       } 
       val = 256*val + low; 

       to->data[i] = (val < limit); 
      } 
     } 
    } 

    return 0; 
} 

static int pnm_p6_matrix(FILE *in, matrix *to) 
{ 
    int rows, cols, max, r, c, result; 

    cols = pnm_value(in); 
    if (cols < 1) 
     return PNM_INVALID; 

    rows = pnm_value(in); 
    if (rows < 1) 
     return PNM_INVALID; 

    max = pnm_value(in); 
    if (max < 1 || max > 65535) 
     return PNM_INVALID; 

    if (pnm_newline(in)) 
     return PNM_INVALID; 

    result = pnm_matrix_init(to, rows, cols); 
    if (result) 
     return result; 

    if (max < 256) { 
     const int limit = 128 * max; 
     int  val, rval, gval, bval; 

     for (r = 0; r < rows; r++) { 
      const long ri = r * to->rowstride; 
      for (c = 0; c < cols; c++) { 
       const long i = ri + c * to->colstride; 

       rval = getc(in); 
       gval = getc(in); 
       bval = getc(in); 
       if (rval == EOF || gval == EOF || bval == EOF) { 
        pnm_matrix_free(to); 
        return PNM_INVALID; 
       } 

       val = 54 * rval 
        + 183 * gval 
        + 19 * bval; 

       to->data[i] = (val < limit); 
      } 
     } 
    } else { 
     const int limit = 128 * max; 
     int  val, rhi, rlo, ghi, glo, bhi, blo; 

     for (r = 0; r < rows; r++) { 
      const long ri = r * to->rowstride; 
      for (c = 0; c < cols; c++) { 
       const long i = ri + c * to->colstride; 

       rhi = getc(in); 
       rlo = getc(in); 
       ghi = getc(in); 
       glo = getc(in); 
       bhi = getc(in); 
       blo = getc(in); 
       if (rhi == EOF || rlo == EOF || 
        ghi == EOF || glo == EOF || 
        bhi == EOF || blo == EOF) { 
        pnm_matrix_free(to); 
        return PNM_INVALID; 
       } 

       val = 54 * (rhi*256 + rlo) 
        + 183 * (ghi*256 + glo) 
        + 19 * (bhi*256 + blo); 

       to->data[i] = (val < limit); 
      } 
     } 
    } 

    return 0; 
} 

int pnm_matrix(FILE *in, matrix *to) 
{ 
    /* If the matrix is specified, initialize it. */ 
    if (to) { 
     to->rows = 0L; 
     to->cols = 0L; 
     to->rowstride = 0L; 
     to->colstride = 0L; 
     to->data = NULL; 
    } 

    /* Sanity checks on parameters. */ 
    if (!to || !in || ferror(in)) 
     return PNM_INVALID; 

    switch (pnm_type(in)) { 
    case PNM_PBM: return pnm_p4_matrix(in, to); 
    case PNM_PGM: return pnm_p5_matrix(in, to); 
    case PNM_PPM: return pnm_p6_matrix(in, to); 
    default:  return PNM_INVALID; 
    } 
} 

int main(void) 
{ 
    int r, c; 
    matrix m = MATRIX_INIT; 

    if (pnm_matrix(stdin, &m)) { 
     fprintf(stderr, "Cannot parse standard input.\n"); 
     return EXIT_FAILURE; 
    } 

    fprintf(stderr, "Read %d rows, %d columns, from standard input.\n", m.rows, m.cols); 

    /* For ease of debugging, we output the matrix as a PGM file. */ 
    printf("P5\n%d %d\n255\n", m.cols, m.rows); 
    for (r = 0; r < m.rows; r++) 
     for (c = 0; c < m.cols; c++) 
      if (m.data[r * m.rowstride + c * m.colstride] == 0) 
       putchar(255); /* White */ 
      else 
       putchar(0); /* Black */ 

    return EXIT_SUCCESS; 
} 

ध्यान दें कि मैं बिट/ग्रेस्केल/रंग रूपांतरण कैसे ओपी मैट्रिक्स का उपयोग करने का इरादा रखता है के संबंध में सही तरीका है कि क्या सत्यापित नहीं किया। (यानी, क्या "सफेद" या हल्के रंगों को मैट्रिक्स में 0 या 1 उत्पन्न करना चाहिए।) यदि आपको इसे पीबीएम छवियों के लिए उलटा करने की आवश्यकता है, तो इसके बजाय !(byte & NUMBER) का उपयोग करें। यदि आपको इसे पीजीएम या पीपीएम छवियों के लिए उलटा करने की आवश्यकता है, तो इसके बजाय (val >= limit) का उपयोग करें।

कार्यक्रम वैध सी (यहां तक ​​कि C89 तक) होना चाहिए, और किसी भी आर्किटेक्चर पर संकलित होना चाहिए। विंडोज़ जैसे मूर्ख वास्तुकलाओं पर, आपको "बाइनरी मोड" में मानक इनपुट को खोलना/दोबारा खोलना पड़ सकता है (fopen() झंडे में शामिल करें), क्योंकि वे अन्यथा इनपुट को उलझ सकते हैं।

लिनक्स पर, मैं संकलित और

gcc -Wall -O2 example.c -o example 
./example <inputfile.pbm> result-pbm.pgm 
./example <inputfile.pgm> result-pgm.pgm 
./example <inputfile.ppm> result-ppm.pgm 
+0

कोई प्रोग्राम कैसा दिखता है जो किसी छवि को पढ़ सकता है और इसे किसी दिए गए पिक्सेल के मान के आधार पर शून्य और किसी के साथ मैट्रिक्स 'एम' में परिवर्तित कर सकता है? – Samuel

+0

@ सैमुएल: मैंने यह दिखाने के लिए एक उदाहरण कोड जोड़ा कि यह कैसे करें। यह बिटमैप, ग्रेस्केल और आरजीबी प्रारूप बाइनरी नेटपीबीएम फाइलों (पीबीएम, पीजीएम, और पीपीएम) का समर्थन करता है। –

7

ऐसा करने के अधिक कुशल तरीके हो सकते हैं, लेकिन यहां एक तरीका है।

उस बहुभुज के समीकरण का उपयोग करके सी में एक फ़ंक्शन को परिभाषित करें जिसे आप आकर्षित करना चाहते हैं। फ़ंक्शन को परिभाषित किया गया है कि यह एक बिंदु निर्देशांक स्वीकार करता है, और यह दर्शाता है कि बिंदु पॉलीगॉन के अंदर है या नहीं। उदाहरण के लिए, एक सर्कल के लिए, फ़ंक्शन (x,y), केंद्र (x0,y0), और त्रिज्या r को स्वीकार कर सकता है, और (x-x0)^2 + (y-y0)^2 - r^2 < 0 लौटा सकता है। इस समारोह को f होने दें।

बहुभुज के बाध्यकारी बॉक्स आयताकार को निर्धारित करें, यदि संभव हो, या फिर, सबसे छोटा आयताकार आप निर्धारित कर सकते हैं कि बहुभुज को पूरी तरह से कौन सा संलग्न करता है। यह आपको एक आयताकार मैट्रिक्स देगा।

अब, आयताकार मैट्रिक्स में बिंदुओं पर पुनरावृत्त करें। प्रत्येक बिंदु के लिए, उस फ़ंक्शन को कॉल करें जिसे आपने पहले परिभाषित किया था। समन्वय को 1 असाइन करें यदि यह सही हो, और 0 यदि यह गलत हो जाता है। यह बहुभुज का निर्माण करेगा।

आप केंद्र (x0,y0), त्रिज्या r साथ एक चक्र आकर्षित करने के लिए है, तो आप उपयोग कर सकते हैं चाहता हूँ मान लीजिए:

int f(int i, int j, int x0, int y0, int r) 
{ 
    return pow((i-x0),2) + pow((j-y0),2) - pow(r,2) < 0;   
} 


for(int i = x0-r; i <= x0 + r; i++) 
{ 
    for(int j = y0-r; j <= y0 + r; j++) 
    { 
     if(f(i,j,x0,y0,r)) 
     { 
      M[i][j] = 1; 
     } 
     else 
     { 
      M[i][j] = 0; 
     } 
    } 
} 
+0

आपका समाधान एक सर्कल के लिए अच्छा काम करता है। लेकिन मुझे वास्तव में इस दृष्टिकोण के साथ अधिक जटिल आकार खींचने का एक आसान तरीका नहीं दिख रहा है। इसके अलावा यदि मैं अलग-अलग आकार खींचना चाहता हूं तो यह बहुत लचीला प्रतीत नहीं होता है। – Samuel

+0

हां, यह थोड़ा और जटिल होगा। हालांकि, आप उन्हें वर्णन करने के लिए टुकड़े के अनुसार परिभाषित कार्यों का उपयोग कर सकते हैं। शायद बहुत सरल और कुशल तरीके हैं, लेकिन मेरा अनुमान कहीं है कि आपको अपने आकार के गणितीय कार्य के कुछ रूपों का वर्णन करने की आवश्यकता होगी। – GoodDeeds

1

साथ कार्यक्रम (example.c) का परीक्षण किया आप मनमाने ढंग से आकार आकर्षित करने के लिए सक्षम होना चाहते हैं, तो आप शायद एसवीजी उपयोग करना चाहते हैं। मैं एक उदाहरण के साथ nanosvg.h and nanosvgrast.h सिफारिश कर सकते हैं (यह भी अन्य छवि प्रारूप और X11 में छवि प्रदर्शित करने के लिए XCB के लिए stb_image का उपयोग करता है) यह GitHub सार में रूप में भी उपलब्ध है here

#include <xcb/xcb.h> 
#include <xcb/xcb_image.h> 
#define STBI_NO_HDR 
#define STBI_NO_LINEAR 
#define STB_IMAGE_IMPLEMENTATION 
#include "stb_image.h" 
#define NANOSVG_IMPLEMENTATION 
#include "nanosvg.h" 
#define NANOSVGRAST_IMPLEMENTATION 
#include "nanosvgrast.h" 

int main(int argc, char **argv){ 
    xcb_connection_t *c = xcb_connect(0, 0); 
    xcb_screen_t *s = xcb_setup_roots_iterator(xcb_get_setup(c)).data; 
    int w, h, n, 
     depth = s->root_depth, 
     win_class = XCB_WINDOW_CLASS_INPUT_OUTPUT, 
     format = XCB_IMAGE_FORMAT_Z_PIXMAP; 
    xcb_colormap_t colormap = s->default_colormap; 
    xcb_drawable_t win = xcb_generate_id(c); 
    xcb_gcontext_t gc = xcb_generate_id(c); 
    xcb_pixmap_t pixmap = xcb_generate_id(c); 
    xcb_generic_event_t *ev; 
    xcb_image_t *image; 
    NSVGimage *shapes = NULL; 
    NSVGrasterizer *rast = NULL; 
    char *data = NULL; 
    unsigned *dp; 
    size_t i, len; 
    uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, 
     value_mask = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS, 
     values[] = { s->black_pixel, value_mask }; 

    if (argc<2) return -1; 
    if ((data = stbi_load(argv[1], &w, &h, &n, 4))) 
     ; 
    else if ((shapes = nsvgParseFromFile(argv[1], "px", 96.0f))) { 
     w = (int)shapes->width; 
     h = (int)shapes->height; 
     rast = nsvgCreateRasterizer(); 
     data = malloc(w*h*4); 
     nsvgRasterize(rast, shapes, 0,0,1, data, w, h, w*4); 
    }else return -1; 
    for(i=0,len=w*h,dp=(unsigned *)data;i<len;i++) //rgba to bgra 
     dp[i]=dp[i]&0xff00ff00|((dp[i]>>16)&0xFF)|((dp[i]<<16)&0xFF0000); 
    xcb_create_window(c,depth,win,s->root,0,0,w,h,1,win_class,s->root_visual,mask,values); 
    xcb_create_pixmap(c,depth,pixmap,win,w,h); 
    xcb_create_gc(c,gc,pixmap,0,NULL); 
    image = xcb_image_create_native(c,w,h,format,depth,data,w*h*4,data); 
    xcb_image_put(c, pixmap, gc, image, 0, 0, 0); 
    xcb_image_destroy(image); 
    xcb_map_window(c, win); 
    xcb_flush(c); 
    while ((ev = xcb_wait_for_event(c))) { 
     switch (ev->response_type & ~0x80){ 
     case XCB_EXPOSE: { 
     xcb_expose_event_t *x = (xcb_expose_event_t *)ev; 
     xcb_copy_area(c,pixmap,win,gc,x->x,x->y,x->x,x->y,x->width,x->height); 
     xcb_flush(c); 
     }break; 
     case XCB_BUTTON_PRESS: goto end; 
     default: break; 
     } 
    } 
end: 
    xcb_free_pixmap(c, pixmap); 
    xcb_disconnect(c); 
    return 0; 
} 

आप को फिट करने के लिए रास्टेराइज़र कोड को संशोधित करने की आवश्यकता हो सकती X11 के बजाय आपका विशिष्ट प्रारूप, लेकिन आप अपने आकार उत्पन्न करने के लिए किसी भी svg छवि संपादक का उपयोग करने में सक्षम होना चाहिए (या यहां तक ​​कि केवल उन्हें एक दृश्य बॉक्स और पथ का उपयोग करके हाथ कोड) उदाहरण के लिए, अपनी छवियों को काले और सफेद रंग में खींचें और किसी भी का उपयोग करें आरजीबीए परिणाम में उत्पन्न आर, जी या बी बिट्स के बजाय इसे एक्स 11 पिक्सेल प्रारूप में परिवर्तित करने के बजाय।

एसवीजी प्रारूप का उपयोग करने से आप इसे किसी भी आकार के छवि प्रारूप (संपादन में उल्लिखित समेत) में परिवर्तित कर सकते हैं, जबकि इसे किसी भी आकार में खींचते हुए यह देखना आसान हो जाता है कि एक्स या वाई आयाम प्रवाह को कैसे प्रभावित करते हैं। एसवीजी प्रारूप भी ठीक ट्यूनिंग के लिए व्यक्तिगत आकारों पर बड़ी संख्या में परिवर्तनों की अनुमति देता है।

1

मैं सर्कल बनाने के लिए 'पाप' और 'कोस' का उपयोग करना पसंद करता हूं। यदि आप ओवल जैसे कुछ विशेष आकार चाहते हैं। आप 'fac_specialX' और 'fac_specialY' का उपयोग कर सकते हैं इसे अलग बनाते हैं। 'fac_specialX' और 'fac_specialY' नहीं एक निश्चित मूल्य, आकार और अधिक विशेष कर सकते हैं। (या बस चक्र सरणी के एक हिस्से को संशोधित करने की कोशिश)

int r=10;// radius 
int x0=25,y0=25; // center 
int circle_points = 300; // accuracy --> higher cause better quality but slow 
int circleX[circle_points]; // circle array 
int circleY[circle_points]; // circle array 
// #define PI 3.1415926 
double fac_angle = (2*PI)/circle_points; 
// normal circle : fac_specialX & fac_specialY set 1 
// Oval : fac_specialX --> higher cause longer in X 
//   fac_specialY --> higher cause longer in Y 
double fac_specialX = 0.5; 
double fac_specialY = 1.5; 
// Calculate the coordinates 
for(int i=0 ; i<circle_points ; i++) { 

    // #include <math.h> ->> sin cos 
    circleX[i] = x0 + r*sin((i+1)*fac_angle)*fac_specialX; 
    circleY[i] = y0 + r*cos((i+1)*fac_angle)*fac_specialY; 
    // set the ponts in M array 
    M[ circleY[i] ][ circleX[i] ] = 1; 
} 
1

(शायद पाश में हर बार बदला जा) यदि यदि आंकड़ों की संख्या इतनी अधिक नहीं है (उदाहरण के लिए 100 से कम) तो आप प्रत्येक पिक्सेल की जांच कर सकते हैं यदि यह किसी बहुभुज से संबंधित है।आपको केवल आकृति अमूर्तता की आवश्यकता है:

/* Abstract struct for hloding figure (rectangle or elipse data)*/ 
typedef struct _figure_t* figure_t; 

/* Pointer to pixel check algorithm implementation */ 
typedef int (*is_pixel_belongs_t)(uint32_t, uint32_t, figure_t); 

struct _figure_t { 
    is_pixel_belongs_t is_pixel_belongs; 
}; 

/* figure implementation for rectangle */ 
typedef struct _rectangle_t { 
    is_pixel_belongs_t is_pixel_belongs; 
    uint32_t x; 
    uint32_t y; 
    uint32_t width; 
    uint32_t height; 
} * rectangle_t; 

int is_pixel_belongs_rectangle(uint32_t x, uint32_t y, rectangle_t rect) { 
    int x_belongs (x >= rect->x) && (x <= (rect->x + rect->width)); 
    int y_belongs (y >= rect->y) && (y <= (rect->y + rect->height)); 
    return x_belongs && y_belongs; 
} 

figure_t make_rect(uint32_t x, uint32_t y, uint32_t width, uint32_t height) { 
    rectangle_t result = (rectangle_t) malloc(sizeof(struct _rectangle_t)); 
    result->is_pixel_belongs = (is_pixel_belongs_t) is_pixel_belongs_rectangle; 
    result->x = x; 
    result->y = x; 
    result->width = width; 
    result->height = height; 
} 

/* figure implementation for elipse */ 
typedef struct _rectangle_t { 
    is_pixel_belongs_t is_pixel_belongs; 
    uint32_t x; 
    uint32_t y; 
    uint32_t width; 
    uint32_t height; 
} * rectangle_t; 

/* Elipse implementation */ 
/* x^2/a^2 + y^2/b^2 = 1*/ 
figure_t make_elipse(uint32_t x, uint32_t y, uint32_t a, uint32_t b); 


void main() { 
    #define NUM_FIGURES 10 
    figure_t figures[NUM_FIGURES] = { 
     make_rect(0, 0, 40, 40), 
     make_elipse(256, 128, 80, 40), 
     /* Add more figures*/ 
    } 

    /* Initialize your image */ 

    /* For each pixel */ 
    for(uint32_t x = 0; x < width; ++x) { 
     for(uint32_t y = 0; y < height; ++x) { 
      /* For each figure check if pixel (x,y) belongs to it*/ 
      for(uint32_t figure_ii = 0; figure_ii < NUM_FIGURES; ++figure_ii) { 
       if (figures[figure_ii]->is_pixel_belongs(x, y)) { 
        image[x][y] = 1; 
        break; 
       } 
      } 
     } 
    } 
} 

यह बहुत सरल दृष्टिकोण है और आपने जो किया है उसके करीब है। आंकड़ों द्वारा आंतरिक लूप प्रदर्शन को प्रभावित कर सकता है, अगर आपको हजारों/लाखों मनमानी आंकड़े आकर्षित करने की आवश्यकता है तो आपको ऑक्स संरचनाओं का उपयोग करने की आवश्यकता होगी। एक विकल्प binary space partitioning दृष्टिकोण है। अर्थात। अपने आंकड़े बाइनरी पेड़ में व्यवस्थित करें ताकि आप O(log(n)) समय में पिक्सेल द्वारा एक आकृति पा सकें जहां n आंकड़े की संख्या है। या आप अपनी छवि को वर्दी ग्रिड पर थूक सकते हैं और प्रत्येक टाइल के लिए आंकड़े सूची रख सकते हैं।

संबंधित मुद्दे

 संबंधित मुद्दे