2017-05-01 56 views
5

का उपयोग करके लंबाई खंडों में भी वक्र को दोहराएं सी ++ का उपयोग करके लंबाई खंडों में वक्र को फिर से बदलने का सबसे अच्छा तरीका क्या होगा? मेरे पास जो बिंदु है वह एक 2 डी वक्र का प्रतिनिधित्व करता है जो बिंदुओं का एक सेट है। नीचे दिए गए मेरे उदाहरण में मेरे पास एक्स और वाई घटकों के साथ एक बिंदु संरचना है और परीक्षण पदों वाले बिंदुओं का वेक्टर है। अंक की प्रत्येक जोड़ी वक्र पर एक सेगमेंट का प्रतिनिधित्व करती है। उदाहरण अनुकरण घटता नीचे दी गई छवियां हैं। रेड सर्किल मूल स्थिति हैं जो अनुकरण के बाद हरी मंडल लक्ष्य स्थितियां हैं।सी ++

Resample 1enter image description here

struct Point 
{ 
    float x, y; 
}; 


std::vector<Point> Points; 
int numPoints = 5; 

float positions[] = { 
0.0350462, -0.0589667, 
0.0688311, 0.240896, 
0.067369, 0.557199, 
-0.024258, 0.715255, 
0.0533231, 0.948694, 
}; 

// Add points 
int offset = 2; 
for (int i =0; i < numPoints; i++) 
{ 
    offset = i * 2; 
    Point pt; 
    pt.x = positions[offset]; 
    pt.y = positions[offset+1]; 
    Points.push_back(pt); 

} 
+0

उस इंटरपोलेशन को करने का सबसे अच्छा तरीका आपके डेटा की प्रकृति पर निर्भर करता है और आपको कितना सटीक होना चाहिए। मैं googling रैखिक और spline interpolations द्वारा शुरू करने के लिए शुरू करना होगा यह देखने के लिए कि क्या वे आपको क्या करना होगा। – RyanP

+0

इस विषय को जानने के लिए आप कंप्यूटर ग्राफिक्स पर कौन सी पुस्तक का उपयोग कर रहे हैं? –

+0

यदि मैं किनारे से पुन: नमूना करता हूं तो वर्तमान बिंदु से अगले स्थान पर विस्थापित या लापरवाही करना काफी आसान है। जो मैं समझ नहीं पा रहा हूं वह पूरे वक्र के लिए कर रहा है। – sabotage3d

उत्तर

2

देखने के लिए कि यह आपके लिए काम करता है। पुनर्वित्त बिंदु स्रोत वेक्टर के बिंदुओं के रैखिक इंटरपोलेशन पर एक दूसरे से समान हैं।

#include <iostream> 
#include <iomanip> 
#include <vector> 
#include <cmath> 

struct Point { 
    double x, y; 
}; 

// Distance gives the Euclidean distance between two Points 
double Distance(const Point& a, const Point& b) { 
    const double dx = b.x - a.x; 
    const double dy = b.y - a.y; 
    const double lsq = dx*dx + dy*dy; 
    return std::sqrt(lsq); 
} 

// LinearCurveLength calculates the total length of the linear 
// interpolation through a vector of Points. It is the sum of 
// the Euclidean distances between all consecutive points in 
// the vector. 
double LinearCurveLength(std::vector<Point> const &points) { 
    auto start = points.begin(); 
    if(start == points.end()) return 0; 
    auto finish = start + 1; 
    double sum = 0; 
    while(finish != points.end()) { 
     sum += Distance(*start, *finish); 
     start = finish++; 
    } 
    return sum; 
} 

// Gives a vector of Points which are sampled as equally-spaced segments 
// taken along the linear interpolation between points in the source. 
// In general, consecutive points in the result will not be equidistant, 
// because of a corner-cutting effect. 
std::vector<Point> UniformLinearInterpolation(std::vector<Point> const &source, std::size_t target_count) { 
    std::vector<Point> result; 
    if(source.size() < 2 || target_count < 2) { 
     // degenerate source vector or target_count value 
     // for simplicity, this returns an empty result 
     // but special cases may be handled when appropriate for the application 
     return result; 
    } 
    // total_length is the total length along a linear interpolation 
    // of the source points. 
    const double total_length = LinearCurveLength(source); 

    // segment_length is the length between result points, taken as 
    // distance traveled between these points on a linear interpolation 
    // of the source points. The actual Euclidean distance between 
    // points in the result vector can vary, and is always less than 
    // or equal to segment_length. 
    const double segment_length = total_length/(target_count - 1); 

    // start and finish are the current source segment's endpoints 
    auto start = source.begin(); 
    auto finish = start + 1; 

    // src_segment_offset is the distance along a linear interpolation 
    // of the source curve from its first point to the start of the current 
    // source segment. 
    double src_segment_offset = 0; 

    // src_segment_length is the length of a line connecting the current 
    // source segment's start and finish points. 
    double src_segment_length = Distance(*start, *finish); 

    // The first point in the result is the same as the first point 
    // in the source. 
    result.push_back(*start); 

    for(std::size_t i=1; i<target_count-1; ++i) { 
     // next_offset is the distance along a linear interpolation 
     // of the source curve from its beginning to the location 
     // of the i'th point in the result. 
     // segment_length is multiplied by i here because iteratively 
     // adding segment_length could accumulate error. 
     const double next_offset = segment_length * i; 

     // Check if next_offset lies inside the current source segment. 
     // If not, move to the next source segment and update the 
     // source segment offset and length variables. 
     while(src_segment_offset + src_segment_length < next_offset) { 
      src_segment_offset += src_segment_length; 
      start = finish++; 
      src_segment_length = Distance(*start, *finish); 
     } 
     // part_offset is the distance into the current source segment 
     // associated with the i'th point's offset. 
     const double part_offset = next_offset - src_segment_offset; 

     // part_ratio is part_offset's normalized distance into the 
     // source segment. Its value is between 0 and 1, 
     // where 0 locates the next point at "start" and 1 
     // locates it at "finish". In-between values represent a 
     // weighted location between these two extremes. 
     const double part_ratio = part_offset/src_segment_length; 

     // Use part_ratio to calculate the next point's components 
     // as weighted averages of components of the current 
     // source segment's points. 
     result.push_back({ 
      start->x + part_ratio * (finish->x - start->x), 
      start->y + part_ratio * (finish->y - start->y) 
     }); 
    } 

    // The first and last points of the result are exactly 
    // the same as the first and last points from the input, 
    // so the iterated calculation above skips calculating 
    // the last point in the result, which is instead copied 
    // directly from the source vector here. 
    result.push_back(source.back()); 
    return result; 
} 

int main() { 
    std::vector<Point> points = { 
     { 0.0350462, -0.0589667}, 
     { 0.0688311, 0.240896 }, 
     { 0.067369, 0.557199 }, 
     {-0.024258, 0.715255 }, 
     { 0.0533231, 0.948694 } 
    }; 

    std::cout << "Source Points:\n"; 
    for(const auto& point : points) { 
     std::cout << std::setw(14) << point.x << " " << std::setw(14) << point.y << '\n'; 
    } 
    std::cout << '\n'; 
    auto interpolated = UniformLinearInterpolation(points, 7); 
    std::cout << "Interpolated Points:\n"; 
    for(const auto& point : interpolated) { 
     std::cout << std::setw(14) << point.x << " " << std::setw(14) << point.y << '\n'; 
    } 
    std::cout << '\n'; 
    std::cout << "Source linear interpolated length:   " << LinearCurveLength(points) << '\n'; 
    std::cout << "Interpolation's linear interpolated length: " << LinearCurveLength(interpolated) << '\n'; 
} 
+0

आप समाधान काफी अच्छी तरह से काम करता है। इस भाग को अनुकूलित करने का एक तरीका है, जबकि (src_segment_offset + src_segment_length sabotage3d

+0

@ sabotage3d यहां एक अनावश्यक अतिरिक्त ऑपरेशन है, जो मुझे पूरा यकीन है कि अनुकूलक का ख्याल रखता है। लेकिन, मेरे सिर के ऊपर से, मैं नहीं देखता कि नक्शा यहां कैसे मदद कर सकता है। क्या आप यहां मानचित्र का उपयोग करने के बारे में अपने विचारों को बता सकते हैं? धन्यवाद। –

+0

@ sabotage3d शायद आपके मन में क्या है यह है कि लगातार स्रोत बिंदुओं के माध्यम से इस रैखिक खोज को किसी कुंजीपटल लुकअप की तरह कुछ और अनुकूलित किया जा सकता है? –

0

पॉलीलाइन साथ समान दूरी पर हरे रंग अंक के लिए:

पहली बार चलाने: बिंदु सूची के माध्यम से चलना, वर्तमान बात करने के लिए हर सेगमेंट और संचयी लंबाई की अवधि की गणना। स्यूडोकोड:

cumlen[0] = 0; 
for (int i=1; i < numPoints; i++) { 
    len = Sqrt((Point[i].x - Point[i-1].x)^2 + (Point[i].y - Point [i-1].y)^2) 
    cumlen[i] = cumlen[i-1] + len; 
} 

अब हर नए टुकड़ा

plen = cumlen[numpoints-1]/numpieces; 

अब इसके दूसरे भाग की लंबाई को खोजने - बिंदु सूची के माध्यम से चलना और उचित क्षेत्रों में नए अंक डालें। numpieces > numPoints के लिए वास्तविक उत्पादन का

i = 0; 
for (ip=0; ip<numpieces; ip++) { 
    curr = plen * ip; 
    while cumlen[i+1] < curr 
    i++; 
    P[ip].x = Points[i].x + (curr - cumlen[i]) * (Points[i+1].x - Points[i].x)/
          (cumlen[i+1] - cumlen[i]); 
    ..the same for y 
} 

उदाहरण और इसके विपरीत

enter image description here

+0

छद्म कोड में कुछ गड़बड़ है मैं इसे सही तरीके से काम नहीं कर सकता। यदि हम मूल सेगमेंट की संख्या को कम करना चाहते हैं तो यह दृष्टिकोण भी काम करेगा? – sabotage3d

+0

'कोलेन [i + 1] 'के दौरान कोड बदल दिया। अगर numpieces MBo

+0

क्षमा करें, तो मुझे अंतिम वाक्य समझ में नहीं आ रहा है। नए अंक (मंडल) मेरे कार्यान्वयन में पुराने खंडों पर झूठ बोलते हैं। – MBo