円弧を描く線の縁に黒細線を着けるには?、

解決


はんにゃ  URL  2011-01-26 07:42:47  No: 72249  IP: [192.*.*.*]

環境WindowsXP,VC6.0 C++ MFC
で描画をしています。下記のコードです
  
CPen whitePen(PS_SOLID, 4+m_kks/30, RGB(255, 255, 255)); 
        // start color Kolam pattern line
memDC.SelectObject(&whitePen);
memDC.Arc( kx1, ky1, kx2, ky2, x3, y3, x4, y4);  //円弧を描く,

で描画しています  URLのアニメ参照
この線は単に色の付いた帯ですが、この帯の縁に黒線を着けたい、
2本の黒細線の間に色の帯があるように、描きたいのですが、簡単な関数はあるでしょうか?

編集 削除
仲澤@失業者  2011-01-26 09:49:28  No: 72250  IP: [192.*.*.*]

ありません。
全て単色線で描画してください。
高度なやりかたとしてLineDDA()を使う方法も考えられますが、
まぁ、やめといたほうが良いでしょう。

編集 削除
はんにゃ  URL  2011-01-26 18:12:04  No: 72251  IP: [192.*.*.*]

お返事ありがとう
描画線の表現がまずかったかもしれません。
輪郭線のある太い色つき線を描きたい。
上の事例は輪郭線のない太い色着き線です。
如何でしょうか

編集 削除
ホウジョウウサギ  2011-01-27 09:35:07  No: 72252  IP: [192.*.*.*]

単に  同じ個所に
色1で太い線→色2で少しだけ細い線
という順で描画すればいいように思うのですが
そういう話ではないということなのでしょうか??

編集 削除
仲澤@失業者  2011-01-27 09:57:25  No: 72253  IP: [192.*.*.*]

描画する線の属性はHPEN又はCPenの作成時にきめますが、
これらに輪郭という概念はありません。
輪郭を定義しようとする人が自分で書いてください。

編集 削除
HT  2011-01-27 10:18:44  No: 72254  IP: [192.*.*.*]

太さを変えて同じ場所に描くと、
円などではどうしても輪郭の太さに誤差が出てしまい、
また、"太い点線"などのジオメトリックペンなどでうまく輪郭にならないので、
自分は8方向にずらした位置に同じ太さで色1の線を描いてから、
当初の位置に色2の線を描くようにしています。

memDC.SelectObject(&blackPen);
for (int y = -1; y <= 1; y++) { //1は輪郭の太さ
  for (int x = -1; x <= 1; x++) {
    memDC.Arc(kx1 + x, ky1 + y, kx2 + x, ky2 + y, x3 + x, y3 + y, x4 + x, y4 + y);
  }
}

memDC.SelectObject(&whitePen);
memDC.Arc(kx1, ky1, kx2, ky2, x3, y3, x4, y4);

編集 削除
はんにゃ  URL  2011-01-27 15:44:44  No: 72255  IP: [192.*.*.*]

ます  既存の関数に輪郭という属性はないという助言ありがとうございました
そこで  黒太線を描いて  後でそれより細い色着きの線を”内側”に重ねがきするという手法  なるほどです。
それでも  微妙な調整が必要なわけですね
やってみます。たくさんの
memDC.SelectObject(&whitePen);
memDC.Arc(kx1, ky1, kx2, ky2, x3, y3, x4, y4);があるので
別途二重描画の関数を立てる必要があるかもしてません。

編集 削除
gak  2011-01-27 18:05:36  No: 72256  IP: [192.*.*.*]

> 2本の黒細線の間に色の帯があるように、描きたいのですが、簡単な関数はあるでしょうか?
簡単な関数は知らないが、自分でヤるならこんな手も有る。

void draw(CDC& dc, const CRect& r, DWORD penstyle, DWORD width, COLORREF color) {
    const int id = dc.SaveDC();
    dc.SetPolyFillMode(WINDING);
    dc.SetArcDirection(AD_CLOCKWISE);

    LOGBRUSH lb;
    lb.lbStyle = BS_SOLID;
    CPen draft(penstyle | PS_GEOMETRIC | PS_ENDCAP_ROUND | PS_JOIN_ROUND, width, &lb);
    dc.SelectObject(&draft);

    dc.BeginPath();
    // sample1. 円弧
    dc.Arc(r, CPoint(r.left, (r.top + r.bottom) * 3 / 4), CPoint(r.right, (r.top + r.bottom) * 3 / 4));
    // sample2. 左下 -> 中央 -> 右下 と繋がる連続線
    dc.MoveTo(r.left, r.bottom);
    dc.LineTo(r.CenterPoint());
    dc.LineTo(r.BottomRight());
    dc.EndPath();
    dc.WidenPath();
#if 0    // こっちだと曲線、折線等を描画時に縁が旨く描けねぇ…
    CPen frame(PS_SOLID, 1, RGB(0x00, 0x00, 0x00));
    CBrush fill(color);
    dc.SelectObject(&frame);
    dc.SelectObject(&fill);
    dc.StrokeAndFillPath();
#else
    CRgn rgn;
    rgn.CreateFromPath(&dc);
    CBrush frame(RGB(0x00, 0x00, 0x00));
    CBrush fill(color);
    dc.FillRgn(&rgn, &fill);
    dc.FrameRgn(&rgn, &frame, 1, 1);
#endif
    dc.RestoreDC(id);
}

void xxxxxxxxxxxxxxxx() {
    draw(dc, rect, PS_SOLID, 20, RGB(0xff, 0x80, 0x00));
}

編集 削除
はんにゃ  URL  2011-01-28 07:28:38  No: 72257  IP: [192.*.*.*]

ありがとうございました。
結構難しそう
void draw(CDC& dc, const CRect& r, DWORD penstyle, DWORD width, COLORREF color) {
}
の各引数から  どうするか  考えています。  

void xxxxxxxxxxxxxxxx() {
    draw(dc, rect, PS_SOLID, 20, RGB(0xff, 0x80, 0x00));
}
が見本ですね。やってみます

#if 0    // こっちだと曲線、折線等を描画時に縁が旨く描けねぇ…
とあるのですが、小生の課題は円弧ですので曲線、弧線です
でこの  変数0は  どこで指定するのでしょうか?  else に行くようにするんには?

編集 削除
gak  2011-01-28 17:55:12  No: 72258  IP: [192.*.*.*]

#if 0  // 0 == false
    :
#else
    :
#endif

は、

if (0) { // 0 == false
    :
}
else {
    :
}

と仕組みは同じ。分岐判断が行われる時期(コンパイル時か実行時か)が違うだけ。
> #if 0    // こっちだと曲線、折線等を描画時に縁が旨く描けねぇ…
> #else
要するに、↑部分はコメントアウトされたコードと同じ様な扱い。
ググると詳しい情報が見つかるかと。

>    dc.BeginPath();
>        :
>    dc.EndPath();
「:」の部分にはんにゃさんがやりたい処理を書けば良い。dc.SetArcDirection(AD_CLOCKWISE)  は必要に応じて変更/削除すれば良い。
後は基本的に触る必要は無いかもしれないがケースバイケースで。

編集 削除
はんにゃ  URL  2011-02-21 20:33:31  No: 72259  IP: [192.*.*.*]

お世話になりました。
初めに太目のPen
  CPen edgePen(PS_SOLID, 7+m_kks/30, RGB(0, 0, 0)); // comBox4: edge-line black color Kolam pattern

            memDC.SelectObject(&edgePen); 
描いておき、
その後  例えば  すこし狭いペンの
    CPen whitePen(PS_SOLID, 4+m_kks/30, RGB(255, 255, 255)); // start color Kolam pattern
で      
          memDC.SelectObject(&whitePen);

描くと  実行上  中心がずれなくて  初めの黒地がのこり  Edge縁のようになりました  ありがとうございました

編集 削除