testbed1

Download: testbed1.zip.

The project testbed1 is a graphics environment for developing procedures for drawing electronic symbols.

The onPaint of the class CChildView is used to position various symbols, drawn with routines from symbols.cpp.

The basic circuit components were designed to be centered in a rectangle 5 units wide and 2.5 units high. The current source is enclosed in a circle 5 units in diameter. The midpoint of each symbol is the origin.

Symbols are then scaled by a factor of ten and translated to their final position. Adding a rotational degree of freedom should be easy.

I think a rotational variable such that 1 is -90 degrees, 2 is 180 degrees, and 3 is +90 degrees makes sense. I expect a -90 degree rotation to be the most common. A rotation of 0.5 would be -45 degrees, 1.5 is -135 degrees, and so forth. Question: should 2.5 be +135 degrees and 3.5 45 degrees or should 2.5 be 45 degrees and 3.5 be 135 degees? I am inclined toward the latter, using numbers above 2 to measure counterclockwize from the positive x-axis.

ChildView.cpp


void CChildView::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	
	// Handle isotropic mapping
	CRect win;
	GetClientRect(&win);
	dc.SetMapMode(MM_ISOTROPIC);
	dc.SetWindowExt(480,-320);
	dc.SetViewportExt(win.Width(),win.Height());
	dc.SetViewportOrg(win.Width()/2,win.Height()/2);
	// Draw a reference grid
	CPen pen (PS_SOLID,0,RGB(220,220,255));
	CPen *oldpen = (CPen *) dc.SelectObject(&pen);
	int u = 4*point2::resolution;
	for (int i=-4; i<=4; i++) {
		int v = i*point2::resolution;
		dc.MoveTo(-u,v);
		dc.LineTo(u,v);
		dc.MoveTo(v,-u);
		dc.LineTo(v,u);
	}
	dc.SelectObject(oldpen);
	int w = 5;
	dc.Ellipse(-w,-w,w,w);

	void drawResistor(CDC &dc, Vec2 &loc);
	void drawImpedance(CDC &dc, Vec2 &loc);
	void drawCapacitor(CDC &dc, Vec2 &loc);
	void drawInductor(CDC &dc, Vec2 &loc);
	void drawCurrentSource(CDC &dc, Vec2 &loc);
	drawResistor(dc,Vec2(-1,1));
	drawInductor(dc,Vec2(-2,-1));
	drawCapacitor(dc,Vec2(-2,-1));
	drawImpedance(dc,Vec2(1,1));
	drawResistor(dc,Vec2(-2,-1));
	drawInductor(dc,Vec2(-2,0));
	drawCapacitor(dc,Vec2(2,0));
	drawCurrentSource(dc,Vec2(0,0));
}


symbols.cpp


//
#include "stdafx.h"
#include "point2.h"


void drawResistor(CDC &dc, Vec2 &loc)
{
	const double w = 2.5/7.0;
	const double y = 1.25;
	Vec2 pts[] = { Vec2(-7*w,0), Vec2(-6*w,0), Vec2(-5*w,y), Vec2(-3*w,-y), Vec2(-w,y), Vec2(w,-y), 
		Vec2(3*w,y), Vec2(5*w,-y), Vec2(6*w,0), Vec2(7*w,0) };
	int npts = sizeof(pts)/sizeof(pts[0]);
	int i;
	CPoint *cpts = new CPoint[npts];
	for (i=0; i<npts; i++) {
		pts[i].scale(0.1).translate(loc);
		point2::convert(pts[i],cpts[i]);
	}
	/*
	CRect rect(0,0,2,2);
	dc.DPtoLP(&rect);
	int width = rect.Width();
	CString str;
	if (width<2) width = 2;
	str.Format("pen width %d",rect.Width());
	dc.TextOut(50,-50,str);
	*/
	int color = RGB(0,0,255);
	CPen pen(PS_SOLID,2,color);
	CPen *oldpen = (CPen *) dc.SelectObject(&pen);
	dc.Polyline(cpts,npts);
	dc.SelectObject(oldpen);
	delete [] cpts;
}

void drawImpedance(CDC &dc, Vec2 &loc)
{
	Vec2 pts[] = { Vec2(-2.5,1.25), Vec2(2.5,-1.25) };
	int i, npts;
	npts = sizeof(pts)/sizeof(pts[0]);
	CPoint *cpts = new CPoint[npts];
	for (i=0; i<npts; i++) {
		pts[i].scale(0.1).translate(loc);
		point2::convert(pts[i],cpts[i]);
	}
	CBrush brush(RGB(220,220,255));
	CBrush *oldbrush = (CBrush *) dc.SelectObject(&brush);
	CRect rect(cpts[0],cpts[1]);
	dc.Rectangle(rect);
	dc.SelectObject(oldbrush);
	int mode = dc.GetBkMode();
	dc.SetBkMode(TRANSPARENT);
	CString str("Z");
	dc.DrawText(str,rect,DT_CENTER | DT_SINGLELINE | DT_VCENTER);
	dc.SetBkMode(mode);
	delete [] cpts;
}

void drawCapacitor(CDC &dc, Vec2 &loc)
{
	Vec2 pts[] = { Vec2(-2.5,0), Vec2(-0.5,0), Vec2(0.5,0), Vec2(2.5,0), Vec2(-0.5,-1.5), Vec2(-0.5,1.5),
			Vec2(1,-1.5), Vec2(0.5,-1.5), Vec2(0.5,-0.5), Vec2(0.5,0.0), Vec2(0.5,0.5),
			Vec2(0.5,1.5), Vec2(1.0,1.5) };
	int npts = sizeof(pts)/sizeof(pts[0]);
	int i;
	CPoint *cpts = new CPoint[npts];
	for (i=0; i<npts; i++) {
		pts[i].scale(0.1).translate(loc);
		point2::convert(pts[i],cpts[i]);
	}
	int color = RGB(0,255,0);
	CPen pen(PS_SOLID,2,color);
	CPen *oldpen = (CPen *) dc.SelectObject(&pen);
	for (i=0; i<6; i+=2) {
		dc.MoveTo(cpts[i]); dc.LineTo(cpts[i+1]);
	}
	dc.PolyBezier(cpts+6,7);
	dc.SelectObject(oldpen);
	delete [] cpts;
}

void drawInductor(CDC &dc, Vec2 &loc)
{
	Vec2 spts[] = { Vec2(-2.75,0), Vec2(-2.75,2), Vec2(-1.25,2), Vec2(-1.25,0), 
		Vec2(-1.25,-1), Vec2(-1.75,-1) };
	int i, j, k, npts;
	npts = sizeof(spts)/sizeof(spts[0]);
	Vec2 *pts = new Vec2[5*npts];
	k = 0;
	for (j=0; j<5; j++) {
		Vec2 t(j,0.0);
		for (i=0; i<npts; i++) {
			pts[k++]=spts[i]+t;
		}
	}
	npts = 4*npts+4;
	double w = pts[npts-1][0];
	w = 0.25/w;
	CPoint *cpts = new CPoint[npts];
	for (i=0; i<npts; i++) {
		pts[i].scale(w).translate(loc);
		point2::convert(pts[i],cpts[i]);
	}
	int color = RGB(255,0,0);
	CPen pen(PS_SOLID,2,color);
	CPen *oldpen = (CPen *) dc.SelectObject(&pen);
	dc.PolyBezier(cpts,npts);
	dc.SelectObject(oldpen);
	delete [] pts;
	delete [] cpts;
}

void drawCurrentSource(CDC &dc, Vec2 &loc)
{
	Vec2 pts[] = { Vec2(-2.5,-2.5), Vec2(2.5,2.5), Vec2(0,-2), Vec2(0,2), Vec2(-0.7,0),
		Vec2(0,0.8), Vec2(0.7,0)};
	int i, npts;
	npts = sizeof(pts)/sizeof(pts[0]);
	CPoint *cpts = new CPoint[npts];
	for (i=0; i<npts; i++) {
		pts[i].scale(0.1).translate(loc);
		point2::convert(pts[i],cpts[i]);
	}
	CPen pen(PS_SOLID,2,RGB(0,0,0));
	CPen *oldpen = (CPen *) dc.SelectObject(&pen);
	CRect rect(cpts[0],cpts[1]);
	dc.Ellipse(&rect);
	dc.MoveTo(cpts[2]); dc.LineTo(cpts[3]);
	CBrush brush(RGB(0,0,0));
	CBrush *oldbrush = (CBrush *) dc.SelectObject(&brush);
	dc.Polygon(cpts+3,npts-3);
	dc.SelectObject(oldbrush);
	dc.SelectObject(oldpen);
	delete [] cpts;
}


Results

The superimposed symbols on the lower-left checks that the symbols all start and stop at the same place and are approximately the same height.




Maintained by John Loomis, updated Thu Feb 01 21:52:42 2007