Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.03.28;
Скачать: CL | DM;

Вниз

Как вращать строку с центром посредине строки?   Найти похожие ветки 

 
DAndrew   (2003-11-19 08:56) [0]

Как вращать строку с центром вращения посредине строки, а не в верхне-левом углу?
Вариант - рисовать текст на битмапе, а затем его вращать на заданный угол приводит к резким искажениям шрифта. Применение алгоритма антиалиазинга к битмапу сглаживает прорисовку, но резко тормозит систему.
Пожалуйста, практический пример или ссылку на подобный алгоритм!
Заранее благодарен!
Андрей!


 
default ©   (2003-11-19 09:11) [1]

через уравнения концентрических окружностей?


 
DAndrew   (2003-11-19 09:34) [2]

А как конкретно?
Приведите, пожалуйста, практический пример или отправьте мне его по почте. Как удобно.
Спасибо!


 
nstur   (2003-11-19 10:00) [3]

Ребята, вопрос интереный, поделитесь для всех.


 
default ©   (2003-11-19 10:02) [4]

символы текста тоже должны вращаться?


 
default ©   (2003-11-19 10:03) [5]

всмысле вокруг своей оси, если за ось принять их центр


 
DAndrew   (2003-11-19 10:31) [6]

всмысле вокруг своей оси, если за ось принять их центр
Да, например, если за центр принять центральный (или приходящийся на него) символ строки (если только это не пробел). А вращать неободимо всю строку! Попеременно в разные стороны (принимая поочередно положительные и отрицательные значения угла поворота строки).
И все же может кто-либо привести практический пример, а не теорию?
Спасибо!


 
default ©   (2003-11-19 10:36) [7]

точно?то есть, например, в какой-то момент буква "ф" может стать перевёрнутой?


 
DAndrew   (2003-11-19 11:17) [8]

Да не совсем, ну вот, например возьмем строку:

Это строка для вращения

И в ней за центр поворота следует взять ее середину, например центр вращения где-то в сисмволе "д" (а символ это будет конкретно или нет - это уже дело случая!)
Теперь понятен смысл вопроса?
Спасибо!


 
default ©   (2003-11-19 11:21) [9]

DAndrew   (19.11.03 11:17) [8]
так и не ответил на вопрос, ну ладно


 
DAndrew   (2003-11-19 11:41) [10]

default - например, в какой-то момент буква "ф" может стать перевёрнутой?
Нет, угол поворота не должен превышать диапазона "-40" градусов и "40" градусов.
Теперь я ответил на Ваш вопрос?
Спасибо!


 
MBo ©   (2003-11-19 12:23) [11]

Делаешь шрифт под углом
var
  LogFont: TLogFont;

with MyCanvas do begin
  Font.Name := "Arial";
  Font.Size := 24;
  Font.Style := [fsBold];
  GetObject(Font.Handle, @LogFont, SizeOf(LogFont));
  with LogFont do begin
    lfOrientation := 450;  {set to 45 degrees}
    lfEscapement := lfOrientation end;
  Font.Handle := CreateFontIndirect(LogFont);

и выводишь строку в рассчитаную позицию


 
DAndrew   (2003-11-19 12:27) [12]

MBo
Да, это все понятно, но как это практически "...и выводишь строку в рассчитаную позицию"?
Можете привести полный пример кода?
По-моему Ваша мысль - это все же прорисовка строки на битмапе и уже поворот его, а не собстенно строки. Или нет?
Спасибо!


 
MBo ©   (2003-11-19 13:02) [13]

>Ваша мысль - это все же прорисовка строки на битмапе и уже
поворот его
нет. Это именно вывод строки штатными средствами GDI (с сохранением антиалиасинга)


procedure TForm1.Button6Click(Sender: TObject);
var
 LogFont: TLogFont;
 s:string;
 w,h,x,y:Integer;
begin
with Canvas do begin
 Font.Name := "Arial";
 Font.Size := 24;
 GetObject(Font.Handle, SizeOf(LogFont),@LogFont);
 with LogFont do begin
   lfOrientation := 300;
   lfEscapement := lfOrientation;
 end;
 Font.Handle := CreateFontIndirect(LogFont);
end;
s:="0123456789----9876543210";
Canvas.Ellipse(195,195,205,205);
w:=Canvas.TextWidth(s);
h:=Canvas.TextHeight(s);
X:=200-Round(cos(Pi/6)*w+h*sin(Pi/6)) div 2;
Y:=200-Round(-sin(Pi/6)*w+h*cos(Pi/6)) div 2;
Canvas.TextOut(X,Y,s);
Canvas.Ellipse(200-5,200-5,200+5,200+5);
end;


 
_Zergey   (2003-11-19 13:35) [14]

function AngleTextRect(DC:HDC;const AText:string;Left,Top:integer;
Angle:single;Alignment:TAlignment):TRect;
var
i,mw:integer;
Sz:TSize;
ARect:TRect;
Pt:array of TPoint;
begin
if Length(AText)=0 then Result:=Bounds(Left,Top,0,0) else
with TStringList.Create do
try
 Text:=AText;
 SetLength(Pt,(Count shl 2)+1);
 mw:=0;
 Int64(Pt[0]):=0;
 for i:=0 to Count-1 do
 begin
  GetTextExtentPoint(DC,PChar(Strings[i]),Length(Strings[i]),Sz);
  mw:=Max(mw,Sz.cx);
  Pt[i+1].x:=Sz.cx;
  Pt[i+1].y:=Pt[i].y+Sz.cy
 end;
 Objects[0]:=TObject(Pt[Count].y shr 1);
 for i:=Count downto 1 do
 with Sz do
 begin
  ARect.Left:=0;
  ARect.Top:=Pt[i-1].y;
  ARect.BottomRight:=Pt[i];
  case Alignment of
   taCenter:OffsetRect(ARect,((mw-WidthOf(ARect)) shr 1)+Left,Top);
   taRightJustify:OffsetRect(ARect,mw-WidthOf(ARect)+Left,Top)
   else OffsetRect(ARect,Left,Top)
  end;
  cy:=i shl 2;
  with ARect do
  begin
   Pt[cy]:=BottomRight;
   Dec(cy);
   Pt[cy]:=Point(Left,Bottom);
   Dec(cy);
   Pt[cy]:=Point(Right,Top);
   Dec(cy);
   Pt[cy]:=TopLeft
  end
 end;
 Pt[0]:=Point((mw shr 1)+Left,Integer(Objects[0])+Top);
 RotatePt(Pt,Angle);
 Result:=PolygonRect(Pt)
finally
 Free
end
end;

procedure DrawRotatedText(DC:HDC;const Text:string;const ARect:TRect;
Angle:single;Alignment:TAlignment;Layout:TTextLayout);
begin
with AngleTextRect(DC,Text,ARect.Left,ARect.Top,-Angle,Alignment) do
begin
 case Alignment of
  taCenter:Left:=(WidthOf(ARect) shr 1)+ARect.Left;
  taRightJustify:Left:=ARect.Right-((Right-Left) shr 1)
  else Left:=((Right-Left) shr 1)+ARect.Left
 end;
 case Layout of
  tlCenter:Top:=(HeightOf(ARect) shr 1)+ARect.Top;
  tlBottom:Top:=ARect.Bottom-((Bottom-Top) shr 1)
  else Top:=((Bottom-Top) shr 1)+ARect.Top
 end;
 AngledTextOut(DC,Text,Left,Top,-Angle,Alignment)
end
end;


 
DAndrew   (2003-11-19 13:43) [15]

MBo!
Спасибо, но это все же не то...
Опять таки поворот строки происходит с центром от первого символа строки ("неподвижная точка"), а мне необходимо, чтобы (по Вашему коду) левая и правая части строки (от Вашего эллипса в центре 0123456789----о-----9876543210) вращались в противоположные стороны при задаваемых значениях угла от "-45" до "45" градусов! А центром вращения ("неподвижной точкой") оставалась точка, которую Вы обозначили, как эллипс послредине строки.
Я несколько дополнил Ваш код, посмотрите, может так Вам станет понятнее проблема. Кликая на кнопке строка должна "вертеться", подобно "детским качелям":

...................................
var
 Form1: TForm1;
 FAngle: Integer;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
 FAngle:= 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
     var LogFont: TLogFont;
         s: string;
         w, h, x, y:Integer;
begin
 inc(FAngle, 200);
 with Image1.Canvas do begin
      Font.Name := "Arial";
      Font.Size := 24;
      GetObject(Font.Handle, SizeOf(LogFont), @LogFont);

      with LogFont do begin
           lfOrientation := FAngle;
           lfEscapement := lfOrientation; end;

      Font.Handle := CreateFontIndirect(LogFont);
 end;

 s:="0123456789----9876543210";
 Image1.Canvas.Ellipse(195, 195, 205, 205);
 w:= Image1.Canvas.TextWidth (s);
 h:= Image1.Canvas.TextHeight(s);
 X:= 200 - Round( cos(Pi/6)*w + h*sin(Pi/6)) div 2;
 Y:= 200 - Round(-sin(Pi/6)*w + h*cos(Pi/6)) div 2;
 Image1.Canvas.TextOut(X, Y, s);
 Image1.Canvas.Ellipse(200 - 5, 200 - 5, 200 + 5, 200 + 5);
end;

end.

Спасибо!

Андрей!


 
DAndrew   (2003-11-19 13:45) [16]

_Zergey

Спасибо - проверю и напишу, что получилось!

Андрей!


 
DAndrew   (2003-11-19 14:00) [17]

_Zergey!

Коды не компилируются, компилятор выдает следующие ошибки (возможно их больше):

[Error] Unit1.pas(78): Undeclared identifier: "RotatePt"
[Error] Unit1.pas(79): Undeclared identifier: "PolygonRect"
[Error] Unit1.pas(100): Undeclared identifier: "AngledTextOut"
[Fatal Error] Project1.dpr(5): Could not compile used unit "Unit1.pas"


Функция WidthOf из библиотеки RXLib? А можно обойти эту библиотеку, у меня строки с символами юникодов?
Как и какими другими функциями можно заменить некоторые из примененных в Вашем коде.
Вы можете привести полные коды, если Вам удобно отошлите мне их на мой email! И еще вопрос могут ли данные коды поворота строки работать с юникодными символами, это очень важно для меня. Так как строка у меня содержит символы юникодов.

Спасибо!

Андрей!


 
MBo ©   (2003-11-19 14:11) [18]

>Спасибо, но это все же не то...
Это именно то, что требовалось, просто кое-кто не обдумал приведенный код.
Pi/6  - это не случайная абстракция, а 30 градусов (соответствует 300 в LogFont).


 
default ©   (2003-11-19 14:22) [19]

DAndrew   (19.11.03 13:43) [15]
inc(FAngle, 200);
этим ты меняешь точку относительно которой под заданным углом выводится строка...
см MBo ©   (19.11.03 14:11) [18]


 
default ©   (2003-11-19 14:24) [20]

MBo ©   (19.11.03 13:02) [13]
"Font.Handle := CreateFontIndirect(LogFont);"
а ресурс здесь не теряется?Font.Handle не надо сохранять?


 
DAndrew   (2003-11-19 14:37) [21]

И все же, Мастера!
Как решить практически проблему?

Есть еще мнения?

Можно по email.

Андрей!


 
default ©   (2003-11-19 14:43) [22]

DAndrew   (19.11.03 14:37) [21]
млин, FAngle ты даже нигде не используешь, а хочешь чтобы что-то менялось...
"Как решить практически проблему?"
MBo тебе всё написал, осталось только обобщить, непонял код?нарисуй на бумажке - поймёшь


 
MBo ©   (2003-11-19 14:54) [23]

>default ©   (19.11.03 14:24) [20]
>а ресурс здесь не теряется?Font.Handle не надо сохранять?
Насколько я помню, при назначении нового дескриптора граф. объекту (TFont.SetHandle) старый освобождается с пом. FreeResource.
Можно оттрассировать.


 
default ©   (2003-11-19 15:08) [24]

MBo ©   (19.11.03 14:54) [23]
да действительно


 
DAndrew   (2003-11-19 15:46) [25]

MBo!

Извините, сразу не понял Вашего кода.
Против часовой стрелки у меня получилось, подскажите, что необходимо скорректировать в Вашем коде (MBo © (19.11.03 13:02) [13]), чтобы вращение строки было по часовой стрелке.

Спасибо!

Андрей!


 
default ©   (2003-11-19 15:51) [26]

DAndrew   (19.11.03 15:46) [25]
а говоришь понял...угол в обратном направлении менять


 
DAndrew   (2003-11-19 16:11) [27]

Пробовал задать переменную FAngle с отрицательным значением - неполучается.
Что-то еще необходимо изменить?

Андрей.


 
default ©   (2003-11-19 16:13) [28]

код покажи


 
default ©   (2003-11-19 16:21) [29]

сделай себе класс...с таймером, через определённый интервал времени у тебя будет надпись вертеться, скорость тем самым сможешь задавать(вращения), крутить по часовой, против часовой, угловой размер одного поворота надписи...


 
DAndrew   (2003-11-19 16:37) [30]

Ниже код (пробую вращать строку по часовой стрелке - не получается):

procedure TForm1.Button1Click(Sender: TObject);
     var LogFont: TLogFont;
         s: string;
         w, h, X, Y:Integer;
         FGrad: Extended;
begin
 Inc(FAngle, 20);
 FAngle:= -FAngle;

 s:= "My name Andrew";

 with Image1.Canvas do begin
      Font.Name := "Times New Roman";
      Font.Size := 36;
      Font.Style:= [fsBold];

      GetObject(Font.Handle, SizeOf(LogFont), @LogFont);

      with LogFont do begin
           lfOrientation := FAngle*10;
           lfEscapement := lfOrientation; end;

      Font.Handle:= CreateFontIndirect(LogFont);

      Ellipse(195, 195, 205, 205);
      w:= TextWidth (s);
      h:= TextHeight(s);

      Brush.Color:= clInfoBk; //clWhite;
      FillRect(ClientRect);
      Brush.Style:= bsClear;

      FGrad:= DegToRad(FAngle);
      X:= 200 - Round( cos(FGrad)*w + h*sin(FGrad)) div 2;
      Y:= 200 - Round(-sin(FGrad)*w + h*cos(FGrad)) div 2;

      TextOut(X, Y, s);
      Ellipse(200 - 5, 200 - 5, 200 + 5, 200 + 5); end;

 Image1.Invalidate;
end;

Что не так?

Андрей!


 
DAndrew   (2003-11-19 16:38) [31]

Ниже код (пробую вращать строку по часовой стрелке - не получается):

procedure TForm1.Button1Click(Sender: TObject);
     var LogFont: TLogFont;
         s: string;
         w, h, X, Y:Integer;
         FGrad: Extended;
begin
 Inc(FAngle, 20);
 FAngle:= -FAngle;

 s:= "My name Andrew";

 with Image1.Canvas do begin
      Font.Name := "Times New Roman";
      Font.Size := 36;
      Font.Style:= [fsBold];

      GetObject(Font.Handle, SizeOf(LogFont), @LogFont);

      with LogFont do begin
           lfOrientation := FAngle*10;
           lfEscapement := lfOrientation; end;

      Font.Handle:= CreateFontIndirect(LogFont);

      Ellipse(195, 195, 205, 205);
      w:= TextWidth (s);
      h:= TextHeight(s);

      Brush.Color:= clInfoBk; //clWhite;
      FillRect(ClientRect);
      Brush.Style:= bsClear;

      FGrad:= DegToRad(FAngle);
      X:= 200 - Round( cos(FGrad)*w + h*sin(FGrad)) div 2;
      Y:= 200 - Round(-sin(FGrad)*w + h*cos(FGrad)) div 2;

      TextOut(X, Y, s);
      Ellipse(200 - 5, 200 - 5, 200 + 5, 200 + 5); end;

 Image1.Invalidate;
end;

Что не так?

Андрей!


 
default ©   (2003-11-19 18:41) [32]

" Inc(FAngle, 20);
FAngle:= -FAngle;" --> Dec(FAngle, 20)


 
DAndrew   (2003-11-19 19:40) [33]

default, MBo!

Спасибо!
Всем спасибо за общение!

Андрей!


 
_Zergey   (2003-11-22 10:48) [34]

Не обратил внимания исправляюсь :)
На основе того чем делюсь был мной написан компонент на основе TLabel с возможностью вращения текста на любой угол с работающим при етом AutoSize!

procedure AngledTextOut(DC:HDC;const Text:string;cx,cy:integer;Angle:single;
Alignment:TAlignment);
var
Pt:array of TPoint;
ps:PChar;
psa:TList;
i:integer;
s:string;
begin
SetString(s,PChar(Text),Length(Text));
psa:=TList.Create;
try
 TextToStrArr(psa,PChar(s));
 SetLength(Pt,psa.Count+1);
 Int64(Pt[0]):=0;
 for i:=1 to psa.Count do
 begin
  ps:=psa[i-1];
  GetTextExtentPoint(DC,ps,StrLen(ps),TSize(Pt[i]));
  with Pt[0] do
  begin
   x:=Max(x,Pt[i].x);
   ps:=Pointer(Pt[i].y);
   Pt[i].y:=y;
   Inc(y,Integer(ps))
  end
 end;
 for i:=1 to psa.Count do
 with Pt[i] do
 case Alignment of
  taCenter:x:=(Pt[0].x-x) shr 1;
  taRightJustify:x:=Pt[0].x-x
  else x:=0
 end;
 with Pt[0] do
 begin
  x:=x shr 1;
  y:=y shr 1
 end;
 RotatePt(Pt,Angle);
 with Pt[0] do OffsetPt(Pt,cx-x,cy-y);
 for i:=1 to psa.Count do
 begin
  ps:=psa[i-1];
  with Pt[i] do TextOut(DC,x,y,ps,StrLen(ps))
 end
finally
 psa.Free
end
end;

procedure RotatePt(var Pt:array of TPoint;Angle:single);
var
i,x0,y0,xb:integer;
s,c:extended;
begin
if Length(Pt)>0 then
begin
 x0:=Pt[0].x;
 y0:=Pt[0].y;
 SinCos(Angle,s,c);
 for i:=1 to High(Pt) do
 with Pt[i] do
 begin
  Dec(x,x0);
  Dec(y,y0);
  xb:=x;
  x:=Round((xb*c)-(y*s))+x0;
  y:=Round((y*c)+(xb*s))+y0
 end
end
end;

function PolygonRect(const Pt:array of TPoint):TRect;
var
i:integer;
begin
Result.TopLeft:=Pt[0];
Result.BottomRight:=Pt[0];
if High(Pt)>0 then
for i:=1 to High(Pt) do
with Result,Pt[i] do
begin
 if x<Left then Left:=x else
 if x>Right then Right:=x;
 if y<Top then Top:=y else
 if y>Bottom then Bottom:=y
end
end;


 
_Zergey   (2003-11-22 10:52) [35]

и есче :)...

procedure TextToStrArr(List:TList;Text:PChar);
var
p:PChar;
begin
List.Clear;
p:=Text;
while p^<>#0 do
if p^=#13 then
begin
 p^:=#0;
 List.Add(Text);
 Inc(p);
 Inc(p);
 Text:=p
end
else Inc(p);
List.Add(Text)
end;


 
_Zergey   (2003-11-22 11:00) [36]

воощет я полагал почемута, что названия процедур грят сами за себя и написать их код, как 2б обнулить!



Страницы: 1 вся ветка

Текущий архив: 2004.03.28;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.035 c
1-1078592161
Rustamus
2004-03-06 19:56
2004.03.28
Поиск


3-1077869603
Dina
2004-02-27 11:13
2004.03.28
Как узнать где создан файл dbf в Paradox, dBase и какой версии?


8-1069253810
Agent[007]
2003-11-19 17:56
2004.03.28
glBegin(GL_QUADS)...glEnd;


3-1077179718
SerKom
2004-02-19 11:35
2004.03.28
В чем разница в TSQL "AS" от "="?


1-1078410219
a.t.k.
2004-03-04 17:23
2004.03.28
Встороить ComboBox в ячейку StringGrid