Jump to content

MullinRJ

Member
  • Posts

    2,017
  • Joined

  • Last visited

Posts posted by MullinRJ

  1. Well that sucks. This means that the getsymlocation always returns in mm, while getorigin returns in the units from the settings.

    GetSymLoc(); returns document units, at least in every program I've ever written. I'm not sure why your numbers are off by a scale factor of 10. I think you'll need to look elsewhere.

    Some functions do return mm only. For those that do, you can scale them to document units with:

    Val_In_Doc_Units := Val_In_mm * GetPrefReal(152) / 25.4;

    Raymond

  2. One more thing before I quit for the night, LObject points to the last object in the drawing, which is always on the topmost layer. LActLayer points to the last object on the active layer, which is what I'm guessing you want.

    If you are working in a one layer drawing or you are on the top layer, they will be equivalent. But what are the odds that will work to your favor?

    Raymond

  3. Michael,

    ???Your loop counters are going from 1 to 0; i.e., not looping. The variables QtyRecordFormats and QtyFields are uninitialized, so they are 0 at the start of the loop.

    Change QtyRecordFormats to NumRecords(OldSym)

    and QtyFields to NumFields(CurrentRecord)

    But I have a question about your record copying, aren't all the records being duplicated with hDuplicate()? And they stay intact after SetHDef(). What are you trying to copy that isn't already there?

    Raymond

  4. Hi Joel,

    ???It could be referring to line 1 of any $Included file. Sometimes, the second or third error message will clue you in to which file is the offending one.

    ???The "{ Error: Expected = }" message usually occurs in CONST declarations. I know this is not much help, but without knowing more, I can't offer more.

    ???Lastly, do you have a blank line at the end of every included file? This prevents statements in adjacent files from running together inadvertently.

    HTH,

    Raymond

  5. Is there a logic to this method that I'm not seeing?

    I sort of expected there to be a Symbol3D() function that was a 3D analog of Symbol().

    Michael,

    ???The logic comes from reading the VS Export file and seeing how NV deals with it. For modularity and ease of use, I define my own functions to fill in the VS gaps.

    ???In this case:

    procedure Symbol3D(Sym :String; X, Y, Z, Xr, Yr, Zr :Real);
    { Place a 3D Symbol in the drawing at the specified 3D point and rotations. }
    Begin
    Symbol (Sym, 0, 0, #0);
    ResetOrientation3D;
    SetRot3D (LNewObj, Xr, Yr, Zr, 0, 0, 0);
    Move3DObj (LNewObj, X, Y, Z);
    End;		{ Symbol3D }

    ???This is off the top of my head, so please test it thoroughly before using it. Setting the flip state is a little more involved. I'll leave that to you for extra credit.

    HTH,

    Raymond

  6. Second post first...

    Scaling mode is ObjVar 101, see appendix.

    Scale factors are ObjVars are 102, 103, 104.

    Symbol position - GetSymLoc3D(H, X, Y, Z);

    Symbol rotation - Boo := Get3DOrientation(H, Xrot, Yrot, Zrot, SymFlip);

    No, there is a replace function. - SetHDef(). This one is hard to remember, and is NOT found in the Symbol section. Knowing it exists helps to find it, but not by much.

    Raymond

  7. Symbol('3D Sym', 0, 0, #0);

    ResetOrientation3D;

    Rotate3D(#11, #22, #55);???{ final rotation }

    Move3D(1, 2, 3);???{ final insertion point location }

    Hi Michael,

    ???You could, of course, make a procedure to do this if you were going to place a lot of symbols. This assumes the User Origin is unmoved.

    Raymond

  8. Yes, if you enter the symbol from the drawing (CMD=[) or (Right Click>Edit) and have "Show other objects while in editing modes" preference turned on. If you enter the symbol from the Resource Browser, then No, you cannot see anything adjacent to it.

    Raymond

  9. Mr. G.,

    ???Here's some Platinum for your collection. Moments ago I was politely informed by an astute Finnish colleague of mine of a significantly more elegant way of divining the answer to your previous CW/CCW query. ObjectVariableBoolean - 652. It knows which way it goes. Thank you Mr. S.

    ???As I told him, I stop looking for answers to problems when I get my first working solution. I think that code snippet predated VW9, the version ObjectVariables arrived on the scene. More than a decade ago? I guess I can step into the 21st century now.

    ???Use it in good health.

    Raymond (part time dinosaur)

  10. Dear Mr. G.,

    ???To find out what is meant by "turns right more than left", you must look at each turn individually and weigh the combined result. It's a pretty simple calculation carried to a meticulous end if the number of vertices is large. Be glad for your little computer friend.

    ???Every three points has an implied angle in the middle. "Simply" add up all the angles and compare the value to 0. If the answer is positive, you have turned left more than right, conversely if it is not positive you have not gone CCW. I'll leave it to you to decide which way you went if the answer is zero.

    ???There may be more elegant means afoot, but for me, the first thing that works is most often adequate. I've used the following routine with all the polys I've run into. It sums up all the left and right hand turns and spits out a verdict, but it does assume the poly to be non-intersecting (and >2 points).

    ???GetPolyPnt is one of my generic routines that returns only the point requested. If you are only processing polygons, then swap it out for GetPolyPt(), otherwise use the other one.

    Happy cipherin',

    Raymond

    function IsCCW(H :Handle) :Boolean;
    { A goodly while ago - R. Mullin }
    { Return TRUE if Poly H is CCW, FALSE if it is CW. }
    Var
    I, VCnt :Integer;
    ang :Real;
    P1, P2, P3 :Vector;
    
    
    function Turn(P1, P2, P3 :Vector) :Real;
    { Return the angle between vectors P2-P1 and P3-P2. CCW is Positive. }
    Var
    	P, V1, V2 :Vector;
    Begin
    	V1 := P2-P1;
    	V2 := P3-P2;
    	P := CrossProduct(V1, V2);
    	If (P.z<0) then Turn := -AngBVec(V1, V2)
    	else Turn := AngBVec(V1, V2);
    End;		{ Turn }
    
    
    Begin
    VCnt := GetVertNum(H);
    GetPolyPnt(H, 1, P1);
    GetPolyPnt(H, 2, P2);
    GetPolyPnt(H, 3, P3);
    ang := Turn(P1, P2, P3);
    
    I := 3;
    while (I		I := I + 1;
    	P1 := P2;
    	P2 := P3;
    	GetPolyPnt(H, I, P3);
    	ang := ang + Turn(P1, P2, P3);
    end;		{ while }
    
    P1 := P2;
    P2 := P3;
    GetPolyPnt(H, 1, P3);
    ang := ang + Turn(P1, P2, P3);
    
    IsCCW := ang > 0;
    End;		{ IsCCW }
    

  11. Here's a more modular approach. The function "FSPIOinWall" can be used any time you need a handle to Selected PIOs in a wall. The code that follows just shows an example of a way to use it, as in counting windows. This is a very simple example as it will only count windows in one wall.

    Now I'm waiting for Pat to find that single function call that makes these gyrations completely unnecessary.

    HTH,

    Raymond

    PROCEDURE CountWindowsInWall;
    { 8 July 2012 - RJMullin }
    { Count the number of selected Windows in a wall. }
    { Watch the Message Window for the answer. }
    VAR
    H :Handle;
    I :Integer;
    
    
    function FSPIOinWall(H :Handle) :Handle;
    { Return a handle to the First Selected PIO in a Wall. }
    { If handle H is not a WALL, return NIL. }
    Var
    	PIOHand :Handle;
    
    	function SelectedPIO(H :Handle) :Boolean;
    	{ Find 1st handle then quit looking. }
    	Begin
    		if Selected(H) & (GetTypeN(H) = 86) then
    			PIOHand := H;
    		SelectedPIO := PIOHand <> nil;	{ quit when true }
    	End;		{ SelectedPIO }
    
    Begin		{ FSPIOinWall }
    	PIOHand := nil;
    	if (GetTypeN(H) = 68) then begin	{ It's a WALL }
    		H := FIn3D(H);			{ first object in the WALL }
    		ForEachObjectInList(SelectedPIO, 2, 0, H);
    	end;		{ if }
    	FSPIOinWall := PIOHand;
    End;		{ FSPIOinWall }
    
    
    BEGIN
    ClrMessage;
    H := FSActLayer;
    if (H <> nil) then begin
    	I := 0;		{ Window counter }
    	if (GetTypeN(H) = 68) then begin	{ it's a WALL }
    		H := FSPIOinWall(H);		{ *** This is the call *** }
    
    		{ ?? THE REST IS FLUFF ?? }
    		while (H <> nil) do begin
    			if (GetName(GetRecord(H, NumRecords(H))) = 'Window') then
    				I := I + 1;
    			H := NextSObj(H);
    		end;		{ while }
    
    		if (I = 1) then 
    			message ('There is ', I, ' selected window in this wall.')
    		else message ('There are ', I, ' selected windows in this wall.');
    	end
    	else message('This is not a wall.');
    	SysBeep;
    end;		{ if }
    
    END;
    Run(CountWindowsInWall);
    

  12. Bill,

    ???When in doubt, tunnel in. Not being well versed on the WALL object, I wrote this script to quickly dig around inside. There are probably better ways to get what you want, but this style of script always yields interesting results.

    ???There are two statements that do the heavy lifting. One is FIn3D() which almost always cracks the door on container objects, and the WALL is definitely a container. The second one is GetName(GetRecord(H, NumRecords(H))) which returns the name of the PIO being pointed to by handle H. PIOs always have a record attached and the last record (which could be the only record) has the same name as the PIO.

    ???To speed things up, get rid of the WAIT(1) statement and the "ELSE ..." on the previous line. There is no need to do anything to objects that don't meet your search criteria.

    ???So, the bottom line, is get a handle to a Wall, look inside for selected PIOs, operate.

    HTH,

    Raymond

    PS - Hold that thought. I'll be right back...

    PROCEDURE WalkThroughWalls;
    { 8 July 2012 - RJMullin }
    { Poke around inside a WALL (type = 68) and see what pops up. }
    { Watch the Message Window for the anatomy of the wall. }
    VAR
    H :Handle;
    I, ObjType :Integer;
    BEGIN
    H := FSActlayer;
    ObjType := GetTypeN(H);
    if (ObjType = 68) then begin		{ It's a WALL }
    	I := 0;				{ counter for objs in the WALL }
    	H := FIn3D(H);			{ first object in the WALL }
    	while (H <> nil) do begin
    		I := I + 1;
    		ObjType := GetTypeN(H);
    		if (ObjType = 86) & Selected(H) then begin	{ it's a PIO & it's selected }
    			message(I, '  ', GetName(GetRecord(H, NumRecords(H))))
    
    			{*** Do your stuff here ***}
    
    		end
    		else message(I, '   Object Type = ', ObjType);
    		wait(1);
    		H := nextobj(H);			{ get next object in WALL }
    	end;		{ while }
    end
    else message('Object Type = ', ObjType);
    sysbeep;
    END;
    Run(WalkThroughWalls);
    

  13. It sounds like your symbols are set up as World Based, not Page Based. With a symbol selected, the OIP will tell you which mode it is. To change it, Edit the symbol in the Resource Browser and when the Edit Symbol Dialog appears, choose the last radio button "Symbol Options". You can toggle it there. Of course, all instances will change. One symbol definition cannot be both at the same time.

    Raymond

×
×
  • Create New...