বিন্দু এবং একটি রেখাংশের মধ্যে সবচেয়ে কম দূরত্ব


358

পয়েন্ট এবং একটি রেখাংশের মধ্যে সবচেয়ে কমতম দূরত্ব খুঁজে পেতে আমার একটি প্রাথমিক ফাংশন প্রয়োজন। আপনার যে কোনও ভাষায় সমাধানটি নির্দ্বিধায় লিখুন; আমি এটি (জাভাস্ক্রিপ্ট) যা ব্যবহার করছি তাতে অনুবাদ করতে পারি।

সম্পাদনা: আমার লাইন বিভাগটি দুটি শেষ পয়েন্ট দ্বারা সংজ্ঞায়িত করা হয়েছে। সুতরাং আমার লাইন বিভাগটি ABদুটি পয়েন্ট দ্বারা সংজ্ঞায়িত করা হয় A (x1,y1)এবং B (x2,y2)। আমি এই লাইন বিভাগ এবং একটি বিন্দুর মধ্যে দূরত্ব সন্ধান করার চেষ্টা করছি C (x3,y3)। আমার জ্যামিতি দক্ষতা মরিচা, সুতরাং আমি যে উদাহরণগুলি দেখেছি তা বিভ্রান্তিকর, আমি স্বীকার করে দুঃখিত।


আপনি কীভাবে লাইন এবং পয়েন্টগুলি উপস্থাপন করছেন তা আমি জানি না, তবে আপনাকে শুরু করতে হবে এমন সমস্ত গণিত এখানে । আপনার কী করা দরকার তা নির্ধারণ করা খুব কঠিন হওয়া উচিত নয়।
মন্ডলেকা

4
@ আর্থারকলিওকোস্কি: এই লিঙ্কটি মারা গেছে, তবে আমি একটি অনুলিপি পেয়েছি: পলবৌড়কন.ট.
গুন্থার স্ট্রুইফ

11
@ গুঞ্জেরস্ট্রুইফ: এই লিঙ্কটিও মারা গেছে, তবে এই একই লিঙ্কটি কাজ করে: পলবৌড়কনেট
মাইকেল

1
যদি কেউ একটি বিন্দু এবং লাইনের মধ্যে দূরত্ব খুঁজছেন, কোনও বিন্দু এবং একটি লাইন SEGMENT নয়, তবে এই লিঙ্কটি দেখুন: gist.github.com/rhyolight/2846020
নিক

1
উপরের লিঙ্কটি মারা গেছে। এখানে সিউডো-কোড এবং সি ++ নমুনা, পাঠ্যপুস্তক হিসাবে বিস্তৃত হিসাবে ব্যাখ্যা এবং উত্পন্ন হয়েছে, জিওমালগোরিদিমস
এরিক

উত্তর:


446

এলি, আপনি যে কোডটি স্থায়ী করেছেন তা ভুল। রেখাটির নিকটে একটি বিন্দু যেখানে সেগমেন্টটি অবস্থিত তবে বিভাগটির এক প্রান্তের অনেক দূরে সেগমেন্টের কাছে ভুলভাবে বিচার করা হবে। আপডেট: উল্লিখিত ভুল উত্তরটি এখন আর গ্রহণযোগ্য নয়।

সি ++ তে এখানে কিছু সঠিক কোড রয়েছে। এটি class vec2 {float x,y;}অপারেটরদের যোগ, বিয়োগ, স্কেল, ইত্যাদি এবং একটি দূরত্ব এবং ডট পণ্য ফাংশন (অর্থাত্ x1 x2 + y1 y2) সহ প্রয়োজনীয়ভাবে একটি ক্লাস 2 ডি-ভেক্টর ধার্য করে ।

float minimum_distance(vec2 v, vec2 w, vec2 p) {
  // Return minimum distance between line segment vw and point p
  const float l2 = length_squared(v, w);  // i.e. |w-v|^2 -  avoid a sqrt
  if (l2 == 0.0) return distance(p, v);   // v == w case
  // Consider the line extending the segment, parameterized as v + t (w - v).
  // We find projection of point p onto the line. 
  // It falls where t = [(p-v) . (w-v)] / |w-v|^2
  // We clamp t from [0,1] to handle points outside the segment vw.
  const float t = max(0, min(1, dot(p - v, w - v) / l2));
  const vec2 projection = v + t * (w - v);  // Projection falls on the segment
  return distance(p, projection);
}

সম্পাদনা: আমার একটি জাভাস্ক্রিপ্ট বাস্তবায়ন দরকার, সুতরাং এটি কোনও নির্ভরতা (বা মন্তব্য নয়, তবে এটি উপরের প্রত্যক্ষ বন্দর) সহ is পয়েন্টগুলি অবজেক্ট xএবং yবৈশিষ্ট্য হিসাবে প্রতিনিধিত্ব করা হয় ।

function sqr(x) { return x * x }
function dist2(v, w) { return sqr(v.x - w.x) + sqr(v.y - w.y) }
function distToSegmentSquared(p, v, w) {
  var l2 = dist2(v, w);
  if (l2 == 0) return dist2(p, v);
  var t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2;
  t = Math.max(0, Math.min(1, t));
  return dist2(p, { x: v.x + t * (w.x - v.x),
                    y: v.y + t * (w.y - v.y) });
}
function distToSegment(p, v, w) { return Math.sqrt(distToSegmentSquared(p, v, w)); }

সম্পাদনা 2: আমার একটি জাভা সংস্করণ প্রয়োজন, তবে আরও গুরুত্বপূর্ণ এটি আমার 2 ডি এর পরিবর্তে 3 ডি প্রয়োজন।

float dist_to_segment_squared(float px, float py, float pz, float lx1, float ly1, float lz1, float lx2, float ly2, float lz2) {
  float line_dist = dist_sq(lx1, ly1, lz1, lx2, ly2, lz2);
  if (line_dist == 0) return dist_sq(px, py, pz, lx1, ly1, lz1);
  float t = ((px - lx1) * (lx2 - lx1) + (py - ly1) * (ly2 - ly1) + (pz - lz1) * (lz2 - lz1)) / line_dist;
  t = constrain(t, 0, 1);
  return dist_sq(px, py, pz, lx1 + t * (lx2 - lx1), ly1 + t * (ly2 - ly1), lz1 + t * (lz2 - lz1));
}

1
আমি পৃথক উত্তর হিসাবে এর একটি মাংসপেশী সংস্করণ যুক্ত করেছি।
এম কাটজ

4
ধন্যবাদ @ গ্রামড্রিগ, আপনার জাভাস্ক্রিপ্ট সমাধানটি স্পট এবং একটি বিশাল সময় সাশ্রয়কারী ছিল। আমি আপনার সমাধানটি উদ্দেশ্য-সিতে পোর্ট করেছি এবং এটি নীচে যুক্ত করেছি।
অগলফ

1
আমরা সত্যিই কেবল সেখানে শূন্য দ্বারা বিভাজন এড়াতে চেষ্টা করছি।
গ্রুমড্রিগ

9
pএকটি রেখার উপরে পয়েন্টের অভিক্ষেপটি হ'ল নিকটবর্তী লাইনের বিন্দু p। (এবং অভিক্ষেপ লাইনে করার জন্য একটি ঋজু মাধ্যমে পাস হবে p।) সংখ্যা tকতদূর লাইন বিভাগটির বরাবর থেকে vথেকে wযে অভিক্ষেপ পড়ে। সুতরাং যদি t0 হয় তবে প্রক্ষেপণটি ঠিক পড়ে যায় v; যদি এটি 1 হয়, এটি চালু w; উদাহরণস্বরূপ যদি এটি 0.5 হয় তবে এটি অর্ধেকের মধ্যে। যদি t0 এর চেয়ে কম বা 1 এর বেশি হয় তবে এটি এক প্রান্ত বা সেগমেন্টের অপর প্রান্তের লাইনে পড়ে। সেক্ষেত্রে সেগমেন্টের দূরত্বটি আরও কাছাকাছি হতে হবে।
গ্রুমড্রিগ

1
ওফস - কেউ 3D সংস্করণ সরবরাহ করেছে তা খেয়াল করেনি। @ রাজিসোলোরজানো, আপনাকে ল্যাট, লম্বা স্থানাঙ্কগুলি প্রথমে 3-স্পেসে এক্স, ওয়াই, জেড স্থানাঙ্কে রূপান্তর করতে হবে।
গ্রামড্রিগ

110

এখানে জাভাস্ক্রিপ্টের সহজতম কোড।

x, y আপনার টার্গেট পয়েন্ট এবং x1, y1 থেকে x2, y2 আপনার লাইন বিভাগ gment

আপডেট করা: মন্তব্যগুলি থেকে 0 দৈর্ঘ্যের লাইন সমস্যার জন্য ঠিক করুন।

function pDistance(x, y, x1, y1, x2, y2) {

  var A = x - x1;
  var B = y - y1;
  var C = x2 - x1;
  var D = y2 - y1;

  var dot = A * C + B * D;
  var len_sq = C * C + D * D;
  var param = -1;
  if (len_sq != 0) //in case of 0 length line
      param = dot / len_sq;

  var xx, yy;

  if (param < 0) {
    xx = x1;
    yy = y1;
  }
  else if (param > 1) {
    xx = x2;
    yy = y2;
  }
  else {
    xx = x1 + param * C;
    yy = y1 + param * D;
  }

  var dx = x - xx;
  var dy = y - yy;
  return Math.sqrt(dx * dx + dy * dy);
}

সমাধানটি কল্পনা করতে সহায়তা করার জন্য চিত্র help


8
এই সমস্যাটি সমাধান করতে আমি যে সমস্ত কোড দেখেছি সেগুলির মধ্যে আমি এটিকে সেরা পছন্দ করি। এটি খুব পরিষ্কার এবং পড়া সহজ। যদিও এর পিছনে গণিতটি কিছুটা রহস্যময় ical দৈর্ঘ্যের স্কোয়ার দ্বারা বিভক্ত ডট-প্রোডাক্ট আসলে কী উপস্থাপন করে?
ব্যবহারকারী 1815201

2
দৈর্ঘ্যের স্কোয়ার দ্বারা বিভক্ত বিন্দু পণ্য আপনাকে প্রজেকশন দূরত্ব দেয় (x1, y1)। এটি বিন্দু (x, y) এর নিকটতম রেখার ভগ্নাংশ। চূড়ান্ত অন্য বিভাগটি দেখুন যেখানে (xx, yy) গণনা করা হয়েছে - এটি বিভাগের (x, y1) বিন্দুর (x1, y1) - (x2, y2) এর প্রক্ষেপণ।
লোগান পিকআপ

4
0 দৈর্ঘ্যের লাইন বিভাগগুলির জন্য চেক কোডের চেয়ে অনেক নিচে। 'len_sq' শূন্য হবে এবং সুরক্ষা চেক করার আগে কোডটি 0 দিয়ে বিভক্ত হবে।
হোস্টেডমেট্রিক্স ডট কম

17
মিটার। এটি মিটারে ফিরে আসে।
জোশুয়া

1
@ এনভারমাইন্ড, আসুন আমাদের পয়েন্ট p0 এবং পয়েন্টগুলি কল করুন যা লাইনটিকে p1 এবং p2 হিসাবে সংজ্ঞায়িত করে। তারপরে আপনি ভেক্টরগুলি এ = পি0 - পি 1 এবং বি = পি 2 - পি 1 পাবেন। পরম হল স্কেলারের মান যা বি তে গুণিত হলে আপনাকে p0 এর নিকটবর্তী লাইনে বিন্দু দেয়। যদি পরম <= 0 হয় তবে নিকটতম পয়েন্ট হ'ল পি 1। যদি পরম> = 1 হয় তবে নিকটতম বিন্দু হল পি 1। যদি এটি 0 এবং 1 এর মধ্যে হয় তবে এটি কোথাও p1 এবং p2 এর মধ্যে রয়েছে তাই আমরা ছেদ করি। এক্সএক্স এবং ওয়াইওয়াই তখন লাইন বিভাগের নিকটতম পয়েন্ট, ডিএক্স / ডিওয়াই p0 থেকে সেই বিন্দুতে ভেক্টর এবং অবশেষে আমরা সেই ভেক্টরের দৈর্ঘ্যটি ফিরিয়ে আনি।
শন

70

এটি ফাইন লাইন সেগমেন্টগুলির জন্য তৈরি একটি বাস্তবায়ন, এখানে অন্যান্য বেশিরভাগ ফাংশনের মতো অসীম লাইন মনে হয় না (এজন্যই আমি এটি তৈরি করেছি)।

পল বোর্কের তত্ত্বের বাস্তবায়ন

পাইথন:

def dist(x1, y1, x2, y2, x3, y3): # x3,y3 is the point
    px = x2-x1
    py = y2-y1

    norm = px*px + py*py

    u =  ((x3 - x1) * px + (y3 - y1) * py) / float(norm)

    if u > 1:
        u = 1
    elif u < 0:
        u = 0

    x = x1 + u * px
    y = y1 + u * py

    dx = x - x3
    dy = y - y3

    # Note: If the actual distance does not matter,
    # if you only want to compare what this function
    # returns to other results of this function, you
    # can just return the squared distance instead
    # (i.e. remove the sqrt) to gain a little performance

    dist = (dx*dx + dy*dy)**.5

    return dist

AS3:

public static function segmentDistToPoint(segA:Point, segB:Point, p:Point):Number
{
    var p2:Point = new Point(segB.x - segA.x, segB.y - segA.y);
    var something:Number = p2.x*p2.x + p2.y*p2.y;
    var u:Number = ((p.x - segA.x) * p2.x + (p.y - segA.y) * p2.y) / something;

    if (u > 1)
        u = 1;
    else if (u < 0)
        u = 0;

    var x:Number = segA.x + u * p2.x;
    var y:Number = segA.y + u * p2.y;

    var dx:Number = x - p.x;
    var dy:Number = y - p.y;

    var dist:Number = Math.sqrt(dx*dx + dy*dy);

    return dist;
}

জাভা

private double shortestDistance(float x1,float y1,float x2,float y2,float x3,float y3)
    {
        float px=x2-x1;
        float py=y2-y1;
        float temp=(px*px)+(py*py);
        float u=((x3 - x1) * px + (y3 - y1) * py) / (temp);
        if(u>1){
            u=1;
        }
        else if(u<0){
            u=0;
        }
        float x = x1 + u * px;
        float y = y1 + u * py;

        float dx = x - x3;
        float dy = y - y3;
        double dist = Math.sqrt(dx*dx + dy*dy);
        return dist;

    }

2
দুঃখিত, তবে আমি এটি চেষ্টা করেছিলাম এবং এটি এখনও আমাকে ফলাফল দেয় যেন লাইন অনন্তে প্রসারিত হয়। যদিও গ্রুমডিগের কাজের উত্তর খুঁজে পেয়েছি।
ফ্রেডেরিক

1
সেক্ষেত্রে আপনি এটিকে ভুল ব্যবহার করছেন বা অসীম সহ অন্য কিছু বোঝাচ্ছেন। এখানে এই কোডের একটি উদাহরণ দেখুন: boomie.se/upload/Drawdebug.swf
কোয়ানো

কোড বা কোনও কিছুতে ভুল বলে মনে হচ্ছে, ফ্রেডেরিক /
ক্রোমস্টার

30
পরিবর্তনশীল নামের পছন্দগুলি ভাল (পি 2, কিছু, ইউ, ...) থেকে দূরে
মাইগুয়েলস্যান্টিরসো

2
আমি ফাংশনের পাইথন সংস্করণ চেষ্টা করে দেখেছি যে পরামিতিগুলি পূর্ণসংখ্যা হলে এটি ভুল ফলাফল দেখায়। distAnother(0, 0, 4, 0, 2, 2)2.8284271247461903 (ভুল) দেয়। distAnother(0., 0., 4., 0., 2., 2.)2.0 দেয় (সঠিক) এই সচেতন হতে হবে দয়া করে। আমি মনে করি কোথাও কোথাও ভাসমান রূপান্তর করতে কোডটি উন্নত করা যেতে পারে।
ভ্লাদিমির ওব্রিজান

22

আমার নিজের প্রশ্ন থ্রেডে সি, সি # /। নেট 2.0 বা জাভাতে সমস্ত ক্ষেত্রে একটি বিন্দু এবং একটি লাইন বিভাগের মধ্যে সংক্ষিপ্ত 2D দূরত্ব কীভাবে গণনা করা যায়? আমি যখন একটি উত্তর পাই তখন আমাকে এখানে একটি সি # উত্তর দিতে বলা হয়েছিল: তাই এখানে এটি http://www.topcoder.com/tc?d1=tutorials&d2=geometry1&module=Static থেকে পরিবর্তিত হয়েছে :

//Compute the dot product AB . BC
private double DotProduct(double[] pointA, double[] pointB, double[] pointC)
{
    double[] AB = new double[2];
    double[] BC = new double[2];
    AB[0] = pointB[0] - pointA[0];
    AB[1] = pointB[1] - pointA[1];
    BC[0] = pointC[0] - pointB[0];
    BC[1] = pointC[1] - pointB[1];
    double dot = AB[0] * BC[0] + AB[1] * BC[1];

    return dot;
}

//Compute the cross product AB x AC
private double CrossProduct(double[] pointA, double[] pointB, double[] pointC)
{
    double[] AB = new double[2];
    double[] AC = new double[2];
    AB[0] = pointB[0] - pointA[0];
    AB[1] = pointB[1] - pointA[1];
    AC[0] = pointC[0] - pointA[0];
    AC[1] = pointC[1] - pointA[1];
    double cross = AB[0] * AC[1] - AB[1] * AC[0];

    return cross;
}

//Compute the distance from A to B
double Distance(double[] pointA, double[] pointB)
{
    double d1 = pointA[0] - pointB[0];
    double d2 = pointA[1] - pointB[1];

    return Math.Sqrt(d1 * d1 + d2 * d2);
}

//Compute the distance from AB to C
//if isSegment is true, AB is a segment, not a line.
double LineToPointDistance2D(double[] pointA, double[] pointB, double[] pointC, 
    bool isSegment)
{
    double dist = CrossProduct(pointA, pointB, pointC) / Distance(pointA, pointB);
    if (isSegment)
    {
        double dot1 = DotProduct(pointA, pointB, pointC);
        if (dot1 > 0) 
            return Distance(pointB, pointC);

        double dot2 = DotProduct(pointB, pointA, pointC);
        if (dot2 > 0) 
            return Distance(pointA, pointC);
    }
    return Math.Abs(dist);
} 

আমি @ উত্তর দিচ্ছি না তবে প্রশ্ন জিজ্ঞাসা করছি তাই আমি আশা করি কিছু কারণের জন্য আমি মিলিয়ন ভোট পাব না তবে সমালোচক তৈরি করছি। আমি কেবল অন্য কারও ধারণাগুলি ভাগ করে নিতে চেয়েছিলাম (এবং উত্সাহিত হয়েছিল) যেহেতু এই থ্রেডের সমাধানগুলি হয় কোনও কোনও বহিরাগত ভাষার (ফোর্টরান, ম্যাথামেটিকা) বা কারও দ্বারা ত্রুটিযুক্ত হিসাবে ট্যাগ করা। আমার জন্য একমাত্র দরকারী (গ্রামড্রিগ দ্বারা) সি ++ দিয়ে লেখা এবং কেউ এটিকে ত্রুটিযুক্ত হিসাবে চিহ্নিত করেন নি। তবে এটি যে পদ্ধতিগুলি (বিন্দু ইত্যাদি) বলা হচ্ছে তা অনুপস্থিত।


1
এই পোস্ট করার জন্য ধন্যবাদ। তবে দেখে মনে হচ্ছে শেষ পদ্ধতিটিতে একটি সুস্পষ্ট অপ্টিমাইজেশন সম্ভব: এটির প্রয়োজনীয়তা নির্ধারিত হওয়ার পরে ডিস্ট গণনা করবেন না।
রেনিপেট

2
ডটপ্রডাক্টের মন্তব্যে বলা হয়েছে যে এটি AB.AC কম্পিউটিং করছে, তবে এটি AB.BC গণনা করছে BC
ধাতব 5050

সংজ্ঞা অনুসারে ক্রস পণ্যটি একটি ভেক্টরকে ফেরত দেয় তবে এখানে একটি স্ক্যালার ফিরিয়ে দেয়।
স্টেকওভারফ্লো

21

এফ # সালে বিন্দু থেকে দূরত্ব cমধ্যে লাইন বিভাগটির করতে aএবংb দ্বারা প্রদত্ত:

let pointToLineSegmentDistance (a: Vector, b: Vector) (c: Vector) =
  let d = b - a
  let s = d.Length
  let lambda = (c - a) * d / s
  let p = (lambda |> max 0.0 |> min s) * d / s
  (a + p - c).Length

ভেক্টর dহইতে পয়েন্ট aথেকে bলাইন বিভাগটির করেন। এর ডট পণ্যের d/sসঙ্গে c-aঅসীম লাইন এবং বিন্দু মধ্যে নিকটতম পদ্ধতির বিন্দু পরামিতি দেয় cminএবং maxফাংশন পরিসরের এই প্যারামিটারটি হাতে দমন করতে ব্যবহার করা হয় 0..s, যাতে মধ্যে বিন্দু মিথ্যা যে aএবং b। অবশেষে, দৈর্ঘ্য a+p-cহল দূরত্বc রেখাংশের নিকটতম বিন্দু ।

উদাহরণ ব্যবহার:

pointToLineSegmentDistance (Vector(0.0, 0.0), Vector(1.0, 0.0)) (Vector(-1.0, 1.0))

1
আমি মনে করি শেষ লাইনটি ভুল, এবং পড়তে হবে:(a + p - c).Length
ব্লেয়ার হলোয়ে

এটি এখনও পুরোপুরি সমস্যার সমাধান করে না। ওয়ান ওয়ে ফাংশন সংশোধন করার পুনরায় সংজ্ঞায়িত করতে হবে lambdaএবং pযেমন let lambda = (c - a) * d / (s * s)এবং let p = a + (lambda |> max 0.0 |> min 1.0) * dযথাক্রমে। এর পরে ফাংশনটি সঠিক দূরত্ব যেমন: যেখানে a = (0,1), b = (1,0)এবং এর ক্ষেত্রে ফিরে আসে c = (1,1)
মিক্কোমা

20

আগ্রহী প্রত্যেকের জন্য, জোশুয়ার জাভাস্ক্রিপ্ট কোডটি উদ্দেশ্য-সি তে তুচ্ছ রূপান্তর:

- (double)distanceToPoint:(CGPoint)p fromLineSegmentBetween:(CGPoint)l1 and:(CGPoint)l2
{
    double A = p.x - l1.x;
    double B = p.y - l1.y;
    double C = l2.x - l1.x;
    double D = l2.y - l1.y;

    double dot = A * C + B * D;
    double len_sq = C * C + D * D;
    double param = dot / len_sq;

    double xx, yy;

    if (param < 0 || (l1.x == l2.x && l1.y == l2.y)) {
        xx = l1.x;
        yy = l1.y;
    }
    else if (param > 1) {
        xx = l2.x;
        yy = l2.y;
    }
    else {
        xx = l1.x + param * C;
        yy = l1.y + param * D;
    }

    double dx = p.x - xx;
    double dy = p.y - yy;

    return sqrtf(dx * dx + dy * dy);
}

কাজ করার জন্য আমার এই সমাধানটির প্রয়োজন ছিল MKMapPointতাই অন্য কারও প্রয়োজন হলে আমি এটি ভাগ করে নেব। কিছুটা সামান্য পরিবর্তন এবং এটি মিটারে দূরত্ব ফিরিয়ে আনবে:

- (double)distanceToPoint:(MKMapPoint)p fromLineSegmentBetween:(MKMapPoint)l1 and:(MKMapPoint)l2
{
    double A = p.x - l1.x;
    double B = p.y - l1.y;
    double C = l2.x - l1.x;
    double D = l2.y - l1.y;

    double dot = A * C + B * D;
    double len_sq = C * C + D * D;
    double param = dot / len_sq;

    double xx, yy;

    if (param < 0 || (l1.x == l2.x && l1.y == l2.y)) {
        xx = l1.x;
        yy = l1.y;
    }
    else if (param > 1) {
        xx = l2.x;
        yy = l2.y;
    }
    else {
        xx = l1.x + param * C;
        yy = l1.y + param * D;
    }

    return MKMetersBetweenMapPoints(p, MKMapPointMake(xx, yy));
}

এটি আমার পক্ষে ভালভাবে কাজ করছে বলে মনে হচ্ছে। রূপান্তর করার জন্য ধন্যবাদ।
গ্রেগির

এটি লক্ষণীয়, এটি (xx, yy) নিকটতম পয়েন্টের অবস্থান। আমি আপনার কোডটি কিছুটা সম্পাদনা করেছি, সুতরাং এটি পয়েন্ট এবং দূরত্ব, রিফ্যাক্টর নামগুলি উভয়ই ফিরিয়ে দেয় যাতে তারা কী কী তা বর্ণনা করে এবং উদাহরণটি সরবরাহ করে: stackoverflow.com/a/28028023/849616
লাইভ

20

গণিতে

এটি বিভাগটির একটি প্যারাম্যাট্রিক বিবরণ ব্যবহার করে এবং বিন্দুটিকে সেগমেন্ট দ্বারা নির্ধারিত লাইনে প্রজেক্ট করে। বিভাগটিতে প্যারামিটারটি 0 থেকে 1 পর্যন্ত চলে যাওয়ার পরে, যদি প্রক্ষেপণটি এই সীমাটির বাইরে থাকে, আমরা বিভাগটির সরলরেখার স্বাভাবিকের পরিবর্তে, সংশ্লিষ্ট এনপয়েন্টের সাথে দূরত্বটি গণনা করি।

Clear["Global`*"];
 distance[{start_, end_}, pt_] := 
   Module[{param},
   param = ((pt - start).(end - start))/Norm[end - start]^2; (*parameter. the "."
                                                       here means vector product*)

   Which[
    param < 0, EuclideanDistance[start, pt],                 (*If outside bounds*)
    param > 1, EuclideanDistance[end, pt],
    True, EuclideanDistance[pt, start + param (end - start)] (*Normal distance*)
    ]
   ];  

প্লটিং ফলাফল:

Plot3D[distance[{{0, 0}, {1, 0}}, {xp, yp}], {xp, -1, 2}, {yp, -1, 2}]

বিকল্প পাঠ

কাটফট দূরত্বের চেয়ে নিকটবর্তী সেই পয়েন্টগুলি প্লট করুন :

বিকল্প পাঠ

কনট্যুর প্লট:

এখানে চিত্র বর্ণনা লিখুন


11

আরে, আমি গতকাল এটি লিখেছিলাম। এটি অ্যাকশনসক্রিপ্ট 3.0.০ এ রয়েছে যা মূলত জাভাস্ক্রিপ্ট, যদিও আপনার একই পয়েন্ট বর্গ নাও থাকতে পারে।

//st = start of line segment
//b = the line segment (as in: st + b = end of line segment)
//pt = point to test
//Returns distance from point to line segment.  
//Note: nearest point on the segment to the test point is right there if we ever need it
public static function linePointDist( st:Point, b:Point, pt:Point ):Number
{
    var nearestPt:Point; //closest point on seqment to pt

    var keyDot:Number = dot( b, pt.subtract( st ) ); //key dot product
    var bLenSq:Number = dot( b, b ); //Segment length squared

    if( keyDot <= 0 )  //pt is "behind" st, use st
    {
        nearestPt = st  
    }
    else if( keyDot >= bLenSq ) //pt is "past" end of segment, use end (notice we are saving twin sqrts here cuz)
    {
        nearestPt = st.add(b);
    }
    else //pt is inside segment, reuse keyDot and bLenSq to get percent of seqment to move in to find closest point
    {
        var keyDotToPctOfB:Number = keyDot/bLenSq; //REM dot product comes squared
        var partOfB:Point = new Point( b.x * keyDotToPctOfB, b.y * keyDotToPctOfB );
        nearestPt = st.add(partOfB);
    }

    var dist:Number = (pt.subtract(nearestPt)).length;

    return dist;
}

এছাড়াও, সমস্যার একটি চমত্কার সম্পূর্ণ এবং পঠনযোগ্য আলোচনা এখানে আছে: নোটজট ডট কম


ধন্যবাদ - আমি ঠিক এই ধরণের কোডের সন্ধান করছিলাম। আমি নীচে আমার নিজের উত্তরটি পোস্ট করেছি, যেহেতু আমি এমন কিছু একসাথে রাখতে সক্ষম হয়েছি যা বর্তমান-যুগের ব্রাউজার-জাভাস্ক্রিপ্টে কাজ করে, তবে আমি আপনার উত্তরটিকে স্বীকৃত হিসাবে চিহ্নিত করেছি কারণ এটি সহজ, লিখিত, সহজেই বোঝা যায়, এবং অনেক প্রশংসা।
এলি কোর্টরাইট

এটি কি বিন্দু-পদ্ধতি অনুপস্থিত? যাই হোক না কেন, গণনা করা সহজ: vec1.x * vec2.x + vec1.y * vec2.y
কোয়ানো

11

অলসতার জন্য, এখানে আমার উপরে @ গ্রামড্রিগের সমাধানের উদ্দেশ্য-সি বন্দরটি রয়েছে:

CGFloat sqr(CGFloat x) { return x*x; }
CGFloat dist2(CGPoint v, CGPoint w) { return sqr(v.x - w.x) + sqr(v.y - w.y); }
CGFloat distanceToSegmentSquared(CGPoint p, CGPoint v, CGPoint w)
{
    CGFloat l2 = dist2(v, w);
    if (l2 == 0.0f) return dist2(p, v);

    CGFloat t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2;
    if (t < 0.0f) return dist2(p, v);
    if (t > 1.0f) return dist2(p, w);
    return dist2(p, CGPointMake(v.x + t * (w.x - v.x), v.y + t * (w.y - v.y)));
}
CGFloat distanceToSegment(CGPoint point, CGPoint segmentPointV, CGPoint segmentPointW)
{
    return sqrtf(distanceToSegmentSquared(point, segmentPointV, segmentPointW));
}

আমি এই লাইন থেকে 'নান' ফিরে পেয়েছি। কোন ধারণা কেন? (উপায় দ্বারা return dist2(p, CGPointMake(v.x + t * (w.x - v.x), v.y + t * (w.y - v.y)))
ওবজ

sqrtf () x স্কোয়ার করছে, এর বর্গমূল পাচ্ছে না
সেনসফুল

@ সেনসফুল আপনি নিশ্চিত বলতে চাইছেন না। sqrtf বর্গমূল হয়। বিকাশকারী.অ্যাপল.
com

@ ওল্ফ: উপরের কোডের প্রথম লাইনে একবার দেখুন। এটি পদ্ধতিটি সংজ্ঞায়িত করে sqrtf(x) = x*x
সেনসফুল

@ সংবেদনশীল ধন্যবাদ, ভুল অপারেশন করার পরিবর্তে এটির ভুল নামকরণ করা হয়েছিল।
অহলফ

10

অজগর এ কোডিং প্রতিহত করতে পারেনি :)

from math import sqrt, fabs
def pdis(a, b, c):
    t = b[0]-a[0], b[1]-a[1]           # Vector ab
    dd = sqrt(t[0]**2+t[1]**2)         # Length of ab
    t = t[0]/dd, t[1]/dd               # unit vector of ab
    n = -t[1], t[0]                    # normal unit vector to ab
    ac = c[0]-a[0], c[1]-a[1]          # vector ac
    return fabs(ac[0]*n[0]+ac[1]*n[1]) # Projection of ac to n (the minimum distance)

print pdis((1,1), (2,2), (2,0))        # Example (answer is 1.414)


দুর্গের জন্য দিতো :)

real function pdis(a, b, c)
    real, dimension(0:1), intent(in) :: a, b, c
    real, dimension(0:1) :: t, n, ac
    real :: dd
    t = b - a                          ! Vector ab
    dd = sqrt(t(0)**2+t(1)**2)         ! Length of ab
    t = t/dd                           ! unit vector of ab
    n = (/-t(1), t(0)/)                ! normal unit vector to ab
    ac = c - a                         ! vector ac
    pdis = abs(ac(0)*n(0)+ac(1)*n(1))  ! Projection of ac to n (the minimum distance)
end function pdis


program test
    print *, pdis((/1.0,1.0/), (/2.0,2.0/), (/2.0,0.0/))   ! Example (answer is 1.414)
end program test

10
এটি কি সেগমেন্টের পরিবর্তে কোনও বিন্দুর দূরত্বকে একটি লাইনের সাথে গণনা করছে ?
balint.miklos

6
এটি ভাগ করে রেখাংশটির দূরত্বটি সেগমেন্টের নয়, সেগমেন্টের কাছে।
গ্রুমড্রিগ

12
এটি কাজ করে না বলে মনে হচ্ছে। যদি আপনি (0,0) এবং (5,0) এর একটি অংশ পেয়ে থাকেন এবং পয়েন্টটির (7,0) বিপরীতে চেষ্টা করেন তবে এটি 0 ফিরে আসবে, যা সত্য নয়। দূরত্বটি 2 হওয়া উচিত
কোয়ানো

8
তিনি সে ক্ষেত্রে বিষয়টি বিবেচনা করতে ব্যর্থ হয়েছেন যেখানে বিভাগ থেকে বিন্দুটির প্রক্ষেপণ এ থেকে বি পর্যন্ত বিরতির বাইরে রয়েছে is প্রশ্নকারীর এটি হতে পারে, তবে তিনি যা চেয়েছিলেন তা নয়।
phkahler

5
এটি মূলত যা বলা হয়েছিল তা নয়।
সাম্বাত্যোন

10

গ্রামড্রিগের দ্রবণ থেকে আরও একটি সম্পূর্ণ বানান এখানে। এই সংস্করণটি নিকটতম বিন্দুটিও ফিরে দেয়।

#include "stdio.h"
#include "math.h"

class Vec2
{
public:
    float _x;
    float _y;

    Vec2()
    {
        _x = 0;
        _y = 0;
    }

    Vec2( const float x, const float y )
    {
        _x = x;
        _y = y;
    }

    Vec2 operator+( const Vec2 &v ) const
    {
        return Vec2( this->_x + v._x, this->_y + v._y );
    }

    Vec2 operator-( const Vec2 &v ) const
    {
        return Vec2( this->_x - v._x, this->_y - v._y );
    }

    Vec2 operator*( const float f ) const
    {
        return Vec2( this->_x * f, this->_y * f );
    }

    float DistanceToSquared( const Vec2 p ) const
    {
        const float dX = p._x - this->_x;
        const float dY = p._y - this->_y;

        return dX * dX + dY * dY;
    }

    float DistanceTo( const Vec2 p ) const
    {
        return sqrt( this->DistanceToSquared( p ) );
    }

    float DotProduct( const Vec2 p ) const
    {
        return this->_x * p._x + this->_y * p._y;
    }
};

// return minimum distance between line segment vw and point p, and the closest point on the line segment, q
float DistanceFromLineSegmentToPoint( const Vec2 v, const Vec2 w, const Vec2 p, Vec2 * const q )
{
    const float distSq = v.DistanceToSquared( w ); // i.e. |w-v|^2 ... avoid a sqrt
    if ( distSq == 0.0 )
    {
        // v == w case
        (*q) = v;

        return v.DistanceTo( p );
    }

    // consider the line extending the segment, parameterized as v + t (w - v)
    // we find projection of point p onto the line
    // it falls where t = [(p-v) . (w-v)] / |w-v|^2

    const float t = ( p - v ).DotProduct( w - v ) / distSq;
    if ( t < 0.0 )
    {
        // beyond the v end of the segment
        (*q) = v;

        return v.DistanceTo( p );
    }
    else if ( t > 1.0 )
    {
        // beyond the w end of the segment
        (*q) = w;

        return w.DistanceTo( p );
    }

    // projection falls on the segment
    const Vec2 projection = v + ( ( w - v ) * t );

    (*q) = projection;

    return p.DistanceTo( projection );
}

float DistanceFromLineSegmentToPoint( float segmentX1, float segmentY1, float segmentX2, float segmentY2, float pX, float pY, float *qX, float *qY )
{
    Vec2 q;

    float distance = DistanceFromLineSegmentToPoint( Vec2( segmentX1, segmentY1 ), Vec2( segmentX2, segmentY2 ), Vec2( pX, pY ), &q );

    (*qX) = q._x;
    (*qY) = q._y;

    return distance;
}

void TestDistanceFromLineSegmentToPoint( float segmentX1, float segmentY1, float segmentX2, float segmentY2, float pX, float pY )
{
    float qX;
    float qY;
    float d = DistanceFromLineSegmentToPoint( segmentX1, segmentY1, segmentX2, segmentY2, pX, pY, &qX, &qY );
    printf( "line segment = ( ( %f, %f ), ( %f, %f ) ), p = ( %f, %f ), distance = %f, q = ( %f, %f )\n",
            segmentX1, segmentY1, segmentX2, segmentY2, pX, pY, d, qX, qY );
}

void TestDistanceFromLineSegmentToPoint()
{
    TestDistanceFromLineSegmentToPoint( 0, 0, 1, 1, 1, 0 );
    TestDistanceFromLineSegmentToPoint( 0, 0, 20, 10, 5, 4 );
    TestDistanceFromLineSegmentToPoint( 0, 0, 20, 10, 30, 15 );
    TestDistanceFromLineSegmentToPoint( 0, 0, 20, 10, -30, 15 );
    TestDistanceFromLineSegmentToPoint( 0, 0, 10, 0, 5, 1 );
    TestDistanceFromLineSegmentToPoint( 0, 0, 0, 10, 1, 5 );
}

এই পোস্ট করার জন্য ধন্যবাদ। খুব ভাল কাঠামোগত এবং মন্তব্য করা হয়েছে এবং ফর্ম্যাট করা হয়েছে - আমাকে সি ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++> আমি এটি সম্পর্কিত সি # সংস্করণ তৈরি করতে ব্যবহার করেছি, যা আমি এখানে এখানে পোস্ট করেছি।
রেনিপেট

10

আর্টজ্যান্টস ব্যবহার করে একটি লাইন সমাধান:

ধারণা সরানো হয় একটি (0, 0) এবং ঘোরান ত্রিভুজ ঘড়ির কাঁটার করতে সি এক্স অক্ষের উপর শুয়ে, যখন এই ঘটতে, কসম দূরত্ব হবে।

  1. a কোণ = আতান (সাই - আই, সেক্স - এক্স);
  2. b কোণ = আতান (লিখেছেন - আয়, বিএক্স - এক্স);
  3. এবি দৈর্ঘ্য = স্কয়ার্ট ((বিএক্স - এক্স) ^ 2 + (লিখেছেন - আয়) ^ 2)
  4. দ্বারা = পাপ (অংল - অংল) * এবিলেংথ

সি শার্প

public double Distance(Point a, Point b, Point c)
{
    // normalize points
    Point cn = new Point(c.X - a.X, c.Y - a.Y);
    Point bn = new Point(b.X - a.X, b.Y - a.Y);

    double angle = Math.Atan2(bn.Y, bn.X) - Math.Atan2(cn.Y, cn.X);
    double abLength = Math.Sqrt(bn.X*bn.X + bn.Y*bn.Y);

    return Math.Sin(angle)*abLength;
}

একটি লাইন সি # (এসকিউএল রূপান্তর করতে)

double distance = Math.Sin(Math.Atan2(b.Y - a.Y, b.X - a.X) - Math.Atan2(c.Y - a.Y, c.X - a.X)) * Math.Sqrt((b.X - a.X) * (b.X - a.X) + (b.Y - a.Y) * (b.Y - a.Y))

7

উপরের গ্রমড্রিগের উত্তরের এই পরিবর্তনটি বিবেচনা করুন। অনেক সময় আপনি দেখতে পাবেন যে ভাসমান পয়েন্ট অসম্পূর্ণতা সমস্যার কারণ হতে পারে। আমি নীচের সংস্করণে ডাবল ব্যবহার করছি, তবে আপনি সহজেই ফ্লোটে পরিবর্তন করতে পারবেন। গুরুত্বপূর্ণ অংশটি হ'ল এটি "opালু" পরিচালনা করতে একটি অ্যাপসিলন ব্যবহার করে। তদ্ব্যতীত, আপনি অনেক সময় জানতে চান যে মোড়টি কখন ঘটেছে, বা এটি আদৌ ঘটেছে কিনা। যদি ফেরত টি <0.0 বা> 1.0 হয় তবে কোনও সংঘর্ষ ঘটেনি। যাইহোক, কোনও সংঘর্ষ না ঘটলেও, অনেক সময় আপনি জানতে চাইবেন যে সেগমেন্টের নিকটতম নিকটস্থ বিন্দুটি P কোথায় এবং সুতরাং আমি এই অবস্থানটি ফিরে আসতে qx এবং qy ব্যবহার করি।

double PointSegmentDistanceSquared( double px, double py,
                                    double p1x, double p1y,
                                    double p2x, double p2y,
                                    double& t,
                                    double& qx, double& qy)
{
    static const double kMinSegmentLenSquared = 0.00000001;  // adjust to suit.  If you use float, you'll probably want something like 0.000001f
    static const double kEpsilon = 1.0E-14;  // adjust to suit.  If you use floats, you'll probably want something like 1E-7f
    double dx = p2x - p1x;
    double dy = p2y - p1y;
    double dp1x = px - p1x;
    double dp1y = py - p1y;
    const double segLenSquared = (dx * dx) + (dy * dy);
    if (segLenSquared >= -kMinSegmentLenSquared && segLenSquared <= kMinSegmentLenSquared)
    {
        // segment is a point.
        qx = p1x;
        qy = p1y;
        t = 0.0;
        return ((dp1x * dp1x) + (dp1y * dp1y));
    }
    else
    {
        // Project a line from p to the segment [p1,p2].  By considering the line
        // extending the segment, parameterized as p1 + (t * (p2 - p1)),
        // we find projection of point p onto the line. 
        // It falls where t = [(p - p1) . (p2 - p1)] / |p2 - p1|^2
        t = ((dp1x * dx) + (dp1y * dy)) / segLenSquared;
        if (t < kEpsilon)
        {
            // intersects at or to the "left" of first segment vertex (p1x, p1y).  If t is approximately 0.0, then
            // intersection is at p1.  If t is less than that, then there is no intersection (i.e. p is not within
            // the 'bounds' of the segment)
            if (t > -kEpsilon)
            {
                // intersects at 1st segment vertex
                t = 0.0;
            }
            // set our 'intersection' point to p1.
            qx = p1x;
            qy = p1y;
            // Note: If you wanted the ACTUAL intersection point of where the projected lines would intersect if
            // we were doing PointLineDistanceSquared, then qx would be (p1x + (t * dx)) and qy would be (p1y + (t * dy)).
        }
        else if (t > (1.0 - kEpsilon))
        {
            // intersects at or to the "right" of second segment vertex (p2x, p2y).  If t is approximately 1.0, then
            // intersection is at p2.  If t is greater than that, then there is no intersection (i.e. p is not within
            // the 'bounds' of the segment)
            if (t < (1.0 + kEpsilon))
            {
                // intersects at 2nd segment vertex
                t = 1.0;
            }
            // set our 'intersection' point to p2.
            qx = p2x;
            qy = p2y;
            // Note: If you wanted the ACTUAL intersection point of where the projected lines would intersect if
            // we were doing PointLineDistanceSquared, then qx would be (p1x + (t * dx)) and qy would be (p1y + (t * dy)).
        }
        else
        {
            // The projection of the point to the point on the segment that is perpendicular succeeded and the point
            // is 'within' the bounds of the segment.  Set the intersection point as that projected point.
            qx = p1x + (t * dx);
            qy = p1y + (t * dy);
        }
        // return the squared distance from p to the intersection point.  Note that we return the squared distance
        // as an optimization because many times you just need to compare relative distances and the squared values
        // works fine for that.  If you want the ACTUAL distance, just take the square root of this value.
        double dpqx = px - qx;
        double dpqy = py - qy;
        return ((dpqx * dpqx) + (dpqy * dpqy));
    }
}

6

আমি ধরে নিচ্ছি আপনি এটি সন্ধান করতে চান কমতমবিন্দু এবং একটি লাইন বিভাগের মধ্যে দূরত্ব; এটি করার জন্য, আপনাকে এমন লাইন (লাইনএ) সন্ধান করতে হবে যা আপনার লাইন বিভাগের (লাইনবি) লম্ব হয় যা আপনার পয়েন্ট দিয়ে যায়, সেই রেখা (লাইনএ) এবং আপনার রেখার মধ্যবর্তী ছেদটি নির্ধারণ করে যা আপনার লাইন বিভাগের (লাইনবি) মধ্য দিয়ে যায় ; যদি সেই বিন্দুটি আপনার লাইন বিভাগের দুটি পয়েন্টের মধ্যে হয়, তবে দূরত্বটি আপনার পয়েন্ট এবং বিন্দুর মধ্যবর্তী দূরত্ব যা আপনি সন্ধান করেছেন যা লাইনএ এবং লাইনবি এর ছেদটি; যদি বিন্দুটি আপনার লাইন বিভাগের দুটি পয়েন্টের মধ্যে না হয়, আপনাকে আপনার পয়েন্ট এবং লাইন বিভাগের দুটি প্রান্তের কাছাকাছি অবস্থান করতে হবে; এটি বিন্দু এবং লাইন বিভাগের দুটি পয়েন্টের মধ্যে বর্গাকার দূরত্ব (বর্গমূলকে এড়াতে) নিয়ে সহজেই করা যায়; যেটি নিকটে, সেইটির বর্গমূল নিন।


6

গ্রামড্রিগের সি ++ / জাভাস্ক্রিপ্ট প্রয়োগটি আমার পক্ষে খুব কার্যকর ছিল, তাই আমি একটি পাইথন প্রত্যক্ষ বন্দর সরবরাহ করেছি যা আমি ব্যবহার করছি। সম্পূর্ণ কোড এখানে

class Point(object):
  def __init__(self, x, y):
    self.x = float(x)
    self.y = float(y)

def square(x):
  return x * x

def distance_squared(v, w):
  return square(v.x - w.x) + square(v.y - w.y)

def distance_point_segment_squared(p, v, w):
  # Segment length squared, |w-v|^2
  d2 = distance_squared(v, w) 
  if d2 == 0: 
    # v == w, return distance to v
    return distance_squared(p, v)
  # Consider the line extending the segment, parameterized as v + t (w - v).
  # We find projection of point p onto the line.
  # It falls where t = [(p-v) . (w-v)] / |w-v|^2
  t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / d2;
  if t < 0:
    # Beyond v end of the segment
    return distance_squared(p, v)
  elif t > 1.0:
    # Beyond w end of the segment
    return distance_squared(p, w)
  else:
    # Projection falls on the segment.
    proj = Point(v.x + t * (w.x - v.x), v.y + t * (w.y - v.y))
    # print proj.x, proj.y
    return distance_squared(p, proj)

5

মতলব কোড, বিল্ট ইন ইন "স্ব-পরীক্ষা" সহ যদি তারা কোনও যুক্তি ছাড়াই ফাংশনটি কল করে:

function r = distPointToLineSegment( xy0, xy1, xyP )
% r = distPointToLineSegment( xy0, xy1, xyP )

if( nargin < 3 )
    selfTest();
    r=0;
else
    vx = xy0(1)-xyP(1);
    vy = xy0(2)-xyP(2);
    ux = xy1(1)-xy0(1);
    uy = xy1(2)-xy0(2);
    lenSqr= (ux*ux+uy*uy);
    detP= -vx*ux + -vy*uy;

    if( detP < 0 )
        r = norm(xy0-xyP,2);
    elseif( detP > lenSqr )
        r = norm(xy1-xyP,2);
    else
        r = abs(ux*vy-uy*vx)/sqrt(lenSqr);
    end
end


    function selfTest()
        %#ok<*NASGU>
        disp(['invalid args, distPointToLineSegment running (recursive)  self-test...']);

        ptA = [1;1]; ptB = [-1;-1];
        ptC = [1/2;1/2];  % on the line
        ptD = [-2;-1.5];  % too far from line segment
        ptE = [1/2;0];    % should be same as perpendicular distance to line
        ptF = [1.5;1.5];      % along the A-B but outside of the segment

        distCtoAB = distPointToLineSegment(ptA,ptB,ptC)
        distDtoAB = distPointToLineSegment(ptA,ptB,ptD)
        distEtoAB = distPointToLineSegment(ptA,ptB,ptE)
        distFtoAB = distPointToLineSegment(ptA,ptB,ptF)
        figure(1); clf;
        circle = @(x, y, r, c) rectangle('Position', [x-r, y-r, 2*r, 2*r], ...
            'Curvature', [1 1], 'EdgeColor', c);
        plot([ptA(1) ptB(1)],[ptA(2) ptB(2)],'r-x'); hold on;
        plot(ptC(1),ptC(2),'b+'); circle(ptC(1),ptC(2), 0.5e-1, 'b');
        plot(ptD(1),ptD(2),'g+'); circle(ptD(1),ptD(2), distDtoAB, 'g');
        plot(ptE(1),ptE(2),'k+'); circle(ptE(1),ptE(2), distEtoAB, 'k');
        plot(ptF(1),ptF(2),'m+'); circle(ptF(1),ptF(2), distFtoAB, 'm');
        hold off;
        axis([-3 3 -3 3]); axis equal;
    end

end

ধন্যবাদ, এই মতলব কোডটি SEGMENT রেখার সবচেয়ে সংক্ষিপ্ত দূরত্ব গণনা করে এবং সেগমেন্টটি যে সীমারেখায় রয়েছে তার অসীম রেখার দূরত্ব নয়।
রুডলফ মেইজিং

4

এবং এখন আমার সমাধানও ...... (জাভাস্ক্রিপ্ট)

এটি খুব দ্রুত কারণ আমি কোনও ম্যাথ.প্যাও ফাংশন এড়াতে চেষ্টা করি।

আপনি দেখতে পাচ্ছেন, ফাংশনটির শেষে আমার লাইনটির দূরত্ব রয়েছে।

কোডটি লিব থেকে http://www.draw2d.org/ographiciti/jsdoc/#!/example

/**
 * Static util function to determine is a point(px,py) on the line(x1,y1,x2,y2)
 * A simple hit test.
 * 
 * @return {boolean}
 * @static
 * @private
 * @param {Number} coronaWidth the accepted corona for the hit test
 * @param {Number} X1 x coordinate of the start point of the line
 * @param {Number} Y1 y coordinate of the start point of the line
 * @param {Number} X2 x coordinate of the end point of the line
 * @param {Number} Y2 y coordinate of the end point of the line
 * @param {Number} px x coordinate of the point to test
 * @param {Number} py y coordinate of the point to test
 **/
graphiti.shape.basic.Line.hit= function( coronaWidth, X1, Y1,  X2,  Y2, px, py)
{
  // Adjust vectors relative to X1,Y1
  // X2,Y2 becomes relative vector from X1,Y1 to end of segment
  X2 -= X1;
  Y2 -= Y1;
  // px,py becomes relative vector from X1,Y1 to test point
  px -= X1;
  py -= Y1;
  var dotprod = px * X2 + py * Y2;
  var projlenSq;
  if (dotprod <= 0.0) {
      // px,py is on the side of X1,Y1 away from X2,Y2
      // distance to segment is length of px,py vector
      // "length of its (clipped) projection" is now 0.0
      projlenSq = 0.0;
  } else {
      // switch to backwards vectors relative to X2,Y2
      // X2,Y2 are already the negative of X1,Y1=>X2,Y2
      // to get px,py to be the negative of px,py=>X2,Y2
      // the dot product of two negated vectors is the same
      // as the dot product of the two normal vectors
      px = X2 - px;
      py = Y2 - py;
      dotprod = px * X2 + py * Y2;
      if (dotprod <= 0.0) {
          // px,py is on the side of X2,Y2 away from X1,Y1
          // distance to segment is length of (backwards) px,py vector
          // "length of its (clipped) projection" is now 0.0
          projlenSq = 0.0;
      } else {
          // px,py is between X1,Y1 and X2,Y2
          // dotprod is the length of the px,py vector
          // projected on the X2,Y2=>X1,Y1 vector times the
          // length of the X2,Y2=>X1,Y1 vector
          projlenSq = dotprod * dotprod / (X2 * X2 + Y2 * Y2);
      }
  }
    // Distance to line is now the length of the relative point
    // vector minus the length of its projection onto the line
    // (which is zero if the projection falls outside the range
    //  of the line segment).
    var lenSq = px * px + py * py - projlenSq;
    if (lenSq < 0) {
        lenSq = 0;
    }
    return Math.sqrt(lenSq)<coronaWidth;
};

4

টি-স্কোলে কোডড

বিন্দুটি (@px, @py) এবং লাইন বিভাগটি (@ ম্যাক্স, @ ই) থেকে (@ বিএক্স, @ বি) অবধি চলে

create function fn_sqr (@NumberToSquare decimal(18,10)) 
returns decimal(18,10)
as 
begin
    declare @Result decimal(18,10)
    set @Result = @NumberToSquare * @NumberToSquare
    return @Result
end
go

create function fn_Distance(@ax decimal (18,10) , @ay decimal (18,10), @bx decimal(18,10),  @by decimal(18,10)) 
returns decimal(18,10)
as
begin
    declare @Result decimal(18,10)
    set @Result = (select dbo.fn_sqr(@ax - @bx) + dbo.fn_sqr(@ay - @by) )
    return @Result
end
go

create function fn_DistanceToSegmentSquared(@px decimal(18,10), @py decimal(18,10), @ax decimal(18,10), @ay decimal(18,10), @bx decimal(18,10), @by decimal(18,10)) 
returns decimal(18,10)
as 
begin
    declare @l2 decimal(18,10)
    set @l2 = (select dbo.fn_Distance(@ax, @ay, @bx, @by))
    if @l2 = 0
        return dbo.fn_Distance(@px, @py, @ax, @ay)
    declare @t decimal(18,10)
    set @t = ((@px - @ax) * (@bx - @ax) + (@py - @ay) * (@by - @ay)) / @l2
    if (@t < 0) 
        return dbo.fn_Distance(@px, @py, @ax, @ay);
    if (@t > 1) 
        return dbo.fn_Distance(@px, @py, @bx, @by);
    return dbo.fn_Distance(@px, @py,  @ax + @t * (@bx - @ax),  @ay + @t * (@by - @ay))
end
go

create function fn_DistanceToSegment(@px decimal(18,10), @py decimal(18,10), @ax decimal(18,10), @ay decimal(18,10), @bx decimal(18,10), @by decimal(18,10)) 
returns decimal(18,10)
as 
begin
    return sqrt(dbo.fn_DistanceToSegmentSquared(@px, @py , @ax , @ay , @bx , @by ))
end
go

--example execution for distance from a point at (6,1) to line segment that runs from (4,2) to (2,1)
select dbo.fn_DistanceToSegment(6, 1, 4, 2, 2, 1) 
--result = 2.2360679775

--example execution for distance from a point at (-3,-2) to line segment that runs from (0,-2) to (-2,1)
select dbo.fn_DistanceToSegment(-3, -2, 0, -2, -2, 1) 
--result = 2.4961508830

--example execution for distance from a point at (0,-2) to line segment that runs from (0,-2) to (-2,1)
select dbo.fn_DistanceToSegment(0,-2, 0, -2, -2, 1) 
--result = 0.0000000000

4

দেখে মনে হচ্ছে স্ট্যাকওভারফ্লোতে থাকা প্রত্যেকেরই একটি উত্তর অবদান রেখেছে (এখনও অবধি 23 টি উত্তর), তাই এখানে সি # এর জন্য আমার অবদান রয়েছে। এটি বেশিরভাগই এম। কাটজের উত্তরের উপর ভিত্তি করে তৈরি, যা ঘুরে ফিরে গ্রুমড্রিগের উত্তরের উপর ভিত্তি করে তৈরি হয়।

   public struct MyVector
   {
      private readonly double _x, _y;


      // Constructor
      public MyVector(double x, double y)
      {
         _x = x;
         _y = y;
      }


      // Distance from this point to another point, squared
      private double DistanceSquared(MyVector otherPoint)
      {
         double dx = otherPoint._x - this._x;
         double dy = otherPoint._y - this._y;
         return dx * dx + dy * dy;
      }


      // Find the distance from this point to a line segment (which is not the same as from this 
      //  point to anywhere on an infinite line). Also returns the closest point.
      public double DistanceToLineSegment(MyVector lineSegmentPoint1, MyVector lineSegmentPoint2,
                                          out MyVector closestPoint)
      {
         return Math.Sqrt(DistanceToLineSegmentSquared(lineSegmentPoint1, lineSegmentPoint2, 
                          out closestPoint));
      }


      // Same as above, but avoid using Sqrt(), saves a new nanoseconds in cases where you only want 
      //  to compare several distances to find the smallest or largest, but don't need the distance
      public double DistanceToLineSegmentSquared(MyVector lineSegmentPoint1, 
                                              MyVector lineSegmentPoint2, out MyVector closestPoint)
      {
         // Compute length of line segment (squared) and handle special case of coincident points
         double segmentLengthSquared = lineSegmentPoint1.DistanceSquared(lineSegmentPoint2);
         if (segmentLengthSquared < 1E-7f)  // Arbitrary "close enough for government work" value
         {
            closestPoint = lineSegmentPoint1;
            return this.DistanceSquared(closestPoint);
         }

         // Use the magic formula to compute the "projection" of this point on the infinite line
         MyVector lineSegment = lineSegmentPoint2 - lineSegmentPoint1;
         double t = (this - lineSegmentPoint1).DotProduct(lineSegment) / segmentLengthSquared;

         // Handle the two cases where the projection is not on the line segment, and the case where 
         //  the projection is on the segment
         if (t <= 0)
            closestPoint = lineSegmentPoint1;
         else if (t >= 1)
            closestPoint = lineSegmentPoint2;
         else 
            closestPoint = lineSegmentPoint1 + (lineSegment * t);
         return this.DistanceSquared(closestPoint);
      }


      public double DotProduct(MyVector otherVector)
      {
         return this._x * otherVector._x + this._y * otherVector._y;
      }

      public static MyVector operator +(MyVector leftVector, MyVector rightVector)
      {
         return new MyVector(leftVector._x + rightVector._x, leftVector._y + rightVector._y);
      }

      public static MyVector operator -(MyVector leftVector, MyVector rightVector)
      {
         return new MyVector(leftVector._x - rightVector._x, leftVector._y - rightVector._y);
      }

      public static MyVector operator *(MyVector aVector, double aScalar)
      {
         return new MyVector(aVector._x * aScalar, aVector._y * aScalar);
      }

      // Added using ReSharper due to CodeAnalysis nagging

      public bool Equals(MyVector other)
      {
         return _x.Equals(other._x) && _y.Equals(other._y);
      }

      public override bool Equals(object obj)
      {
         if (ReferenceEquals(null, obj)) return false;
         return obj is MyVector && Equals((MyVector) obj);
      }

      public override int GetHashCode()
      {
         unchecked
         {
            return (_x.GetHashCode()*397) ^ _y.GetHashCode();
         }
      }

      public static bool operator ==(MyVector left, MyVector right)
      {
         return left.Equals(right);
      }

      public static bool operator !=(MyVector left, MyVector right)
      {
         return !left.Equals(right);
      }
   }

এবং এখানে একটি সামান্য পরীক্ষা প্রোগ্রাম।

   public static class JustTesting
   {
      public static void Main()
      {
         Stopwatch stopwatch = new Stopwatch();
         stopwatch.Start();

         for (int i = 0; i < 10000000; i++)
         {
            TestIt(1, 0, 0, 0, 1, 1, 0.70710678118654757);
            TestIt(5, 4, 0, 0, 20, 10, 1.3416407864998738);
            TestIt(30, 15, 0, 0, 20, 10, 11.180339887498949);
            TestIt(-30, 15, 0, 0, 20, 10, 33.541019662496844);
            TestIt(5, 1, 0, 0, 10, 0, 1.0);
            TestIt(1, 5, 0, 0, 0, 10, 1.0);
         }

         stopwatch.Stop();
         TimeSpan timeSpan = stopwatch.Elapsed;
      }


      private static void TestIt(float aPointX, float aPointY, 
                                 float lineSegmentPoint1X, float lineSegmentPoint1Y, 
                                 float lineSegmentPoint2X, float lineSegmentPoint2Y, 
                                 double expectedAnswer)
      {
         // Katz
         double d1 = DistanceFromPointToLineSegment(new MyVector(aPointX, aPointY), 
                                              new MyVector(lineSegmentPoint1X, lineSegmentPoint1Y), 
                                              new MyVector(lineSegmentPoint2X, lineSegmentPoint2Y));
         Debug.Assert(d1 == expectedAnswer);

         /*
         // Katz using squared distance
         double d2 = DistanceFromPointToLineSegmentSquared(new MyVector(aPointX, aPointY), 
                                              new MyVector(lineSegmentPoint1X, lineSegmentPoint1Y), 
                                              new MyVector(lineSegmentPoint2X, lineSegmentPoint2Y));
         Debug.Assert(Math.Abs(d2 - expectedAnswer * expectedAnswer) < 1E-7f);
          */

         /*
         // Matti (optimized)
         double d3 = FloatVector.DistanceToLineSegment(new PointF(aPointX, aPointY), 
                                                new PointF(lineSegmentPoint1X, lineSegmentPoint1Y), 
                                                new PointF(lineSegmentPoint2X, lineSegmentPoint2Y));
         Debug.Assert(Math.Abs(d3 - expectedAnswer) < 1E-7f);
          */
      }

      private static double DistanceFromPointToLineSegment(MyVector aPoint, 
                                             MyVector lineSegmentPoint1, MyVector lineSegmentPoint2)
      {
         MyVector closestPoint;  // Not used
         return aPoint.DistanceToLineSegment(lineSegmentPoint1, lineSegmentPoint2, 
                                             out closestPoint);
      }

      private static double DistanceFromPointToLineSegmentSquared(MyVector aPoint, 
                                             MyVector lineSegmentPoint1, MyVector lineSegmentPoint2)
      {
         MyVector closestPoint;  // Not used
         return aPoint.DistanceToLineSegmentSquared(lineSegmentPoint1, lineSegmentPoint2, 
                                                    out closestPoint);
      }
   }

আপনি দেখতে পাচ্ছেন, আমি স্ক্রার্ট () পদ্ধতি এবং সাধারণ সংস্করণ এড়ানো সংস্করণটি ব্যবহার করার মধ্যে পার্থক্যটি পরিমাপ করার চেষ্টা করেছি। আমার পরীক্ষাগুলি ইঙ্গিত দেয় আপনি সম্ভবত প্রায় 2.5% সঞ্চয় করতে পারবেন, তবে আমি এটি সম্পর্কে নিশ্চিতও নই - বিভিন্ন পরীক্ষার রানের মধ্যে বিভিন্নতা একই মাত্রার আকারের ছিল। আমি মাত্তি দ্বারা পোস্ট করা সংস্করণটিও পরিমাপ করার চেষ্টা করেছি (প্লাস একটি সুস্পষ্ট অপ্টিমাইজেশান) এবং সেই সংস্করণটি কাটজ / গ্রুমড্রিগ কোডের উপর ভিত্তি করে সংস্করণটির চেয়ে প্রায় 4% ধীর বলে মনে হচ্ছে।

সম্পাদনা: প্রসঙ্গক্রমে, আমি এমন একটি পদ্ধতিও পরিমাপের চেষ্টা করেছি যা ক্রস প্রোডাক্ট (এবং স্কয়ার্ট ()) ব্যবহার করে অসীম রেখার (একটি লাইন বিভাগ নয়) দূরত্ব খুঁজে পায় এবং এটি প্রায় 32% দ্রুত।


3

এখানে ডিভনুলিকাসের সি ++ সংস্করণটি সি # তে রূপান্তরিত হয়েছে। আমার বাস্তবায়নের জন্য আমার ছেদ বিন্দুটি জানতে হবে এবং তার কাজটি ভালভাবে চালানোর সমাধান খুঁজে পেয়েছি।

public static bool PointSegmentDistanceSquared(PointF point, PointF lineStart, PointF lineEnd, out double distance, out PointF intersectPoint)
{
    const double kMinSegmentLenSquared = 0.00000001; // adjust to suit.  If you use float, you'll probably want something like 0.000001f
    const double kEpsilon = 1.0E-14; // adjust to suit.  If you use floats, you'll probably want something like 1E-7f
    double dX = lineEnd.X - lineStart.X;
    double dY = lineEnd.Y - lineStart.Y;
    double dp1X = point.X - lineStart.X;
    double dp1Y = point.Y - lineStart.Y;
    double segLenSquared = (dX * dX) + (dY * dY);
    double t = 0.0;

    if (segLenSquared >= -kMinSegmentLenSquared && segLenSquared <= kMinSegmentLenSquared)
    {
        // segment is a point.
        intersectPoint = lineStart;
        t = 0.0;
        distance = ((dp1X * dp1X) + (dp1Y * dp1Y));
    }
    else
    {
        // Project a line from p to the segment [p1,p2].  By considering the line
        // extending the segment, parameterized as p1 + (t * (p2 - p1)),
        // we find projection of point p onto the line. 
        // It falls where t = [(p - p1) . (p2 - p1)] / |p2 - p1|^2
        t = ((dp1X * dX) + (dp1Y * dY)) / segLenSquared;
        if (t < kEpsilon)
        {
            // intersects at or to the "left" of first segment vertex (lineStart.X, lineStart.Y).  If t is approximately 0.0, then
            // intersection is at p1.  If t is less than that, then there is no intersection (i.e. p is not within
            // the 'bounds' of the segment)
            if (t > -kEpsilon)
            {
                // intersects at 1st segment vertex
                t = 0.0;
            }
            // set our 'intersection' point to p1.
            intersectPoint = lineStart;
            // Note: If you wanted the ACTUAL intersection point of where the projected lines would intersect if
            // we were doing PointLineDistanceSquared, then intersectPoint.X would be (lineStart.X + (t * dx)) and intersectPoint.Y would be (lineStart.Y + (t * dy)).
        }
        else if (t > (1.0 - kEpsilon))
        {
            // intersects at or to the "right" of second segment vertex (lineEnd.X, lineEnd.Y).  If t is approximately 1.0, then
            // intersection is at p2.  If t is greater than that, then there is no intersection (i.e. p is not within
            // the 'bounds' of the segment)
            if (t < (1.0 + kEpsilon))
            {
                // intersects at 2nd segment vertex
                t = 1.0;
            }
            // set our 'intersection' point to p2.
            intersectPoint = lineEnd;
            // Note: If you wanted the ACTUAL intersection point of where the projected lines would intersect if
            // we were doing PointLineDistanceSquared, then intersectPoint.X would be (lineStart.X + (t * dx)) and intersectPoint.Y would be (lineStart.Y + (t * dy)).
        }
        else
        {
            // The projection of the point to the point on the segment that is perpendicular succeeded and the point
            // is 'within' the bounds of the segment.  Set the intersection point as that projected point.
            intersectPoint = new PointF((float)(lineStart.X + (t * dX)), (float)(lineStart.Y + (t * dY)));
        }
        // return the squared distance from p to the intersection point.  Note that we return the squared distance
        // as an optimization because many times you just need to compare relative distances and the squared values
        // works fine for that.  If you want the ACTUAL distance, just take the square root of this value.
        double dpqX = point.X - intersectPoint.X;
        double dpqY = point.Y - intersectPoint.Y;

        distance = ((dpqX * dpqX) + (dpqY * dpqY));
    }

    return true;
}

একটি যাদুমন্ত্র মত কাজ করে!! আমাকে অগণিত ঘন্টা বাঁচিয়েছে। অনেক ধন্যবাদ!!
স্টিভ জনসন

3

এখানে এটি সুইফ্ট ব্যবহার করছে

    /* Distance from a point (p1) to line l1 l2 */
func distanceFromPoint(p: CGPoint, toLineSegment l1: CGPoint, and l2: CGPoint) -> CGFloat {
    let A = p.x - l1.x
    let B = p.y - l1.y
    let C = l2.x - l1.x
    let D = l2.y - l1.y

    let dot = A * C + B * D
    let len_sq = C * C + D * D
    let param = dot / len_sq

    var xx, yy: CGFloat

    if param < 0 || (l1.x == l2.x && l1.y == l2.y) {
        xx = l1.x
        yy = l1.y
    } else if param > 1 {
        xx = l2.x
        yy = l2.y
    } else {
        xx = l1.x + param * C
        yy = l1.y + param * D
    }

    let dx = p.x - xx
    let dy = p.y - yy

    return sqrt(dx * dx + dy * dy)
}

3

সি শার্প

@ গ্রামড্রিগ থেকে অভিযোজিত

public static double MinimumDistanceToLineSegment(this Point p,
    Line line)
{
    var v = line.StartPoint;
    var w = line.EndPoint;

    double lengthSquared = DistanceSquared(v, w);

    if (lengthSquared == 0.0)
        return Distance(p, v);

    double t = Math.Max(0, Math.Min(1, DotProduct(p - v, w - v) / lengthSquared));
    var projection = v + t * (w - v);

    return Distance(p, projection);
}

public static double Distance(Point a, Point b)
{
    return Math.Sqrt(DistanceSquared(a, b));
}

public static double DistanceSquared(Point a, Point b)
{
    var d = a - b;
    return DotProduct(d, d);
}

public static double DotProduct(Point a, Point b)
{
    return (a.X * b.X) + (a.Y * b.Y);
}

এই কোডটি চেষ্টা করে দেখেছেন, বেশ সঠিকভাবে কাজ করছে বলে মনে হচ্ছে না। কিছু সময় ভুল দূরত্ব পেয়েছে বলে মনে হচ্ছে।
ডাব্লুডিউকে

3

একটি 2 ডি এবং 3 ডি সমাধান

ভিত্তি পরিবর্তনের বিষয়টি বিবেচনা করুন যেমন লাইন বিভাগটি হয়ে যায় (0, 0, 0)-(d, 0, 0)এবং বিন্দু হয় (u, v, 0)। সংক্ষিপ্ততম দূরত্বটি সেই বিমানটিতে ঘটে এবং তা দিয়ে দেওয়া হয়

    u ≤ 0 -> d(A, C)
0 ≤ u ≤ d -> |v|
d ≤ u     -> d(B, C)

(শেষের বিন্দুগুলির একটিতে বা সমর্থনকারী লাইনের দূরত্ব, লাইনটির প্রক্ষেপণের উপর নির্ভর করে is আইসো-দুরত্ব লোকসটি দুটি অর্ধ-বৃত্ত এবং দুটি লাইন বিভাগে তৈরি))

এখানে চিত্র বর্ণনা লিখুন

উপরের মত প্রকাশের ক্ষেত্রে, ডি বিভাগটি এবিটির দৈর্ঘ্য, এবং আপনি, v মাপকাঠি পণ্য এবং (AB এর দিকের ইউনিট ভেক্টর) এবং এসির স্কেলার পণ্য এবং (মডিউলাসের) ক্রস প্রোডাক্ট respective সুতরাং ভেক্টোরিয়ালভাবে,

AB.AC ≤ 0             -> |AC|
    0 ≤ AB.AC ≤ AB²   -> |ABxAC|/|AB|
          AB² ≤ AB.AC -> |BC|

2

নীচের ওয়েবসাইটে মতলব জিওমেট্রি টুলবক্সটি দেখুন: http://people.sc.fsu.edu/~jburkardt/m_src/geometry/geometry.html

সিআরটিএল + এফ এবং টাইপ করুন "সেগমেন্ট" লাইনের বিভাগের সম্পর্কিত ফাংশনগুলি সন্ধান করতে। "সেগমেন্ট_পয়েন্ট_ডিজ্ট_ড.এম" এবং "সেগমেন্ট_পয়েন্ট_ডিসট_ড.এম" ফাংশনগুলি আপনার প্রয়োজনীয়।

জিওমেট্রি কোডগুলি সি সংস্করণ এবং একটি সি ++ সংস্করণ এবং একটি ফোরট্র্যান version version সংস্করণ এবং একটি ফোরট্রান version৯০ সংস্করণ এবং একটি ম্যাটল্যাব সংস্করণে উপলব্ধ।


2

জোশুয়ার জাভাস্ক্রিপ্টের উপর ভিত্তি করে অটোহটকিজ সংস্করণ:

plDist(x, y, x1, y1, x2, y2) {
    A:= x - x1
    B:= y - y1
    C:= x2 - x1
    D:= y2 - y1

    dot:= A*C + B*D
    sqLen:= C*C + D*D
    param:= dot / sqLen

    if (param < 0 || ((x1 = x2) && (y1 = y2))) {
        xx:= x1
        yy:= y1
    } else if (param > 1) {
        xx:= x2
        yy:= y2
    } else {
        xx:= x1 + param*C
        yy:= y1 + param*D
    }

    dx:= x - xx
    dy:= y - yy

    return sqrt(dx*dx + dy*dy)
}

2

এখানে একটি জাভা বাস্তবায়ন দেখা যায়নি, তাই আমি জাভাস্ক্রিপ্ট ফাংশনটি জাভা কোডের গৃহীত উত্তর থেকে অনুবাদ করেছি:

static double sqr(double x) {
    return x * x;
}
static double dist2(DoublePoint v, DoublePoint w) {
    return sqr(v.x - w.x) + sqr(v.y - w.y);
}
static double distToSegmentSquared(DoublePoint p, DoublePoint v, DoublePoint w) {
    double l2 = dist2(v, w);
    if (l2 == 0) return dist2(p, v);
    double t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2;
    if (t < 0) return dist2(p, v);
    if (t > 1) return dist2(p, w);
    return dist2(p, new DoublePoint(
            v.x + t * (w.x - v.x),
            v.y + t * (w.y - v.y)
    ));
}
static double distToSegment(DoublePoint p, DoublePoint v, DoublePoint w) {
    return Math.sqrt(distToSegmentSquared(p, v, w));
}
static class DoublePoint {
    public double x;
    public double y;

    public DoublePoint(double x, double y) {
        this.x = x;
        this.y = y;
    }
}

2

ডাব্লুপিএফ সংস্করণ:

public class LineSegment
{
    private readonly Vector _offset;
    private readonly Vector _vector;

    public LineSegment(Point start, Point end)
    {
        _offset = (Vector)start;
        _vector = (Vector)(end - _offset);
    }

    public double DistanceTo(Point pt)
    {
        var v = (Vector)pt - _offset;

        // first, find a projection point on the segment in parametric form (0..1)
        var p = (v * _vector) / _vector.LengthSquared;

        // and limit it so it lays inside the segment
        p = Math.Min(Math.Max(p, 0), 1);

        // now, find the distance from that point to our point
        return (_vector * p - v).Length;
    }
}

1

কোডটি এখানে লিখে শেষ করেছি। এই কোডটি ধরে নিয়েছে যে একটি বিন্দু আকারে সংজ্ঞায়িত হয়েছে {x:5, y:7}। মনে রাখবেন যে এটি চূড়ান্ত সবচেয়ে কার্যকর উপায় নয়, তবে এটি সহজ এবং সহজ-বোঝার কোড যা আমি সামনে আসতে পারলাম।

// a, b, and c in the code below are all points

function distance(a, b)
{
    var dx = a.x - b.x;
    var dy = a.y - b.y;
    return Math.sqrt(dx*dx + dy*dy);
}

function Segment(a, b)
{
    var ab = {
        x: b.x - a.x,
        y: b.y - a.y
    };
    var length = distance(a, b);

    function cross(c) {
        return ab.x * (c.y-a.y) - ab.y * (c.x-a.x);
    };

    this.distanceFrom = function(c) {
        return Math.min(distance(a,c),
                        distance(b,c),
                        Math.abs(cross(c) / length));
    };
}

1
এই কোডটিতে একটি বাগ রয়েছে। রেখাটির নিকটে অবস্থিত একটি বিন্দু যেখানে বিভাগটি অবস্থিত, কিন্তু বিভাগটির এক প্রান্তের খুব দূরে, সেগমেন্টের কাছাকাছি থাকার জন্য ভুলভাবে বিচার করা হবে।
গ্রুমড্রিগ

আকর্ষণীয়, আমি পরবর্তী সময় আমি এই কোডবেজে আপনার দৃ confirm়তা নিশ্চিত করার জন্য কাজ করে যাচ্ছি into ভকভগক.
এলি কোর্টরাইট 3

1

উপরের ফাংশনটি উল্লম্ব লাইনে কাজ করছে না। এখানে একটি ফাংশন যা ভাল কাজ করছে! পয়েন্ট পি 1, পি 2 সহ লাইন। এবং চেকপয়েন্টটি পি;

public float DistanceOfPointToLine2(PointF p1, PointF p2, PointF p)
{
  //          (y1-y2)x + (x2-x1)y + (x1y2-x2y1)
  //d(P,L) = --------------------------------
  //         sqrt( (x2-x1)pow2 + (y2-y1)pow2 )

  double ch = (p1.Y - p2.Y) * p.X + (p2.X - p1.X) * p.Y + (p1.X * p2.Y - p2.X * p1.Y);
  double del = Math.Sqrt(Math.Pow(p2.X - p1.X, 2) + Math.Pow(p2.Y - p1.Y, 2));
  double d = ch / del;
  return (float)d;
}

প্রশ্নের উত্তর দেয় না। এটি কেবল রেখাগুলির জন্য কাজ করে (মহাশূন্যে সীমিত আকারে প্রসারিত) লাইন বিভাগগুলি নয় (যার সীমাবদ্ধ দৈর্ঘ্য রয়েছে)।
ত্রিনিদাদ

"উপরের ফাংশন" একটি দ্ব্যর্থহীন রেফারেন্স। (আমাকে বিরক্ত করে কারণ মাঝে মাঝে এই উত্তরটি আমার উত্তরের নীচে প্রদর্শিত হয়))
রেনিপেট

1

এখানে সি ++ উত্তর হিসাবে একই জিনিস তবে প্যাসকেলে পোর্ট করা হয়েছে। পয়েন্ট প্যারামিটারের ক্রমটি আমার কোড অনুসারে পরিবর্তিত হয়েছে তবে একই জিনিস।

function Dot(const p1, p2: PointF): double;
begin
  Result := p1.x * p2.x + p1.y * p2.y;
end;
function SubPoint(const p1, p2: PointF): PointF;
begin
  result.x := p1.x - p2.x;
  result.y := p1.y - p2.y;
end;

function ShortestDistance2(const p,v,w : PointF) : double;
var
  l2,t : double;
  projection,tt: PointF;
begin
  // Return minimum distance between line segment vw and point p
  //l2 := length_squared(v, w);  // i.e. |w-v|^2 -  avoid a sqrt
  l2 := Distance(v,w);
  l2 := MPower(l2,2);
  if (l2 = 0.0) then begin
    result:= Distance(p, v);   // v == w case
    exit;
  end;
  // Consider the line extending the segment, parameterized as v + t (w - v).
  // We find projection of point p onto the line.
  // It falls where t = [(p-v) . (w-v)] / |w-v|^2
  t := Dot(SubPoint(p,v),SubPoint(w,v)) / l2;
  if (t < 0.0) then begin
    result := Distance(p, v);       // Beyond the 'v' end of the segment
    exit;
  end
  else if (t > 1.0) then begin
    result := Distance(p, w);  // Beyond the 'w' end of the segment
    exit;
  end;
  //projection := v + t * (w - v);  // Projection falls on the segment
  tt.x := v.x + t * (w.x - v.x);
  tt.y := v.y + t * (w.y - v.y);
  result := Distance(p, tt);
end;

এই উত্তরটির সাথে বেশ কয়েকটি সমস্যা রয়েছে: পয়েন্টএফ টাইপটি ঘোষিত হয় না (এটি কিছু পাস্কাল বাস্তবায়নের ক্ষেত্রে স্ট্যান্ডার্ড টাইপ)। এটি সম্ভবত একটি রেকর্ড এক্স, ওয়াই: ডাবল; শেষ; ২. দূরত্ব এবং এমপিওয়ারের কার্যগুলি ঘোষণা করা হয় না এবং তারা কী করে তার কোনও ব্যাখ্যা নেই (আমরা অনুমান করতে পারি, হ্যাঁ)। ৩. ভেরিয়েবল প্রজেকশন ঘোষিত তবে কখনও ব্যবহৃত হয় না। সামগ্রিকভাবে এটি একটি বরং খারাপ উত্তর করে।
dummzeuch
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.